Procesos y llamadas al sistema

Aprende cómo un sistema operativo comparte una CPU entre muchos programas en ejecución y, al mismo tiempo, mantiene cada programa en su propio espacio. Verás qué es un proceso y cómo pasa entre los estados de ejecución, listo y bloqueado; crearás procesos en C con fork, ejecutarás nuevos programas con exec y recogerás sus resultados con wait, hasta llegar a un intérprete de comandos sencillo con redirección y tuberías. Después examinarás su funcionamiento interno: el modo usuario y el modo núcleo, cómo una llamada al sistema accede al núcleo mediante una trampa, en qué se diferencian las excepciones y las interrupciones, y cómo la ejecución directa limitada y la interrupción del temporizador permiten al sistema operativo recuperar la CPU y pasar de un proceso a otro.

IntermedioUnidad 1 de 9 del curso Curso de Sistemas operativos

Lo que aprenderás

  1. Describe las funciones principales del sistema operativo y la historia y las ideas de diseño que explican por qué comparte y protege la máquina como lo hace.
    • Describe las funciones principales de un sistema operativo
      Explica cómo el sistema operativo convierte el hardware en recursos más fáciles de usar, compartidos y protegidos para los programas.
    • Explica cómo la multiprogramación y el tiempo compartido dieron forma al sistema operativo
      Sigue los pasos desde el procesamiento por lotes hasta la multiprogramación y el tiempo compartido, descubre por qué cada paso necesitó nuevas protecciones y compara las principales formas de organizar un núcleo.
  2. Explica qué es un proceso, qué información registra el sistema operativo sobre cada uno y cómo los procesos pasan entre los estados de ejecución, listo y bloqueado.
    • Explica qué es un proceso y qué información mantiene sobre él el sistema operativo
      Distingue un programa de un proceso, describe el estado de la máquina y el espacio de direcciones de un proceso, y explica cómo el SO crea un proceso y lleva su seguimiento.
    • Sigue las transiciones de estado de un proceso
      Usa los estados de ejecución, listo y bloqueado y sus transiciones para seguir cómo los procesos comparten una CPU, y reconoce los estados adicionales que muestran los sistemas reales.
  3. Usa la API de procesos de Unix en C para crear procesos hijos, ejecutar nuevos programas en ellos, recoger sus resultados, terminarlos y combinar estas llamadas en un intérprete de comandos sencillo.
    • Crea un proceso hijo con fork
      Llama a fork, distingue al padre del hijo por su valor de retorno y predice qué ve e imprime cada proceso.
    • Ejecuta otro programa con exec
      Sustituye el programa de un proceso con exec, pasa los argumentos correctamente y explica por qué Unix separa la creación de un proceso de la carga de un programa.
    • Espera a los procesos hijos, consulta su estado de salida y termina procesos
      Termina procesos con exit y señales, recoge el resultado de un hijo con wait y waitpid, decodifica su estado y evita que los procesos zombis y huérfanos causen problemas.
    • Construye un intérprete de comandos sencillo con fork, exec, wait y redirección
      Combina las llamadas de proceso en un bucle de intérprete de comandos que ejecuta comandos, redirige la entrada y la salida, conecta comandos con tuberías y ejecuta trabajos en segundo plano.
  4. Explica cómo el hardware separa el código privilegiado del núcleo de los programas de usuario y cómo los programas cruzan esa frontera de forma controlada mediante llamadas al sistema, excepciones e interrupciones.
    • Distingue el modo usuario del modo núcleo
      Explica qué permite cada modo de la CPU, qué operaciones son privilegiadas y qué ocurre cuando un programa excede los límites de su modo.
    • Explica paso a paso cómo funciona una llamada al sistema
      Sigue una llamada al sistema desde la función envoltorio de biblioteca hasta el núcleo mediante una trampa y de vuelta, e interpreta su valor de retorno y sus errores.
    • Distingue las trampas, las excepciones y las interrupciones
      Clasifica los eventos que hacen que la CPU entre en el núcleo, explica cómo funciona la tabla de manejadores del núcleo y predice qué ocurre después de cada tipo de evento.
  5. Explica cómo el sistema operativo ejecuta programas directamente en la CPU a toda velocidad sin perder el control y cómo cambia la CPU de un proceso a otro.
    • Explica la ejecución directa limitada
      Explica los dos problemas de ejecutar programas directamente en la CPU y cómo los resuelven el modo usuario, las trampas y la interrupción del temporizador, paso a paso desde el arranque hasta la terminación del proceso.
    • Sigue un cambio de contexto y estima su coste
      Sigue cada paso del cambio de la CPU de un proceso a otro, distingue un cambio de contexto de un cambio de modo y estima cuánto tiempo de CPU cuesta el cambio.

Guía de estudio de Procesos y llamadas al sistema

5 capítulos

1

Explica qué hace un sistema operativo

El SO ofrece a los programas normales formas útiles de realizar cálculos, almacenar datos y usar dispositivos mientras comparten la máquina de forma segura. Sus responsabilidades explican por qué una aplicación de escritorio no necesita su propio controlador de disco y por qué un programa defectuoso no debería detenerlo todo. Sigue el paso de los computadores que ejecutaban un trabajo a la vez a los sistemas interactivos y luego compara cómo los distintos diseños de núcleo dividen el trabajo privilegiado.

1.1 Describe las funciones principales de un sistema operativo

Un navegador, un compilador y un reproductor de música pueden avanzar en un mismo computador. Cada uno necesita tiempo de CPU, memoria y acceso a dispositivos. El sistema operativo (SO) proporciona esos recursos mediante servicios que los programas pueden usar sin controlar toda la máquina.

Proporcionar recursos útiles a los programas

La virtualización convierte un recurso físico en un recurso virtual cómodo de usar. La virtualización de la CPU permite que muchos procesos se comporten como si cada uno tuviera su propio procesador. El SO ejecuta cada uno durante un tiempo y conserva su estado entre turnos. La virtualización de la memoria da a cada proceso su propio espacio de direcciones: las direcciones que pueden usar sus instrucciones.

Una abstracción oculta detalles detrás de una interfaz útil. Un archivo es una abstracción de bytes almacenados. Un programa puede llamar a write sin saber si esos bytes van a una unidad SSD o a una unidad de red. Una llamada al sistema proporciona una forma controlada de solicitar un servicio del núcleo. El trabajo específico del dispositivo queda detrás de la interfaz.

Compartir recursos y proteger programas

Como gestor de recursos, el SO decide quién obtiene tiempo de CPU, memoria y servicio de los dispositivos. Intenta mantener el hardware en uso y, al mismo tiempo, dar a los programas un acceso razonable. Compartir también requiere protección: un programa no debe sobrescribir la memoria privada de otro ni desactivar el temporizador para retener la CPU.

El hardware ayuda a imponer este límite. Las instrucciones de las aplicaciones se ejecutan en modo usuario con permisos limitados. El código del núcleo se ejecuta con los privilegios necesarios para gestionar la máquina. Un temporizador puede interrumpir un programa aunque este nunca solicite nada al SO.

Para una computadora portátil que descarga un archivo mientras compila código, sigue tres tareas distintas:

  1. El dispositivo de red informa de la llegada de datos. El núcleo los pone a disposición del proceso que realiza la descarga.
  2. El SO comparte el tiempo de CPU entre el navegador, el compilador y otros procesos listos.
  3. El compilador solicita operaciones de archivo para almacenar su salida. Su código no controla directamente el controlador de almacenamiento.
Separar el núcleo de la interfaz

El núcleo es la parte central privilegiada. El intérprete de comandos, el escritorio y la mayoría de las bibliotecas del sistema se ejecutan como programas normales, incluso cuando se distribuyen con el SO. Cerrar una ventana del escritorio no elimina el núcleo. Un servidor sin interfaz gráfica sigue necesitando gestión de procesos, protección de memoria y servicios de dispositivos.

En una CPU lógica, el código de usuario y el código del núcleo se turnan. Mientras el compilador ejecuta instrucciones normales de usuario, el núcleo no se está ejecutando también en esa CPU. Las llamadas al sistema, las excepciones y las interrupciones de hardware le devuelven el control.

Elegir cómo y después a quién

Un mecanismo proporciona una operación; una política elige cómo usarla. Guardar los registros de un proceso y restaurar los de otro es un mecanismo. Elegir qué proceso listo obtiene el siguiente turno es una política. Mantenerlos separados permite al SO cambiar sus decisiones de planificación sin reemplazar el mecanismo de cambio.

El diseño de un SO equilibra abstracciones útiles, rendimiento, protección, fiabilidad, seguridad y consumo de energía. El tiempo de CPU y la memoria adicionales dedicados a la gestión son sobrecarga. En toda la materia aparecen tres temas recurrentes: la virtualización, la concurrencia (actividades en curso al mismo tiempo) y la persistencia, que conserva los datos almacenados más allá de la vida de un programa o de una pérdida de alimentación.

Puntos clave

  • La virtualización da a los programas vistas cómodas del hardware compartido.
  • Las abstracciones, como los archivos, ocultan los detalles de los dispositivos detrás de operaciones útiles.
  • El núcleo es privilegiado; el intérprete de comandos y el escritorio son programas normales.
  • Un mecanismo proporciona una operación; una política elige cuándo o para quién se usa.
  • La protección y una sobrecarga baja son objetivos del diseño de un SO.

1.2 Explica cómo la multiprogramación y el tiempo compartido dieron forma al sistema operativo

Los sistemas operativos evolucionaron a medida que los computadores pasaron de ejecutar trabajos aislados a atender muchas actividades a la vez. Cada cambio resolvió un problema práctico: hardware inactivo, interacción lenta o fallos que se propagaban entre programas.

De los lotes al trabajo solapado

En el procesamiento por lotes, los trabajos enviados se ejecutan uno tras otro sin interacción con quien los envió. Los primeros programas de soporte ayudaban principalmente a cargar trabajos y realizar operaciones comunes de entrada/salida. Si el trabajo actual tenía que esperar a un dispositivo, la CPU podía quedar inactiva.

La multiprogramación mantiene varios trabajos en memoria. Cuando uno se bloquea por una operación de entrada/salida, otro puede realizar cálculos. Supón que un trabajo calcula repetidamente durante 20 ms y espera 80 ms a una operación de entrada/salida de disco. Por sí solo, su utilización de CPU es 20 / 100 = 20 %. Con dos trabajos así y un solapamiento adecuado, los cálculos útiles pueden ocupar el 40 % del tiempo transcurrido. La demora del dispositivo no se ha reducido; se ha ocupado tiempo de CPU que, de otro modo, habría quedado inactivo.

La ganancia depende de que haya trabajo listo. Añadir trabajos no puede elevar la utilización de la CPU por encima del 100 %, y los trabajos que esperan al mismo dispositivo aún pueden encontrarse con un cuello de botella. Varios trabajos en memoria también necesitan protección: uno no debe sobrescribir a otro ni dañar los datos del propio SO.

Hacer que la interacción sea rápida

El tiempo compartido da a los procesos turnos cortos en la CPU. Una terminal o un escritorio puede responder mientras otros programas siguen trabajando. Esperar a que termine un trabajo por lotes antes de atender la pulsación de una tecla de otro usuario daría una experiencia muy distinta.

Método de comparticiónQué se divideEjemplo
Tiempo compartidoUso de un recurso en intervalos sucesivosTurnos de CPU
Compartición espacialCapacidad que distintos usuarios poseen a la vezRegiones de memoria o espacio en disco

La concurrencia significa que varias actividades están en curso durante el mismo periodo. Sus instrucciones pueden intercalarse en una CPU lógica. El paralelismo significa que las instrucciones se ejecutan realmente de forma simultánea en distintos recursos de procesamiento. La multiprogramación no requiere hardware paralelo.

Situar los servicios dentro o fuera del núcleo
DiseñoDónde se ejecuta la mayoría de los serviciosContrapartida principal
Núcleo monolíticoLos sistemas de archivos, controladores y funciones de red se ejecutan en modo núcleoLas llamadas directas son eficientes; un error en un controlador puede dañar el núcleo
MicronúcleoUn núcleo privilegiado pequeño da soporte a procesos de servicio en modo usuarioEl aislamiento de los servicios ayuda a contener fallos; la comunicación añade trabajo
Núcleo híbridoCombina elementos de ambos enfoquesEl límite exacto entre servicios depende del diseño

Linux es monolítico y puede cargar módulos del núcleo. MINIX 3, QNX y seL4 ilustran diseños de micronúcleo. Windows NT y XNU de Apple suelen describirse como diseños híbridos. A menudo puede reiniciarse un controlador en modo usuario después de un fallo, mientras que un controlador privilegiado tiene acceso que puede hacer que su fallo afecte a todo el sistema.

Los primeros sistemas para computadores personales, como MS-DOS y el Mac OS clásico, carecían de la protección de memoria de los procesos que se espera hoy. Los sistemas modernos combinan las reglas del SO con la aplicación de esas reglas mediante hardware. Los turnos cortos de CPU por sí solos no impedirían que un programa modificara la memoria de otro; la compartición y la protección resuelven partes distintas del problema.

Puntos clave

  • La multiprogramación ocupa las esperas de entrada/salida con los cálculos de otro trabajo.
  • El tiempo compartido permite el uso interactivo con turnos cortos de CPU.
  • El trabajo concurrente puede intercalarse en una CPU; el trabajo paralelo se ejecuta simultáneamente.
  • El tiempo compartido divide los turnos; la compartición espacial divide la capacidad.
  • La organización del núcleo sopesa las llamadas directas entre servicios frente a un mayor aislamiento de estos.
  • Varios trabajos residentes requieren protección de memoria y de privilegios.
2

Describe los procesos y los estados por los que pasan

Un archivo de programa es solo el punto de partida. Para ejecutarlo, el SO construye y supervisa un proceso activo con memoria, registros, descriptores abiertos y un lugar en la lista de procesos. Aprende a interpretar ese estado y luego sigue a un par de procesos mientras el trabajo de CPU se solapa con las esperas de dispositivos. La diferencia entre esperar una CPU y esperar un evento explica qué proceso puede elegir el planificador.

2.1 Explica qué es un proceso y qué información mantiene sobre él el sistema operativo

Un ejecutable en disco puede iniciarse repetidamente. Cada ejecución necesita su propio estado cambiante para que una instancia pueda pausarse, reanudarse o fallar de forma independiente. Esa instancia activa es un proceso.

Identificar la instancia en ejecución

Un programa consiste en instrucciones y datos estáticos almacenados. Un proceso combina un programa con su memoria, registros de CPU y estado de entrada/salida actuales. Tres intérpretes de comandos pueden ejecutar el mismo archivo ejecutable mientras mantienen distintas variables, directorios actuales e historiales.

El contador de programa (PC) identifica la siguiente instrucción. El puntero de pila localiza la pila activa. Los registros generales contienen valores intermedios. Cuando un proceso deja de ejecutarse, debe conservarse suficiente estado para que continúe en la instrucción correcta con los valores correctos.

Interpretar la organización del espacio de direcciones

El espacio de direcciones de un proceso es la memoria que pueden direccionar sus instrucciones. Una organización didáctica habitual sitúa el código y los datos estáticos hacia las direcciones más bajas, un montículo por encima y una pila hacia las direcciones más altas. El montículo da soporte a los objetos asignados dinámicamente; la pila da soporte a las llamadas a funciones y al estado local. En esta organización, el montículo crece hacia direcciones más altas y la pila hacia direcciones más bajas. Las organizaciones reales dependen del sistema y las implementaciones de malloc pueden obtener memoria de más de una manera.

Dos procesos pueden imprimir la misma dirección virtual para una variable y, aun así, contener valores distintos en ella. Las direcciones virtuales pertenecen a la vista de memoria de un proceso. Que los números de dirección coincidan no implica que exista almacenamiento escribible compartido.

Iniciar un programa

Para iniciar una nueva imagen de programa, el SO prepara estos elementos:

  1. Su código y datos ejecutables, cuyas partes se cargan cuando se necesitan en los sistemas modernos.
  2. Una pila de usuario inicial e información de arranque, incluidas las cadenas de argumentos y el vector de argumentos que usa el entorno de ejecución para llamar a main.
  3. Memoria para la asignación dinámica y el estado inicial de los registros.
  4. Un entorno de entrada/salida, incluidos los descriptores de archivo heredados.
  5. Un punto de entrada donde comienza el código de inicio del programa.

En Unix, los descriptores de archivo son enteros pequeños que identifican recursos de entrada/salida abiertos. Por convenio del intérprete de comandos, 0 es la entrada estándar, 1 la salida estándar y 2 el error estándar. A menudo están conectados a una terminal. Un proceso puede heredar descriptores adicionales; los tres números conocidos no son un límite ni una garantía de que todos los procesos los tengan siempre abiertos.

Examinar el registro del núcleo

El bloque de control de proceso (PCB) registra la información que el núcleo necesita para gestionar un proceso: PID, estado, contexto de ejecución guardado, información de memoria, descriptores abiertos, padre, propietario, directorio actual e información de contabilidad. Linux usa task_struct; xv6 usa struct proc. Una tabla o lista de procesos organiza estos registros.

Mientras un proceso se ejecuta, sus registros activos están en la CPU. Al entrar en el núcleo, sus registros de usuario se guardan en su pila del núcleo; un cambio de contexto también conserva el contexto de ejecución del núcleo. El PCB no es una copia actualizada continuamente de cada registro de usuario.

Por ejemplo, un listado de ps en Linux podría contener 8240 8200 S bash y 8291 8240 R ps. El segundo proceso tiene el PID 8291 y el PID de su padre es 8240, por lo que es hijo del intérprete de comandos. R abarca tanto los procesos en ejecución como los listos. Un PID identifica a un proceso activo dentro de su espacio de nombres de PID, pero después de liberar sus recursos ese número puede reutilizarse.

Puntos clave

  • Un proceso es una instancia de un programa con estado de memoria, registros y entrada/salida.
  • Las direcciones virtuales idénticas en procesos distintos pueden identificar datos diferentes.
  • El PCB contiene el registro de gestión del núcleo, no los registros activos de la CPU actualizados continuamente.
  • Los descriptores de archivo se heredan; 0, 1 y 2 tienen funciones establecidas por convenio.
  • Los PID pueden reutilizarse después de que un proceso haya terminado y se hayan liberado sus recursos.

2.2 Sigue las transiciones de estado de un proceso

Un proceso puede existir sin estar ejecutando una instrucción en ese momento. Su estado indica al SO si puede usar una CPU o si primero debe esperar otra cosa. Esta distinción explica por qué un computador ocupado puede tener muchos procesos, pero solo unos pocos ejecutándose en un instante dado.

Determinar qué necesita el proceso
EstadoSignificadoEjemplo
En ejecuciónEjecuta instrucciones en una CPUUn compilador que genera instrucciones
ListoPuede ejecutarse, espera tiempo de CPUUn cálculo cuyo turno acaba de terminar
BloqueadoEspera un evento antes de poder continuarUna lectura de terminal que espera entrada

Un proceso bloqueado no consume tiempo de CPU mientras está bloqueado. Su dispositivo o evento puede seguir avanzando. Un proceso listo ya tiene lo que necesita salvo una CPU.

Las transiciones básicas son listo → en ejecución cuando se selecciona, en ejecución → listo cuando se retira de la CPU, en ejecución → bloqueado cuando debe esperar y bloqueado → listo cuando ocurre su evento. La finalización del evento permite que un proceso pueda ejecutarse; no le concede la CPU inmediatamente. Elegir entre los procesos que pueden ejecutarse es tarea del planificador.

Seguir el trabajo solapado

Usa una CPU lógica e ignora la sobrecarga del cambio. El proceso A calcula durante 2 ms, espera 3 ms a una operación de entrada/salida de disco y luego calcula durante 1 ms. El proceso B necesita 4 ms de tiempo de CPU. A empieza primero.

IntervaloCPUEstado de AEstado de B
0–2 msAEn ejecuciónListo
2–5 msBBloqueadoEn ejecución
5–6 msBListoEn ejecución
6–7 msAEn ejecuciónTerminado

A los 2 ms, A inicia la operación de entrada/salida y se bloquea. B calcula mientras trabaja el disco. A los 5 ms, termina la operación de entrada/salida de A, pero el SO deja que B complete su cuarto milisegundo de CPU antes de ejecutar A. Esta es una decisión de política, no una transición adicional directa de bloqueado a en ejecución.

El trabajo total de CPU es 2 + 1 + 4 = 7 ms y ambos terminan después de 7 ms. Si A se ejecutara hasta terminar antes de que comenzara B, el tiempo transcurrido sería 2 + 3 + 1 + 4 = 10 ms. La utilización de la CPU sería 7 / 10 = 70 %, porque ningún otro trabajo ocuparía la espera de entrada/salida.

Interpretar los estados en un sistema real

En Linux, ps combina los estados en ejecución y listo como R. Muestra el sueño interrumpible como S, el sueño ininterrumpible, a menudo por entrada/salida, como D, un proceso detenido como T y un proceso terminado pero no recolectado como Z. Un proceso detenido no está simplemente esperando la finalización de una operación normal de entrada/salida. Un zombi ha terminado de ejecutarse y solo conserva el registro necesario para comunicar su resultado.

Un proceso nuevo también pasa por la creación antes de estar listo. En un sistema con cuatro CPU lógicas, como máximo cuatro procesos de un solo hilo pueden ejecutarse simultáneamente. Las colas de procesos listos organizan el trabajo que puede ejecutarse; las listas de bloqueados registran los eventos que necesitan los procesos. Un cambio de contexto conserva el estado de ejecución de un proceso y restaura el de otro cuando el SO cambia el proceso que se ejecuta.

Puntos clave

  • Listo significa que espera una CPU; bloqueado significa que espera un evento.
  • La finalización de una operación de entrada/salida pasa un proceso de bloqueado a listo.
  • Solapar las esperas de dispositivos con trabajo útil de CPU puede acortar el tiempo total transcurrido.
  • Linux indica los estados listo y en ejecución con el mismo código, R.
  • Un zombi ha terminado, pero aún no ha sido recolectado.
  • El número de CPU lógicas limita la ejecución simultánea de procesos de un solo hilo.
3

Crea y controla procesos con fork, exec y wait

La interfaz de procesos de Unix separa la creación de un hijo, la sustitución de su programa y la recogida de su resultado. Sigue qué cambia y qué conserva cada llamada, incluidas las variables privadas y el estado compartido de los archivos abiertos. Luego combina las llamadas para construir el comportamiento de un intérprete de comandos: comandos en primer plano, redirección, cadenas de tuberías y trabajos en segundo plano. Cada paso depende de saber qué proceso lo está ejecutando.

3.1 Crea un proceso hijo con fork

fork() crea un proceso hijo a partir del proceso padre que realiza la llamada. Ambos continúan inmediatamente después de la llamada, por lo que una ruta del código fuente da lugar a dos ejecuciones. El valor de retorno indica a cada proceso qué papel tiene.

Distinguir los tres resultados
pid_t rc = fork();
if (rc < 0) {
    perror("fork");
    exit(1);
} else if (rc == 0) {
    printf("child %ld\n", (long) getpid());
} else {
    printf("parent of %ld\n", (long) rc);
}

Usa <unistd.h> para fork y getpid, <stdio.h> para imprimir y <stdlib.h> para exit. Si la llamada tiene éxito, el padre recibe el PID positivo del hijo y el hijo recibe 0. Si falla, quien llama recibe -1, errno explica el error y no existe ningún hijo.

Si el PID del padre es 5000 y el del hijo es 5001, el padre imprime «parent of 5001» y el hijo imprime «child 5001». No se garantiza que ninguno de los dos se ejecute primero. getpid() devuelve el PID de quien realiza la llamada; getppid() devuelve el PID de su padre. El hijo no reinicia main ni repite las instrucciones anteriores a la bifurcación.

Seguir la memoria privada y la entrada/salida compartida

El padre y el hijo comienzan con el mismo contenido de memoria ordinaria en espacios de direcciones separados. Si x es 10 antes de la llamada y el hijo cambia su copia a 20, la copia del padre sigue siendo 10. Incluso la dirección impresa de x puede coincidir: esas direcciones virtuales iguales pertenecen a espacios de direcciones de procesos distintos.

La copia en escritura evita copiar todas las páginas de memoria de inmediato. El padre y el hijo comparten inicialmente páginas físicas protegidas contra escritura. Cuando uno escribe en una página privada, el núcleo prepara una copia privada antes de permitir la escritura. Esto conserva el comportamiento de memorias separadas y reduce el coste cuando un hijo llama pronto a exec.

Los descriptores de archivo se comportan de otra manera. Sus entradas copiadas hacen referencia a la misma descripción de archivo abierto subyacente, que incluye el desplazamiento actual dentro del archivo. Las lecturas secuenciales mediante un descriptor heredado hacen avanzar ese desplazamiento compartido. La tabla de descriptores se copia, pero el estado subyacente del archivo abierto en el núcleo puede seguir compartido.

Contar solo las bifurcaciones que alcanza un proceso

Si todas las llamadas tienen éxito, fork(); fork(); deja cuatro procesos: los dos procesos producidos por la primera llamada ejecutan la segunda. Un bucle de tres iteraciones que alcanzan todos los procesos deja 23=8 procesos, incluido el original. Una bifurcación dentro de una rama exclusiva del padre la alcanzan menos procesos, por lo que la duplicación repetida ya no describe todo el programa.

Vaciar deliberadamente el texto almacenado en búfer

printf puede dejar texto en un búfer del espacio de usuario. fork copia ese búfer junto con el resto de la memoria. Si la salida se redirige a un flujo con almacenamiento completo en búfer, el texto impreso antes de la bifurcación puede ser vaciado por ambos procesos al terminar normalmente.

Para printf("start\n"); fork();, la terminal habitual, que almacena la salida por líneas, vacía el texto al encontrar el salto de línea antes de la bifurcación. Un archivo al que se redirige la salida puede retenerlo y recibir dos copias. fflush(stdout) antes de fork() envía el texto pendiente una sola vez. El duplicado procede de los datos copiados en el búfer, no de ejecutar dos veces el printf anterior.

Puntos clave

  • fork() devuelve el PID del hijo en el padre, 0 en el hijo o -1 si falla.
  • Si la llamada tiene éxito, ambos procesos continúan justo después de fork().
  • Los cambios en la memoria privada ordinaria del hijo no modifican los valores del padre.
  • Los descriptores heredados pueden compartir una descripción de archivo abierto y su desplazamiento.
  • El número de procesos depende de cuáles alcanzan cada bifurcación.
  • Vacía la salida pendiente antes de una bifurcación cuando no se desee que se vacíe por duplicado.

3.2 Ejecuta otro programa con exec

Un proceso puede conservar su identidad mientras cambia el programa que ejecuta. La familia exec realiza esa sustitución. Combinarla con fork permite que un padre continúe su trabajo mientras un hijo pasa a ejecutar otro programa.

Sustituir la imagen y conservar el proceso

Una llamada a exec que tiene éxito sustituye el código, los datos estáticos, el montículo y la pila anteriores. El núcleo prepara los argumentos y el estado de entrada del nuevo programa y luego inicia su código de arranque. El lugar desde el que se hizo la llamada ya no existe, por lo que una llamada a exec que tiene éxito nunca retorna a él.

El PID, la relación con el padre y el directorio actual se conservan. Los descriptores abiertos se conservan, salvo los marcados para cierre al ejecutar exec. Las señales con un manejador instalado vuelven a su disposición predeterminada; las que se ignoran suelen seguir ignorándose. Las credenciales normalmente siguen siendo las mismas, pero los permisos set-user-ID o set-group-ID de un ejecutable pueden cambiar las credenciales efectivas cuando el sistema lo permite.

Operación¿Proceso nuevo?Efecto principal
fork()SíCrea un hijo con una copia del estado de ejecución
Exec con éxitoNoSustituye la imagen de programa del proceso que llama
Construir un vector de argumentos válido

Para ejecutar wc -l notes.txt, el hijo puede usar:

char *args[] = {"wc", "-l", "notes.txt", NULL};
execvp(args[0], args);
perror("execvp");
_exit(127);

Las cadenas son argumentos separados, no una sola línea de comandos combinada. Por convenio, args[0] identifica el programa. El NULL final es un puntero que marca el final del array; no es la cadena «NULL». Sin un terminador válido, la llamada puede leer más allá del array.

Las líneas posteriores a execvp gestionan el fallo. Si no se encuentra el programa, exec devuelve -1 y establece errno, por ejemplo en ENOENT. Después, _exit termina el hijo sin vaciar los búferes de salida de C heredados. Volver al bucle del intérprete de comandos después del fallo crearía accidentalmente otra ruta de ejecución del intérprete.

Interpretar el nombre de la variante

La v de execv significa que los argumentos llegan como un vector; las variantes l reciben una lista. Una variante p busca un nombre de programa en PATH. Una variante e proporciona un entorno explícito. La llamada al sistema subyacente de Linux es execve; la biblioteca proporciona las variantes más cómodas de usar.

execvp("wc", args) busca en PATH. execv("wc", args) trata «wc» como una ruta relativa en el directorio actual. Se puede usar una ruta absoluta como /usr/bin/wc donde esté instalado ese ejecutable. Exec no interpreta la sintaxis del intérprete de comandos: una cadena > en args es solo un argumento, salvo que un programa la interprete por sí mismo.

Usar el intervalo previo a la sustitución

En el ejemplo con el padre de PID 6000 y el hijo de PID 6001, el hijo pasa a ejecutar wc, pero conserva el PID 6001. Su padre puede esperar a ese PID. Antes de exec, el hijo puede redirigir descriptores, conectar una tubería o cambiar de directorio; el programa que lo sustituye hereda el entorno preparado.

Esta separación es fundamental para el intérprete de comandos de Unix. CreateProcess de Windows combina la creación y la carga del programa, mediante parámetros que configuran el nuevo proceso. POSIX también ofrece posix_spawn para una operación combinada.

Puntos clave

  • Exec sustituye una imagen de programa sin crear un proceso ni cambiar su PID.
  • Si exec tiene éxito, nunca retorna; las instrucciones posteriores gestionan el fallo.
  • Termina los vectores de argumentos con un puntero NULL.
  • Las variantes p buscan en PATH; una variante que solo acepta una ruta no lo hace.
  • Preparar los descriptores antes de exec permite que un programa sin modificar participe en redirecciones y tuberías.

3.3 Espera a los procesos hijos, consulta su estado de salida y termina procesos

Un padre necesita saber si un hijo ha terminado y cómo lo ha hecho. La terminación del proceso y la recogida del resultado son pasos separados: el hijo termina y luego su padre recolecta el registro que queda en el núcleo.

Terminar un proceso

Retornar de main o llamar a exit(status) termina la ejecución normal. exit vacía los búferes de salida de C y ejecuta los manejadores de salida registrados. _exit(status) termina sin esa liberación de recursos de la biblioteca, lo que es útil después de un exec fallido en un hijo creado mediante fork. Por convenio, 0 indica éxito y un valor distinto de cero indica fallo.

Una señal también puede terminar un proceso. SIGTERM solicita la terminación y puede ser gestionada por un manejador; SIGKILL no se puede capturar ni ignorar. SIGSTOP detiene la ejecución y tampoco se puede capturar ni ignorar; SIGCONT reanuda un proceso detenido. Una terminal normalmente envía SIGINT por Ctrl-C y SIGTSTP por Ctrl-Z al trabajo en primer plano. Una señal es una notificación de software a un proceso, no una interrupción de hardware.

Esperar un resultado

wait(&status) espera a un hijo y devuelve su PID. waitpid(pid, &status, 0) selecciona un PID positivo de un hijo concreto. Un hijo que ha terminado y no ha sido recolectado puede recogerse inmediatamente. En caso contrario, una espera bloqueante normal suspende al padre hasta que haya un resultado disponible que cumpla el criterio.

Con WNOHANG, waitpid devuelve 0 cuando existen hijos que cumplen el criterio, pero ninguno tiene un resultado listo. Un resultado positivo identifica al hijo recogido. Un resultado de -1 indica un error: ECHILD significa que no queda ningún hijo que cumpla el criterio; EINTR significa que un manejador de señales interrumpió la espera.

Decodificar el estado antes de usarlo
int status;
pid_t r;
do {
    r = waitpid(child, &status, 0);
} while (r == -1 && errno == EINTR);
if (r == -1) {
    perror("waitpid");
} else if (WIFEXITED(status)) {
    printf("exit %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
    printf("signal %d\n", WTERMSIG(status));
}

Esto usa <sys/wait.h>, <errno.h> y <stdio.h>. El estado almacenado codifica tanto la forma de terminación como un resultado. WEXITSTATUS tiene sentido después de que WIFEXITED sea verdadero; WTERMSIG se usa después de WIFSIGNALED.

Solo están disponibles los ocho bits menos significativos de un valor de salida normal. Por tanto, exit(300) produce 44, mientras que exit(-1) produce 255. En Linux, exit(3) suele producir el estado devuelto por wait sin decodificar 768; imprimir ese entero no equivale a decodificar el código de salida.

Recolectar zombis y reconocer huérfanos

Un zombi ha terminado, pero conserva su PID y su resultado hasta que una espera los recoge. No ejecuta código, por lo que enviarle SIGKILL no puede eliminarlo. Un padre de larga duración debe recolectar a cada hijo. Para recoger a todos los hijos, sigue esperando después de cada PID positivo, vuelve a intentarlo ante EINTR y detente ante ECHILD; informa de los demás errores.

Un huérfano ha perdido a su padre y puede seguir ejecutándose. Linux le asigna como nuevo padre un proceso recolector de descendientes adecuado o el proceso init del espacio de nombres, que puede recoger su resultado más adelante. Los permisos normales para enviar señales dependen de las identidades y los privilegios de los usuarios. Ejecutarse como root concede permisos, no ejecución en modo núcleo.

Puntos clave

  • Cada espera que tiene éxito recoge el resultado de un hijo.
  • Decodifica la salida normal y la terminación por señal con sus macros de estado correspondientes.
  • WNOHANG devuelve 0 cuando existe un hijo que cumple el criterio, pero aún no tiene un resultado listo.
  • Vuelve a intentar una espera interrumpida ante EINTR; ECHILD significa que no queda ningún hijo que cumpla el criterio.
  • Un zombi ha terminado; un huérfano ha perdido a su padre y puede seguir ejecutándose.
  • SIGKILL y SIGSTOP no se pueden capturar ni ignorar.
  • exit vacía los búferes de C; _exit no lo hace.

3.4 Construye un intérprete de comandos sencillo con fork, exec, wait y redirección

Un intérprete de comandos convierte el texto de los comandos en creación de procesos, preparación de descriptores y recogida de resultados. Es un programa de usuario normal que usa los mismos servicios protegidos del SO disponibles para otros programas.

Iniciar un comando externo

Para wc -l notes.txt, el intérprete de comandos construye el vector de argumentos e inicia el comando. Las palabras analizadas forman un vector de argumentos terminado en un puntero nulo, args:

pid_t child = fork();
if (child == -1) {
    perror("fork");
} else if (child == 0) {
    execvp(args[0], args);
    perror("execvp");
    _exit(127);
} else {
    int status;
    pid_t result;
    do {
        result = waitpid(child, &status, 0);
    } while (result == -1 && errno == EINTR);
    if (result == -1) perror("waitpid");
    else if (WIFEXITED(status)) {
        printf("exit %d\n", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
        printf("signal %d\n", WTERMSIG(status));
    }
}

Esto usa <unistd.h>, <sys/wait.h>, <errno.h> y <stdio.h>. El intérprete de comandos que contiene este código lee y analiza cada comando, sigue esta ruta de inicio y luego muestra su siguiente indicador de entrada.

Solo el hijo sustituye su programa; el intérprete puede recoger el fallo de un comando como resultado de terminación. Los comandos internos como cd deben cambiar el estado del propio intérprete: cambiar el directorio de un hijo dejaría al intérprete padre donde estaba.

Redirigir un descriptor antes de exec

Para ls -l > out.txt, el hijo abre el destino para escritura, creándolo o truncándolo. Luego hace que la salida estándar haga referencia a ese archivo:

int fd = open("out.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) { perror("open"); _exit(1); }
if (dup2(fd, STDOUT_FILENO) == -1) {
    perror("dup2"); _exit(1);
}
if (fd != STDOUT_FILENO && close(fd) == -1) {
    perror("close"); _exit(1);
}

open necesita <fcntl.h>; las llamadas a descriptores y _exit usan <unistd.h>. El modo de creación se filtra mediante la máscara de creación de archivos del proceso. La comprobación fd != STDOUT_FILENO mantiene abierto el descriptor 1 aunque open haya devuelto 1. Una vez completada la preparación, exec conserva el descriptor 1 y ls escribe normalmente sin conocer la redirección.

Un enfoque más antiguo cierra el descriptor 1 antes de abrir el archivo: open devuelve el descriptor libre más bajo. dup2 expresa el destino de forma explícita. La redirección de entrada conecta de forma similar un archivo legible al descriptor 0.

Conectar dos comandos

Para ls | wc -l, pipe(fds) crea un extremo de lectura fds[0] y un extremo de escritura fds[1]. El hijo productor conecta el extremo de escritura al descriptor 1. El hijo consumidor conecta el extremo de lectura al descriptor 0. Después de duplicarlos, cada uno cierra los descriptores originales de la tubería que no necesita. El padre cierra sus copias y espera a ambos hijos.

Crea ambos hijos antes de esperar a cualquiera de ellos. Un productor puede llenar la tubería y bloquearse; el lector debe existir para vaciarla. El lector solo alcanza el fin de archivo cuando se cierran todos los descriptores de escritura y se han consumido los datos almacenados en la tubería. Un extremo de escritura sin usar que el padre mantiene abierto puede hacer que wc espere indefinidamente.

Mantener disponible el indicador de entrada

Para sleep 60 &, el intérprete de comandos inicia el hijo y presenta el siguiente indicador sin esperar inmediatamente. Más tarde usa esperas no bloqueantes o responde a SIGCHLD para recolectar a los hijos terminados.

El estado de salida también controla las combinaciones de comandos. make && ./app inicia el segundo comando solo después de un resultado satisfactorio; make || echo failed inicia el segundo solo después de un fallo. Estas decisiones usan el resultado decodificado, no el estado codificado devuelto por wait sin decodificar.

Puntos clave

  • Un comando externo se ejecuta en un hijo; un comando interno que cambia el estado se ejecuta en el intérprete de comandos.
  • La redirección cambia los descriptores en el hijo antes de exec.
  • Una tubería conecta la salida estándar de un productor con la entrada estándar de un consumidor.
  • Inicia ambos lados antes de esperar y cierra los extremos de la tubería que no se usan.
  • Para alcanzar el fin de archivo deben cerrarse todos los extremos de escritura de la tubería y consumirse los datos almacenados en búfer.
  • La ejecución en segundo plano pospone la espera; el intérprete de comandos debe recolectar al hijo más tarde.
4

Explica el modo usuario, el modo núcleo y las llamadas al sistema

Los programas de usuario necesitan servicios del SO sin obtener el control de la máquina. Los modos de privilegio del hardware crean ese límite, y las rutas de entrada controladas permiten al núcleo atender solicitudes y eventos. Sigue una llamada al sistema a través de su función envoltorio de biblioteca y su manejador en el núcleo, y luego distingue las trampas deliberadas, los fallos de instrucción y las interrupciones de dispositivos por sus causas y posibles resultados.

4.1 Distingue el modo usuario del modo núcleo

El núcleo debe permitir que los programas calculen rápidamente y, al mismo tiempo, impedir operaciones que podrían tomar el control de la máquina. El modo de privilegio de la CPU es el límite de hardware que hace posibles ambas cosas.

Separar el cálculo del control privilegiado

En modo usuario, las instrucciones pueden acceder a la memoria permitida del proceso y realizar cálculos normales. No pueden cambiar libremente la configuración de hardware que protege a otros programas. En modo núcleo, también llamado modo supervisor o privilegiado, el SO puede realizar las operaciones protegidas necesarias para gestionar la máquina.

Las operaciones privilegiadas incluyen programar el temporizador, desactivar interrupciones, instalar manejadores de interrupciones, cambiar los registros de control de traducción de memoria, controlar directamente dispositivos protegidos y detener la CPU. Si cualquier aplicación pudiera desactivar el temporizador, los turnos cortos de CPU dependerían de la cooperación de esa aplicación.

PlataformaModo de aplicaciónModo núcleo
x86-64 en Linux o WindowsAnillo 3Anillo 0
AArch64EL0EL1

AArch64 también proporciona EL2 para hipervisores y EL3 para firmware seguro. Estos nombres identifican niveles de privilegio del hardware, no distintos tipos de cuentas de usuario.

Entrar en una dirección controlada

El código de usuario no puede elevar su propio privilegio ni elegir cualquier dirección del núcleo para ejecutarla. La entrada se produce mediante una llamada al sistema, una excepción causada por una instrucción o una interrupción de hardware. La CPU transfiere el control a un punto de entrada configurado por el SO. El código de retorno del núcleo restaura el estado de usuario guardado y reduce el nivel de privilegio para reanudar el código de la aplicación.

El núcleo también protege sus datos mediante permisos de memoria. Un proceso puede tener direcciones del núcleo en su organización virtual y, aun así, carecer de permiso en modo usuario para acceder a ellas. Conocer una dirección no concede acceso a los bytes que contiene.

Considera una aplicación de Linux x86-64 que ejecuta hlt, una instrucción destinada a detener una CPU hasta que ocurra un evento. En modo usuario, la instrucción provoca una excepción. Linux normalmente envía SIGSEGV, cuya acción predeterminada termina ese proceso. La aplicación no detiene todo el computador; el límite de protección convierte el intento de operación privilegiada en un evento que gestiona el núcleo.

Separar la identidad del modo

Un proceso de root o administrador sigue siendo un programa en modo usuario mientras se ejecutan sus propias instrucciones. Su identidad de usuario le da un permiso más amplio para solicitar servicios. Sigue entrando en el núcleo mediante rutas controladas y el núcleo comprueba la solicitud.

Por ejemplo, una utilidad de mantenimiento privilegiada puede tener permiso para abrir un archivo protegido. La utilidad lo solicita mediante una llamada al sistema; no se convierte en código del núcleo solo porque se permita la solicitud. A la inversa, cuando el código del núcleo atiende una llamada a read de un usuario normal, se ejecuta en modo núcleo aunque quien llama no tenga una identidad administrativa.

En una CPU lógica, esto ocurre en secuencia: instrucciones de usuario, entrada en el núcleo, trabajo del núcleo y retorno a las instrucciones de usuario. No es una ejecución simultánea de un programa y una segunda tarea del SO en esa misma CPU. Distintas CPU lógicas pueden ejecutar distintos modos en el mismo instante.

Puntos clave

  • El modo usuario permite cálculos normales mientras restringe las operaciones de control de la máquina.
  • La entrada en el núcleo usa puntos de entrada configurados por el SO.
  • Root es una identidad de usuario; el modo núcleo es un estado de privilegio de la CPU.
  • Una instrucción prohibida en modo usuario genera una excepción para que el núcleo pueda responder.

4.2 Explica paso a paso cómo funciona una llamada al sistema

Un programa en C a menudo parece llamar a una función normal cuando necesita un servicio del SO. Debajo de la función envoltorio de una llamada al sistema, una transición controlada de la CPU permite al código del núcleo validar y realizar esa solicitud.

Distinguir una llamada de biblioteca de una solicitud al núcleo

La biblioteca de C implementa strlen en espacio de usuario sin una llamada al sistema. printf da formato a los datos y puede almacenarlos en un búfer; una llamada posterior a write transfiere bytes a través del núcleo. Una función envoltorio sencilla de read prepara los argumentos según el convenio de llamadas al sistema de la plataforma y ejecuta la instrucción de entrada.

POSIX describe interfaces para sistemas de tipo Unix. Linux implementa muchos servicios agrupados de forma general en control de procesos, operaciones de archivos y dispositivos, información, comunicación y protección. Un número de llamada al sistema selecciona un servicio de la tabla de despacho del núcleo. Los números dependen de la plataforma: Linux x86-64 usa 1 para write y 39 para getpid; AArch64 usa 64 para write.

Seguir una solicitud de escritura

Para write(1, "hi\n", 3) en Linux x86-64, sigue la solicitud en orden:

  1. La función envoltorio coloca el número de servicio 1 en rax, el descriptor 1 en rdi, la dirección del búfer en rsi y la cantidad 3 en rdx.
  2. syscall conserva la dirección de retorno y los indicadores en registros, entra en modo núcleo y salta al punto de entrada configurado. No cambia de pila automáticamente.
  3. El código de entrada del núcleo establece la pila del núcleo del proceso y guarda el resto del estado de usuario.
  4. El despacho del núcleo selecciona write; la implementación comprueba el descriptor, el acceso al búfer de usuario y la solicitud antes de pasar los bytes hacia el recurso de salida.
  5. Si se escriben todos los bytes correctamente, el resultado es 3 bytes. El código de retorno del núcleo restaura el estado de usuario y reanuda la función envoltorio, que retorna a quien la llamó.

El descriptor 1 puede identificar una terminal, un archivo o una tubería. El número por sí solo no identifica el dispositivo de salida. Una escritura también puede devolver una cantidad menor de bytes escritos sin que haya un error; quienes necesitan transferir todos los bytes llevan la cuenta de la cantidad realmente escrita.

Comprobar errores en la interfaz

El núcleo trata los punteros de usuario y los demás argumentos como no fiables. Una solicitud para copiar desde un búfer inaccesible puede fallar con EFAULT; la copia controlada evita conceder a quien llama acceso a la memoria del núcleo.

En Linux, un error del núcleo es un código de error negativo. La función envoltorio habitual de C devuelve -1 y establece errno. Por ejemplo, si open("missing.txt", O_RDONLY) falla porque el archivo no existe, errno es ENOENT. perror("missing.txt") puede mostrar «missing.txt: No such file or directory». Consulta errno después de que se indique un fallo, no como comprobación principal de éxito: una llamada que tiene éxito no tiene por qué borrar un error anterior.

Tener en cuenta el tiempo empleado en el núcleo

Una llamada que puede terminar en ese momento puede retornar al mismo proceso. Una lectura bloqueante de terminal puede, en cambio, poner ese proceso en estado bloqueado y dejar que otro se ejecute. El evento de entrada hace que el lector quede listo; una vez planificado, completa la ruta de retorno.

La entrada en el núcleo añade trabajo respecto de una llamada normal a una función: guardar el estado, cambiar de privilegio, comprobar los argumentos y restaurar la ejecución. El almacenamiento en búfer de la biblioteca puede combinar salidas pequeñas en menos escrituras. En Linux, strace ls ejecuta ls mientras informa de sus llamadas al sistema, argumentos y resultados.

Puntos clave

  • Una función de biblioteca puede hacer todo su trabajo en espacio de usuario o invocar llamadas al sistema.
  • Un número de servicio selecciona una operación del núcleo; quien llama no elige una dirección arbitraria del núcleo.
  • El código del núcleo valida descriptores, punteros y otros argumentos.
  • Usa el valor de retorno para detectar un fallo y después consulta errno.
  • Una llamada al sistema bloqueante puede provocar un cambio de contexto; la entrada en el núcleo por sí sola no tiene por qué hacerlo.
  • Los números de llamadas al sistema y los convenios de registros dependen del SO y de la arquitectura.

4.3 Distingue las trampas, las excepciones y las interrupciones

La entrada en el núcleo puede deberse a una solicitud de servicio, un problema de instrucción o un evento de dispositivo. Clasificar la causa te ayuda a predecir qué hará el SO y si debe volver a ejecutarse la misma instrucción.

Preguntar qué causó el evento
EventoCausaMomento respecto a la instrucción actual
Trampa de llamada al sistemaEl programa solicita deliberadamente un servicioSíncrono
Excepción o falloLa instrucción actual necesita una gestión especialSíncrono
Interrupción de hardwareUn temporizador o dispositivo envía una señal a la CPUAsíncrono

Síncrono significa que está ligado a la instrucción que se ejecuta. No significa que la misma entrada cause exactamente los mismos fallos en cada ejecución. Una carga puede fallar cuando su página está ausente y tener éxito más tarde cuando esa página está presente en memoria. Asíncrono significa que la causa del evento es independiente de la instrucción actual, como cuando un disco completa un trabajo anterior.

Los manuales de CPU usan estos términos de distintas maneras. Sigue la causa: solicitud deliberada de servicio, evento causado por una instrucción o notificación de hardware.

Despachar al manejador correcto

Durante el arranque, el SO instala direcciones protegidas de manejadores. Una tabla de trampas o interrupciones asigna los tipos de eventos a rutinas del núcleo. En x86-64, la tabla de descriptores de interrupción (IDT) atiende las interrupciones y excepciones; syscall usa una dirección de entrada en un registro especial del procesador. Solo el código privilegiado puede configurar estos destinos.

Ante una interrupción desde el modo usuario, el hardware x86-64 guarda un marco de retorno en una pila del núcleo. El código de entrada guarda registros adicionales antes de realizar el trabajo. La ruta de syscall conserva su estado inicial de retorno en registros y depende del código de entrada para establecer la pila del núcleo. Tratar todas las rutas de entrada como acciones de hardware idénticas oculta una diferencia importante de implementación.

Elegir el resultado

Se puede cargar una página válida que no está en memoria, tras lo cual se vuelve a intentar la instrucción que provocó el fallo. Un acceso a memoria que el proceso no puede usar normalmente hace que Linux envíe SIGSEGV. Por tanto, una excepción no siempre es fatal ni siempre implica saltarse la instrucción actual.

Para una instrucción entera real idiv de x86-64 con divisor cero, la CPU genera una excepción de error de división. Linux normalmente entrega SIGFPE; su conocido mensaje menciona el punto flotante incluso para esta instrucción entera. En cambio, la división entera de AArch64 da cero cuando el divisor es cero. La división entre cero en C tiene un comportamiento indefinido, por lo que el código C portable no puede depender de ninguno de los dos resultados de la máquina.

Cuando termina una lectura de disco, el manejador de interrupciones registra su finalización y pasa el proceso que espera a listo. Ese proceso puede ejecutarse más tarde. Una interrupción del temporizador da al SO la oportunidad de reconsiderar qué proceso usa actualmente la CPU, pero el manejador también puede volver a ese mismo proceso.

Distinguir una señal de una interrupción

Una interrupción de hardware notifica a la CPU; una señal notifica a un proceso a través del SO. Una excepción puede hacer que el núcleo envíe una señal, y un proceso puede solicitar una señal para otro mediante kill. Las finalizaciones normales de dispositivos son interrupciones que no implican errores de programa.

El código del núcleo también debe proteger los datos compartidos mientras ocurren eventos. Puede desactivar brevemente las interrupciones en una CPU y usar cerrojos donde sea necesario. Los periodos largos con interrupciones desactivadas retrasan la atención a los dispositivos; desactivar solo las interrupciones locales no impide que otra CPU acceda a los datos compartidos.

Puntos clave

  • Las trampas y excepciones surgen de la instrucción actual; las interrupciones de hardware tienen una causa externa.
  • Un fallo recuperable puede corregirse y su instrucción puede volver a intentarse.
  • Las tablas de entrada protegidas impiden que los programas de usuario sustituyan los manejadores del núcleo.
  • Una señal se dirige a un proceso; una interrupción de hardware se dirige a la CPU para que la gestione.
  • La finalización de un dispositivo pasa un proceso de bloqueado a listo, y una interrupción del temporizador no tiene por qué cambiar de proceso.
5

Explica cómo el sistema operativo comparte la CPU mediante la ejecución directa limitada

La ejecución rápida y el control del SO deben funcionar conjuntamente. La ejecución directa limitada permite que las instrucciones normales se ejecuten en el hardware mientras los modos, los puntos de entrada protegidos y un temporizador mantienen el control en manos del núcleo. Sigue lo que ocurre cuando el SO vuelve al mismo proceso y cuando reanuda uno distinto. El estado guardado y los costes de cambio explican cómo los turnos cortos de CPU pueden facilitar el trabajo interactivo.

5.1 Explica la ejecución directa limitada

Ejecutar cada instrucción de una aplicación en un simulador de software haría costosa la compartición de la CPU. Permitir que una aplicación controle la máquina sin límites haría insegura esa compartición. La ejecución directa limitada (LDE) usa la ejecución normal en el hardware con una ruta protegida de regreso al SO.

Resolver dos problemas de control distintos

La ejecución directa significa que las instrucciones normales de un proceso se ejecutan en la propia CPU. El SO no examina ni aprueba cada instrucción aritmética. Quedan dos problemas: restringir las operaciones que podrían dañar la máquina y recuperar el control cuando un programa no se detiene voluntariamente.

El modo usuario resuelve el problema de las restricciones. Las trampas de llamadas al sistema permiten que un programa solicite servicios sin elegir código privilegiado arbitrario. Un temporizador de hardware resuelve el problema del control: puede interrumpir una aplicación que no realiza ninguna llamada. Juntos, estos mecanismos permiten virtualizar la CPU con poca sobrecarga.

Preparar el sistema antes de ejecutar aplicaciones

Durante el arranque, el núcleo configura los manejadores de eventos e inicializa el temporizador. Estas operaciones de configuración son privilegiadas. Los programas de usuario posteriores no pueden redirigir los manejadores ni desactivar el temporizador para evitar perder sus turnos.

Para iniciar un proceso, el SO crea su registro de gestión y su imagen de memoria, prepara los argumentos de arranque y una pila de usuario, y establece los valores iniciales de los registros. Prepara un contexto inicial guardado para que la ruta normal de retorno del núcleo al usuario pueda iniciar el programa. Conceptualmente, el proceso comienza retornando de una trampa que nunca realizó.

La organización detallada del marco guardado depende de la CPU y del SO. La idea de diseño útil es la reutilización: el mismo mecanismo de restauración puede reanudar un proceso suspendido o iniciar uno recién preparado.

Volver al núcleo voluntariamente

Durante una llamada al sistema, el hardware conserva el estado inicial de retorno y transfiere el control. El código de entrada del núcleo guarda los registros adicionales en la pila del núcleo del proceso. Después de completar una solicitud no bloqueante, el núcleo restaura el proceso y vuelve al modo usuario. Si la solicitud bloquea el proceso, primero puede ejecutarse otro proceso listo.

Cuando main retorna, el procesamiento de salida del entorno de ejecución acaba pidiendo al núcleo que termine el proceso. Su memoria puede liberarse mientras su registro de terminación permanece hasta que un padre lo recolecte.

Volver sin cooperación

Un sistema cooperativo depende de que los programas realicen llamadas, cedan la CPU o provoquen excepciones. Un bucle infinito que no hace ninguna de estas cosas puede monopolizar una CPU. El Mac OS clásico ilustra esta debilidad.

Un diseño no cooperativo usa una interrupción del temporizador para forzar la entrada en el núcleo. Considera un modelo didáctico con una CPU lógica y un temporizador periódico cada 4 ms. El temporizador produce 1000 / 4 = 250 pulsos por segundo. Un proceso de usuario atrapado en while (1) { } es interrumpido en el siguiente pulso. El núcleo puede entonces ejecutar otro proceso listo; el bucle no necesita alcanzar primero una llamada al sistema.

El pulso es una oportunidad para actuar, no una obligación de cambiar de proceso. El planificador puede dejar que continúe el proceso interrumpido. La gestión del temporizador y la restauración del estado guardado son mecanismos; la elección del planificador es una política. El tiempo de respuesta real también depende del trabajo del núcleo y de cuándo pueden gestionarse las interrupciones, por lo que el periodo del temporizador por sí solo no garantiza el tiempo de respuesta de una aplicación.

Puntos clave

  • LDE ejecuta directamente las instrucciones normales de usuario con límites impuestos por el hardware.
  • El modo usuario restringe las operaciones; las llamadas al sistema proporcionan servicios privilegiados de forma controlada.
  • Un temporizador permite al SO recuperar el control sin cooperación del código de usuario.
  • La configuración durante el arranque protege las direcciones de los manejadores y la configuración del temporizador.
  • Un pulso del temporizador da al planificador la posibilidad de elegir; no exige un cambio de proceso.

5.2 Sigue un cambio de contexto y estima su coste

Entrar en modo núcleo no cambia necesariamente el proceso en ejecución. Un cambio de contexto ocurre cuando el núcleo conserva el estado de ejecución de un proceso y reanuda el de otro. Esto requiere tanto conservar el estado de usuario como cambiar el propio contexto de ejecución del núcleo.

Seguir la salida de A y la entrada de B

Para un cambio provocado por el temporizador en x86-64, sigue las capas:

  1. A ejecuta instrucciones de usuario. El temporizador lo interrumpe.
  2. El hardware pasa a modo núcleo y guarda el marco de retorno de interrupción de A en la pila del núcleo de A. El código de entrada guarda allí los demás registros de usuario de A.
  3. El planificador elige B. La rutina de cambio guarda el contexto de ejecución del núcleo de A y restaura el contexto del núcleo guardado de B, incluido su puntero de pila del núcleo.
  4. El núcleo cambia al contexto del espacio de direcciones de B según sea necesario. Ahora se ejecuta en nombre de B usando la pila del núcleo de B.
  5. El código de salida del núcleo restaura los registros de usuario de B. La instrucción de retorno restaura el estado de retorno de B y entra en modo usuario. B se reanuda donde se detuvo anteriormente.

El primer guardado conserva la ejecución de usuario interrumpida de A. El segundo conserva el punto en el que estaba el núcleo mientras atendía a A. No son dos copias completas e idénticas del mismo conjunto de registros. Un PCB o estructura de contexto asociada y la pila del núcleo de cada proceso trabajan conjuntamente para conservar el estado.

Identificar el evento y la decisión

Una llamada bloqueante, la terminación de un proceso o una decisión tras una interrupción del temporizador pueden provocar un cambio. Una interrupción de dispositivo puede hacer que otro proceso quede listo y la planificación puede seleccionarlo entonces. Todo el mecanismo de cambio se ejecuta en el núcleo; una aplicación no guarda sus propios registros para ofrecerse a ser interrumpida.

Situación¿Transición de modo?¿Cambio de proceso?
Un servicio no bloqueante retorna a quien lo llamóUsuario → núcleo → usuarioNo
Se gestiona el temporizador y se reanuda el mismo procesoUsuario → núcleo → usuarioNo
A se bloquea y B se reanudaEntrada en el núcleo y luego ruta de retorno de BSí

Un cambio de contexto conserva el estado de ejecución necesario para continuar. El tiempo transcurre y el mundo exterior puede cambiar: los desplazamientos compartidos de archivos y las entradas externas no quedan congelados mientras un proceso está en pausa.

Tener en cuenta los costes directos e indirectos

El trabajo directo incluye ejecutar el planificador, guardar y restaurar registros y seleccionar un espacio de direcciones. Las cachés de traducción pueden necesitar ajustes; las traducciones etiquetadas pueden evitar que se descarten todas las entradas anteriores. Después aparecen costes indirectos cuando B debe volver a llenar las cachés de la CPU o las traducciones de direcciones almacenadas en caché que A desplazó. El coste depende del hardware y de la carga de trabajo, así que usa valores medidos o indicados al calcular la sobrecarga.

Supón que un cambio, incluidos sus efectos pertinentes, cuesta 5 µs y que los turnos útiles de CPU duran 10 ms. Convierte 10 ms en 10 000 µs. La proporción dedicada al cambio es 5 / (10 000 + 5), aproximadamente 0,05 %. Para turnos útiles de 1 ms es 5 / 1005, aproximadamente 0,50 %; con 0,1 ms es 5 / 105, aproximadamente 4,8 %.

El denominador incluye el trabajo útil más el tiempo de cambio de un ciclo repetido. Un turno más corto puede mejorar las oportunidades para el trabajo interactivo, pero dedica una fracción mayor a cambios repetidos. El temporizador y el código de cambio hacen posibles los turnos cortos; la política de planificación debe sopesar ese coste frente a la rapidez de respuesta.

Puntos clave

  • La entrada en el núcleo puede retornar al mismo proceso sin un cambio de contexto.
  • Guardar el estado de usuario al entrar y guardar el contexto del núcleo durante un cambio cumplen funciones distintas.
  • Reanudar B requiere su pila del núcleo, sus registros guardados y el contexto de su espacio de direcciones.
  • Los costes de cambio incluyen el trabajo directo de gestión y el llenado posterior de cachés o traducciones.
  • La proporción de sobrecarga es el coste de cambio dividido entre el turno útil más el coste de cambio.
  • Con un coste fijo por cambio, los turnos más cortos aumentan la proporción dedicada a los cambios.

Ejemplos de Procesos y llamadas al sistema

5 Lecciones Interactivas

1

Descubre qué aporta el SO

12 pasos
Sigue los recursos compartidos desde una solicitud de aplicación hasta los servicios del núcleo y luego compara los diseños que permiten su uso compartido.
  1. 1
    IntroducciónEmpieza con varios programas

    Imagina una computadora portátil que compila un proyecto mientras reproduce música y recibe datos de red. Cada aplicación necesita tiempo de CPU, memoria y entrada/salida, pero ninguna controla toda la máquina.

    Sigue quién proporciona esos recursos, cómo avanzan varios trabajos y dónde se ejecutan los servicios privilegiados. La pregunta recurrente es concreta: ¿qué trabajo solicita la aplicación y qué trabajo debe gestionar el SO?

  2. 2
    ExplicaciónOculta los detalles del dispositivo

    El SO ofrece abstracciones: interfaces útiles que ocultan los mecanismos de nivel inferior. Un programa abre un archivo y lee bytes sin implementar comandos para cada dispositivo de almacenamiento.

    Una llamada al sistema solicita un servicio del núcleo mediante una interfaz controlada. El núcleo comprueba y realiza el trabajo protegido. La aplicación sigue decidiendo qué datos quiere; no obtiene permiso para controlar directamente el dispositivo.

  3. 3
    EjemploSigue un archivo de salida de un compilador

    Un compilador produce bytes para un ejecutable y solicita una escritura. El núcleo comprueba el recurso de salida y gestiona el almacenamiento detrás de la interfaz de archivos.

    Al mismo tiempo, el SO gestiona la memoria del compilador y comparte el tiempo de CPU con el reproductor de música. Una acción, guardar un archivo, se sitúa por tanto dentro de varias responsabilidades del SO: abstracción, gestión de recursos y protección de los demás programas.

  4. 4
    Idea claveDa a cada proceso una máquina utilizable

    La virtualización presenta un recurso físico mediante una vista privada útil. Un proceso puede avanzar como si tuviera un procesador propio, aunque sus instrucciones se turnen con las de otros procesos.

    Su vista de memoria también es privada: la dirección que usa no tiene por qué identificar los mismos bytes físicos en otro proceso. La virtualización de la CPU y la memoria da a los programas modelos cómodos mientras el SO gestiona el hardware físico compartido.

  5. 5
    DesafíoLocaliza la parte privilegiada

    Un computador no tiene instalado un escritorio gráfico, pero ejecuta servicios, almacena archivos y comparte tiempo de CPU. ¿Ha perdido la parte central esencial del SO? Explícalo.

    ---reveal---

    No. El núcleo sigue gestionando procesos, memoria y servicios de dispositivos. Un escritorio gráfico es un programa de usuario que se ejecuta sobre esos servicios. Su ausencia cambia la interfaz que ve una persona, no la necesidad del trabajo de gestión de recursos del núcleo.

  6. 6
    ExplicaciónSepara la operación de la elección

    Un mecanismo hace posible una acción. Guardar los registros de un proceso y restaurar los de otro proporciona el mecanismo necesario para cambiar de proceso.

    Una política elige cómo usarlo, por ejemplo, al decidir qué proceso listo obtiene el siguiente turno de CPU. La distinción importa cuando cambia un diseño: una nueva regla de elección puede reutilizar el mismo código fiable de cambio. Los mecanismos eficientes por sí solos no deciden qué es equitativo.

  7. 7
    ExplicaciónOcupa una espera que dejaría la CPU inactiva

    Un sistema por lotes puede dejar la CPU inactiva mientras su trabajo actual espera una operación de entrada/salida. La multiprogramación mantiene otros trabajos disponibles y ejecuta uno durante esa espera.

    El trabajo que espera no calcula y el dispositivo no se ha vuelto más rápido. La ganancia procede de solapar trabajo independiente: un proceso espera mientras otro usa la CPU. Varios programas residentes también requieren protección para que uno no pueda sobrescribir la memoria de otro.

  8. 8
    EjemploCalcula la ganancia de utilización

    Un trabajo calcula durante 20 ms y luego espera 80 ms a una operación de entrada/salida. Por sí solo, un ciclo de 100 ms contiene solo 20 ms de trabajo de CPU: la utilización es del 20 %.

    Con un segundo trabajo de ese tipo y un solapamiento adecuado, otros 20 ms de cálculo pueden ocupar tiempo que de otro modo quedaría inactivo, lo que da hasta un 40 % en este ejemplo. La mejora usa productivamente el tiempo de espera; añadir trabajos no puede elevar la utilización de la CPU por encima del 100 %.

  9. 9
    ConexiónDa turnos cortos al trabajo interactivo

    El tiempo compartido da a los procesos turnos cortos de CPU para que el trabajo interactivo no tenga que esperar a que termine todo un trabajo por lotes. Esto es concurrencia incluso en una CPU lógica: varias actividades avanzan mediante el intercalado.

    El paralelismo necesita una ejecución realmente simultánea en recursos de procesamiento separados. La capacidad de memoria y disco ilustra otra división, la compartición espacial, en la que distintos usuarios disponen de partes separadas a la vez.

  10. 10
    ExplicaciónElige un límite para los servicios

    Un núcleo monolítico, como Linux, ejecuta la mayoría de los servicios juntos y con privilegios. Las llamadas directas son eficientes, pero un controlador defectuoso puede dañar el estado del núcleo.

    Un micronúcleo, como seL4, deja más servicios en procesos de usuario separados. El aislamiento puede contener el fallo de un servicio, a costa de comunicación y transiciones de modo. Windows NT y XNU mezclan enfoques. El límite determina qué fallos pueden propagarse y qué servicios pueden reiniciarse.

  11. 11
    DesafíoRelaciona la compartición y la protección

    Un sistema con una CPU ejecuta varios trabajos y cambia a otro cuando uno espera una operación de entrada/salida de disco. Una propuesta permitiría que cada trabajo sobrescribiera cualquier dirección de memoria. Explica el beneficio para la utilización y el defecto de esta propuesta.

    ---reveal---

    La multiprogramación ocupa las esperas de entrada/salida con los cálculos de otro trabajo. Las escrituras sin restricciones permitirían que un trabajo dañara a otro o al SO. Solapar el trabajo mejora el uso de los recursos, pero el uso compartido sigue necesitando protección de memoria y privilegios que se haga cumplir.

  12. 12
    RepasoAnaliza un diseño con tres preguntas

    Ante el diseño de un SO, pregunta qué recurso se comparte, qué interfaz ve un programa y qué límite protege el resto del trabajo.

    Estas preguntas conectan la virtualización de la CPU con los turnos de los procesos, los archivos con los detalles ocultos de los dispositivos y la organización del núcleo con el aislamiento de fallos. Los mecanismos realizan operaciones protegidas; las políticas deciden cómo distribuir su uso. La concurrencia puede surgir del intercalado en una CPU.

2

Sigue un proceso durante el trabajo de CPU y de entrada/salida

13 pasos
Interpreta un registro de proceso y luego construye una línea de tiempo que separe la ejecución, la espera de una CPU y la espera de un evento.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónSigue una instancia activa
  2. 2
    ExplicaciónConvierte un archivo en un proceso
  3. 3
    ExplicaciónConserva la siguiente instrucción
  4. 4
    EjemploInterpreta un listado de procesos
  5. 5
    DesafíoInterpreta direcciones iguales
  6. 6
    ConsejoInterpreta los descriptores como recursos heredados
  7. 7
    ExplicaciónPregunta qué falta
  8. 8
    EjemploInicia la línea de tiempo
  9. 9
    EjemploCompleta la línea de tiempo
  10. 10
    DesafíoCambia la decisión sobre el proceso listo
  11. 11
    ConexiónReconoce los nombres de estado reales
  12. 12
    DesafíoRelaciona los registros con la capacidad de CPU
  13. 13
    RepasoInterpreta el estado como posibilidad de ejecución
3

Construye un comando a partir de llamadas de proceso

23 pasos
Sigue a un hijo desde fork hasta la sustitución del programa, la recogida del resultado, la redirección y una cadena de tuberías conectada.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónAsigna una tarea a cada llamada
  2. 2
    ExplicaciónDivide una ejecución en dos
  3. 3
    EjemploSigue un valor privado
  4. 4
    EjemploCuenta una rama, no las llamadas del código fuente
  5. 5
    DesafíoCuenta las rutas que imprimen
  6. 6
    ConsejoComprueba qué se copió
  7. 7
    ExplicaciónSustituye el programa del hijo
  8. 8
    EjemploPasa cadenas de argumentos separadas
  9. 9
    DesafíoPredice una sustitución con éxito
  10. 10
    Idea claveUsa el intervalo antes de exec
  11. 11
    ExplicaciónRecoge el resultado de un hijo
  12. 12
    EjemploDecodifica la salida normal
  13. 13
    ExplicaciónNo dejes resultados sin recoger
  14. 14
    DesafíoGestiona correctamente una interrupción
  15. 15
    ConsejoElige una solicitud de terminación
  16. 16
    ExplicaciónVuelve al indicador de entrada en primer plano
  17. 17
    EjemploRedirige la salida antes de la sustitución
  18. 18
    DesafíoConserva el destino de salida
  19. 19
    EjemploConecta los dos extremos de la tubería
  20. 20
    Idea claveInicia los procesos antes de esperar
  21. 21
    ConexiónLleva el seguimiento del trabajo en segundo plano
  22. 22
    DesafíoSigue una cadena de tuberías vacía
  23. 23
    RepasoSigue la identidad, la imagen y el resultado
4

Sigue una solicitud a través del límite de privilegio

15 pasos
Sigue una solicitud de servicio hasta el núcleo y después compárala con los fallos de instrucción y los eventos externos de dispositivos.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónPregunta por qué se entró en el núcleo
  2. 2
    ExplicaciónLimita lo que pueden controlar las aplicaciones
  3. 3
    EjemploSepara la identidad del privilegio
  4. 4
    DesafíoPredice qué ocurre con una instrucción prohibida
  5. 5
    ExplicaciónEncuentra la llamada al sistema real
  6. 6
    EjemploPrepara una escritura
  7. 7
    EjemploEntra y valida
  8. 8
    EjemploInterpreta el retorno
  9. 9
    DesafíoSigue una lectura bloqueada
  10. 10
    ExplicaciónClasifica según la causa
  11. 11
    EjemploCorrige o termina
  12. 12
    ConsejoMantén las señales en la capa de procesos
  13. 13
    DesafíoClasifica la finalización de una operación de dispositivo
  14. 14
    DesafíoSepara dos tipos de entrada
  15. 15
    RepasoSigue la causa, las comprobaciones y el resultado
5

Mantén el control mientras los programas se ejecutan directamente

15 pasos
Sigue el control provocado por el temporizador hasta un cambio entre procesos y luego estima la fracción de tiempo que consume ese cambio.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónCombina velocidad y control
  2. 2
    ExplicaciónResuelve dos problemas de control
  3. 3
    EjemploPrepara la máquina y el proceso
  4. 4
    ConexiónObserva la debilidad del enfoque cooperativo
  5. 5
    EjemploInterrumpe un bucle infinito
  6. 6
    DesafíoIdentifica el mecanismo que falta
  7. 7
    ExplicaciónGuarda la ruta de usuario interrumpida
  8. 8
    EjemploGuarda también la ruta del núcleo
  9. 9
    EjemploRetorna mediante el estado guardado de B
  10. 10
    DesafíoDetecta una transición solo de modo
  11. 11
    ExplicaciónCuenta los costes después de un cambio
  12. 12
    EjemploConstruye el denominador del ciclo completo
  13. 13
    DesafíoEstima el efecto de cambiar la duración del turno
  14. 14
    DesafíoRelaciona una llamada bloqueada con su reanudación
  15. 15
    RepasoSigue a quién pertenece la ruta de retorno

Ejercicios de Procesos y llamadas al sistema

50 Preguntas de Práctica en 5 sets

Set 1: Recursos, procesos y protección10 Preguntas de Práctica

Pregunta 1 de 10

Un programa escribe un archivo sin saber si sus datos van a una unidad SSD o a una unidad de red. ¿Qué idea del SO hace esto posible?
  1. El tiempo compartido del dispositivo de almacenamiento
  2. Una abstracción para las operaciones de archivo
  3. La ejecución paralela de solicitudes a dispositivos
  4. Una política de planificación para el programa
Mostrar respuestaOcultar respuesta
Respuesta: B
Una interfaz de archivos oculta el trabajo específico del dispositivo detrás de operaciones que el programa puede solicitar. Esto es una abstracción: el programa trabaja con bytes y archivos mientras el SO gestiona los detalles del dispositivo. El tiempo compartido se refiere a cuándo se usa un recurso, no a la interfaz que oculta esos detalles.

Pregunta 2 de 10

Un SO cambia qué proceso listo recibe el siguiente turno, pero mantiene sin cambios su rutina de guardado de registros. ¿Qué cambió?
  1. La organización del espacio de direcciones
  2. El mecanismo de privilegios
  3. El formato de los registros
  4. La política de planificación
Mostrar respuestaOcultar respuesta
Respuesta: D
La regla de selección es una política; la rutina de guardado y restauración que no cambió es un mecanismo. Un mecanismo de cambio puede admitir varias formas de elegir el siguiente proceso. Cambiar el orden de los turnos de CPU no cambia por sí solo cómo conserva la máquina el estado de los registros.

Pregunta 3 de 10

Un trabajo calcula repetidamente durante 15 ms y luego espera 45 ms a una operación de entrada/salida. ¿Qué utilización de CPU alcanza cuando es el único trabajo y se ignora la sobrecarga del cambio?
  1. 25%
  2. 33,3 %
  3. 75%
  4. 15%
Mostrar respuestaOcultar respuesta
Respuesta: A
Cada ciclo dura 15 + 45 = 60 ms y solo 15 ms contienen cálculos. Por tanto, la utilización de CPU es 15 / 60 = 25 %. Dividir 15 entre los 45 ms de espera da 33,3 %, pero la utilización usa todo el ciclo transcurrido, incluidos el cálculo y la espera.

Pregunta 4 de 10

Dos programas se turnan repetidamente en una CPU lógica antes de que termine cualquiera de ellos. ¿Cómo se describe su ejecución?
  1. Paralela, con ejecución simultánea
  2. Secuencial, con cada uno terminando primero
  3. Concurrente, con ejecución intercalada
  4. Con compartición espacial, con división permanente de la CPU
Mostrar respuestaOcultar respuesta
Respuesta: C
Ambas actividades están en curso durante el mismo intervalo, por lo que su ejecución es concurrente. Una sola CPU lógica intercala sus instrucciones. La ejecución paralela requeriría recursos de procesamiento simultáneos; cambiar rápidamente de turno no hace que las instrucciones se ejecuten en el mismo instante.

Pregunta 5 de 10

Un listado de procesos muestra PID 9641, PPID 9600 y el nombre de comando «sort». ¿Cuál es su proceso padre?
  1. El proceso cuyo PID es 9600
  2. El proceso cuyo PID es 9641
  3. Todos los procesos llamados «sort»
  4. El proceso creado después de 9641
Mostrar respuestaOcultar respuesta
Respuesta: A
PPID identifica al proceso padre, por lo que el padre tiene el PID 9600. El PID 9641 identifica al propio proceso sort. Un nombre de comando puede ser compartido por muchas instancias de proceso y no sustituye la relación numérica con el padre registrada por el núcleo.

Pregunta 6 de 10

Dos copias de un programa iniciadas por separado imprimen la misma dirección virtual para una variable privada. Una cambia su valor. ¿Qué ocurre con la otra copia?
  1. Ve la misma escritura porque coinciden las direcciones virtuales.
  2. Ve la escritura solo después de que ambos procesos vuelvan a entrar en el núcleo.
  3. Conserva su valor solo hasta que se restaure su siguiente contexto guardado.
  4. Conserva su valor porque su espacio de direcciones está separado.
Mostrar respuestaOcultar respuesta
Respuesta: D
Cada proceso tiene su propio espacio de direcciones privado, por lo que números de dirección virtual iguales pueden identificar datos distintos. Una escritura en una variable privada no actualiza la variable del otro proceso. Que las direcciones impresas coincidan no implica por sí solo un mapeo de memoria escribible compartida.

Pregunta 7 de 10

Un proceso puede seguir calculando, pero el temporizador ha terminado su turno de CPU. ¿Cuál es ahora su estado básico?
  1. Bloqueado, esperando la finalización del temporizador
  2. Listo, esperando otro turno de CPU
  3. Detenido, esperando una señal de reanudación
  4. Zombi, esperando que su padre lo recoja
Mostrar respuestaOcultar respuesta
Respuesta: B
El proceso tiene trabajo disponible y solo necesita una CPU, por lo que está listo. Perder un turno no lo bloquea, porque ninguna operación de entrada/salida ni otro evento necesario impide su avance. Los estados detenido y zombi describen situaciones distintas: ejecución suspendida y ejecución terminada pendiente de recogida.

Pregunta 8 de 10

En una CPU lógica, M está en ejecución mientras N está bloqueado por una lectura. El dispositivo termina la lectura de N y el núcleo retorna a M. ¿Cuáles son los dos estados básicos inmediatamente después?
  1. M listo; N en ejecución
  2. M en ejecución; N bloqueado
  3. M en ejecución; N listo
  4. M bloqueado; N listo
Mostrar respuestaOcultar respuesta
Respuesta: C
La lectura completada elimina el motivo por el que N estaba bloqueado, por lo que N queda listo. M sigue ejecutándose porque el núcleo retornó a él. La finalización del dispositivo permite que N pueda ejecutarse, pero no exige que el planificador le dé la CPU inmediatamente; tratar la finalización como un cambio automático omite esa decisión.

Pregunta 9 de 10

Una utilidad de mantenimiento se ejecuta con identidad de root y solicita una operación protegida sobre un archivo. ¿En qué modo se ejecutan sus propias instrucciones de aplicación?
  1. Modo núcleo, porque root elude las comprobaciones de entrada
  2. Modo supervisor hasta que se cierre el archivo
  3. Modo usuario solo cuando el archivo solicitado es público
  4. Modo usuario, con permisos comprobados por el núcleo
Mostrar respuestaOcultar respuesta
Respuesta: D
Root es una identidad con permisos más amplios para solicitar servicios, no un modo de ejecución de la CPU. Las instrucciones de aplicación de la utilidad siguen ejecutándose en modo usuario y cruzan una ruta de entrada controlada para el trabajo del núcleo. El permiso para abrir un archivo protegido no convierte la utilidad en código del núcleo.

Pregunta 10 de 10

Un SO nuevo impone restricciones de modo usuario y una entrada protegida para llamadas al sistema, pero solo recupera la CPU cuando un programa realiza una llamada o provoca un fallo. Un programa de usuario entra en un bucle aritmético infinito. ¿Por qué puede fallar este diseño al compartir una CPU?
  1. El bucle puede evitar todas las rutas configuradas de regreso al SO.
  2. El bucle cede la CPU automáticamente cada vez que toma su siguiente bifurcación.
  3. El núcleo se ejecuta junto al bucle en la misma CPU lógica.
  4. La protección del modo usuario obliga a elegir un proceso listo tras cada instrucción.
Mostrar respuestaOcultar respuesta
Respuesta: A
El programa puede seguir ejecutando instrucciones permitidas sin realizar una llamada ni provocar una excepción. Entonces el SO no tiene un evento independiente que fuerce la entrada para poder ejecutar otro proceso. Las restricciones de privilegio protegen las operaciones, pero se necesita una interrupción del temporizador para recuperar el control sin cooperación.
Set 2: Crea, sustituye y recoge un proceso10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un padre recibe 7421 de una llamada a fork que tiene éxito. ¿Qué valor devuelve esa misma llamada a fork en el hijo?
  1. 7421
  2. -1
  3. 0
  4. El PID del padre
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Todas las llamadas a fork tienen éxito. ¿Cuántos procesos alcanzan puts("done") en este código?

if (fork() == 0) {
    fork();
}
puts("done");
  1. 2
  2. 3
  3. 4
  4. 5
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un programa de un solo hilo deja «ready» pendiente en un flujo de salida con almacenamiento completo en búfer y luego ejecuta fork correctamente. Ambos procesos llaman a exit sin producir más salida. ¿Qué puede recibir el destino?
  1. Ninguna copia, porque fork borra la salida pendiente
  2. Una copia, porque el flujo tiene un descriptor
  3. Una copia solo si el hijo termina primero
  4. Dos copias, porque cada proceso vacía un búfer copiado
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un proceso con PID 8502 ejecuta correctamente exec para un nuevo programa. ¿Cuál es el identificador de proceso del nuevo programa?
  1. 8502
  2. 8503
  3. 0
  4. El PID del padre
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un programa está instalado en /opt/course/bin/checker y PATH incluye /opt/course/bin. No hay ningún archivo llamado checker en el directorio actual. ¿Por qué execv("checker", args) no consigue localizarlo?
  1. Execv busca en PATH solo cuando args[0] es una ruta absoluta.
  2. Execv busca solo en el directorio del ejecutable que llama.
  3. Execv trata el nombre como una ruta y no busca en PATH.
  4. Execv busca en PATH solo después de fallar en el directorio actual.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un hijo llama a exit(515). Después de una espera que tiene éxito y de que WIFEXITED sea verdadero, ¿qué valor indica WEXITSTATUS?
  1. 515
  2. 512
  3. 255
  4. 3
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un padre tiene un hijo en ejecución. Su llamada a waitpid(child, &status, WNOHANG) devuelve 0. ¿Qué ha ocurrido?
  1. El hijo ha terminado correctamente.
  2. No hay ningún resultado del hijo listo, por lo que el padre continúa.
  3. El hijo ya no pertenece al padre.
  4. El padre ha recolectado un hijo con PID 0.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

El hijo de un servidor tiene el estado Z. Al enviar SIGKILL, la entrada sigue visible. ¿Qué acción libera el registro que conserva el resultado de este hijo?
  1. El padre lo recoge mediante una operación de espera.
  2. El hijo gestiona SIGTERM y llama a exit.
  3. El planificador concede al hijo otro turno de CPU.
  4. El padre envía SIGCONT y luego SIGSTOP.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un intérprete de comandos redirige la salida estándar de un hijo a un archivo y ejecuta un comando mediante exec. El comando escribe normalmente, termina correctamente y el intérprete vuelve a mostrar el indicador de entrada. ¿Qué explica que el comando no necesitara código de redirección?
  1. El padre reenvía la salida del hijo después de que wait retorne.
  2. Exec interpreta el texto de redirección en el vector de argumentos.
  3. La configuración de descriptores del hijo sobrevive a la sustitución del programa.
  4. Exec da al comando una copia nueva de los descriptores del padre.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un intérprete de comandos inicia producer | consumer. El productor termina, pero el consumidor espera indefinidamente después de leer todos los bytes disponibles. El intérprete cerró sus copias de la tubería; el consumidor aún mantiene abierto el descriptor original heredado del extremo de escritura. ¿Qué soluciona el bloqueo?
  1. Esperar al consumidor antes de cerrar el extremo de lectura del intérprete.
  2. Cerrar el extremo de escritura sin usar en el consumidor antes de exec.
  3. Cerrar el extremo de lectura del consumidor cuando termine el productor.
  4. Hacer que el intérprete recoja al productor antes de iniciar su lectura.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Sigue la entrada en el núcleo y los cambios de CPU10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

¿Por qué debe ser privilegiado el cambio de la tabla de manejadores de interrupciones?
  1. Para impedir que el código de usuario redirija la entrada protegida al núcleo
  2. Para garantizar que cada programa use un número de llamada al sistema distinto
  3. Para hacer que todos los eventos de hardware sean síncronos con las instrucciones de usuario
  4. Para exigir un proceso nuevo cada vez que se entra en un manejador
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Una función de C da formato a varios mensajes cortos en un búfer de salida y después los transfiere con una sola escritura. ¿Qué coste reduce esta agrupación?
  1. El número de caracteres a los que la aplicación debe dar formato
  2. La cantidad de memoria necesaria para el archivo ejecutable
  3. El número de procesos necesarios para contener los mensajes
  4. El trabajo repetido de entrada al núcleo y gestión de llamadas al sistema
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Una función envoltorio de C devuelve -1 desde open y errno es ENOENT. ¿Qué debe concluir quien llama?
  1. El archivo se abrió correctamente con un descriptor poco habitual.
  2. La solicitud falló porque no se encontró el archivo indicado.
  3. La solicitud creó un hijo que aún no ha terminado.
  4. El archivo se abrió, pero la cantidad de bytes se truncó.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un controlador de red informa de que llegó un paquete mientras un proceso sumaba enteros. ¿Qué tipo de evento de entrada en el núcleo es este?
  1. Una excepción aritmética síncrona
  2. Una trampa deliberada de llamada al sistema
  3. Una interrupción de hardware asíncrona
  4. Una señal de software enviada por la instrucción de suma
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una instrucción accede a una página válida que no está presente actualmente en memoria. El núcleo carga la página correctamente. ¿Cómo puede continuar la ejecución?
  1. Saltar la instrucción porque su resultado ya se almacenó.
  2. Terminar el proceso porque todas las excepciones son fatales.
  3. Crear un proceso nuevo para ejecutar las instrucciones restantes.
  4. Volver a intentar la instrucción con la página necesaria ya disponible.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

En un modelo de temporizador periódico con un pulso cada 5 ms, ¿cuántos pulsos del temporizador ocurren por segundo?
  1. 200
  2. 50
  3. 500
  4. 5000
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un proceso entra en el núcleo para solicitar un servicio no bloqueante. El manejador termina y retorna al mismo proceso. ¿Qué ocurrió?
  1. Un cambio de contexto sin ningún cambio de privilegio
  2. Una transición de modo sin cambio de contexto de proceso
  3. Un cambio de proceso que conservó el PID original
  4. Una sustitución del programa del proceso mediante exec
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

En una CPU lógica, A realiza una escritura no bloqueante que retorna a A; después, una interrupción del temporizador entra en el núcleo y retorna a A. Luego A realiza una lectura bloqueante y B se reanuda; más tarde B termina mediante una llamada al sistema y C se reanuda. No hay más entradas en el núcleo. ¿Cuántas entradas de usuario a núcleo y cambios de contexto de proceso ocurren?
  1. 4 entradas en el núcleo; 4 cambios de proceso
  2. 3 entradas en el núcleo; 2 cambios de proceso
  3. 4 entradas en el núcleo; 2 cambios de proceso
  4. 4 entradas en el núcleo; 3 cambios de proceso
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Una aplicación coloca una dirección de memoria protegida del núcleo en un argumento de búfer de escritura y realiza una llamada al sistema. ¿Por qué la entrada controlada por sí sola no autoriza la lectura solicitada desde esa dirección?
  1. El núcleo aún debe validar el acceso de quien llama al búfer.
  2. El número de servicio por sí solo autoriza todas las direcciones de búfer proporcionadas.
  3. La preparación de registros de la función envoltorio ya demuestra que se puede acceder al puntero.
  4. El cambio de modo hace que la memoria protegida forme parte del búfer de usuario.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un ciclo repetido de CPU proporciona 2 ms de ejecución útil seguidos de un coste de cambio de contexto de 8 µs. ¿Qué fracción aproximada del ciclo se dedica al cambio?
  1. 4,00 %
  2. 0,004 %
  3. 0,80 %
  4. 0,398 %
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Sigue el comportamiento de los procesos y la compartición de recursos10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Una CPU lógica ejecuta J durante 3 ms. Luego J espera 5 ms a una operación de entrada/salida y necesita 2 ms más de tiempo de CPU. K está listo inicialmente y necesita 6 ms de tiempo de CPU. K se ejecuta cuando J se bloquea y continúa hasta terminar; se ignora el coste de cambio. ¿Cuándo terminan ambos?
  1. 10 ms
  2. 11 ms
  3. 14 ms
  4. 16 ms
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

¿Qué valor almacenado permite al núcleo identificar la siguiente instrucción cuando reanuda un contexto de ejecución pausado?
  1. El directorio actual
  2. El desplazamiento dentro del archivo
  3. El PID del padre
  4. El contador de programa
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un proceso de un solo hilo tiene una variable privada x igual a 6. Todas las llamadas a fork tienen éxito. Todos los procesos alcanzan puts. ¿Cuántas líneas contienen «9»?

pid_t p = fork();
if (p == 0) x += 3;
fork();
if (x == 9) puts("9");
  1. 2
  2. 1
  3. 3
  4. 4
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Antes de una llamada a fork que tiene éxito, un descriptor de archivo hace referencia al desplazamiento 0 en un archivo abierto que contiene «ABCDEFGH». El padre lee exactamente tres bytes y luego el hijo lee exactamente dos bytes mediante el descriptor heredado. No ocurre ninguna otra operación. ¿Qué lee el hijo?
  1. «AB»
  2. «BC»
  3. «DE»
  4. «FG»
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Un hijo llama a execvp para un programa que no existe. Su siguiente instrucción imprime un error. ¿Por qué puede ejecutarse esa instrucción?
  1. Exec inicia el programa nuevo junto a la ruta de llamada anterior.
  2. Toda llamada a exec que tiene éxito retorna una vez antes de sustituir la memoria.
  3. El padre ejecuta automáticamente todas las instrucciones de error del hijo.
  4. La llamada a exec fallida retorna sin sustituir el programa anterior.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un padre con dos hijos activos llama a wait. Un manejador de señales interrumpe la espera, que devuelve -1 y establece errno en EINTR. ¿Qué debe hacer el padre para seguir recogiendo a sus hijos?
  1. Detenerse porque ambos hijos han sido recolectados.
  2. Volver a intentar la espera en lugar de tratar EINTR como una finalización.
  3. Decodificar el estado sin modificar con WEXITSTATUS.
  4. Enviar SIGKILL a su propia entrada en la tabla de procesos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un intérprete de comandos llama a chdir solo en un hijo creado mediante fork para implementar cd, espera a ese hijo y luego inicia otro comando. ¿Por qué comienza el siguiente comando en el directorio anterior?
  1. Wait siempre restablece el directorio del padre a su valor inicial.
  2. Exec ignora toda configuración heredada del directorio actual.
  3. El cambio de directorio del hijo no cambió el del intérprete padre.
  4. Chdir requiere que el propio intérprete se ejecute en modo núcleo.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un intérprete de comandos crea una tubería, crea mediante fork solo al productor y espera a que termine antes de crear al consumidor. El productor escribe más de lo que cabe en la tubería. ¿Por qué puede detenerse la secuencia de inicio?
  1. El productor se bloquea con la tubería llena y ningún consumidor puede vaciarla.
  2. La copia del extremo de lectura del padre consume bytes solo después de que wait retorne.
  3. El productor alcanza el fin de archivo cuando la tubería se llena por primera vez.
  4. El productor no puede cerrar su salida hasta que se recolecte al padre.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un servicio de dispositivo se ejecuta en un servidor separado en modo usuario y falla. El SO reinicia ese servicio mientras las aplicaciones no relacionadas continúan. ¿Qué característica del diseño del núcleo ayuda a explicar este resultado?
  1. Todos los servicios comparten el mismo espacio de direcciones privilegiado.
  2. Cada solicitud de dispositivo elude las reglas de protección del núcleo.
  3. El planificador garantiza que todas las aplicaciones se ejecuten en paralelo.
  4. El servicio está aislado de la pequeña parte central privilegiada.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

El mismo programa y la misma entrada causan un fallo de página en una ejecución, pero no en otra porque la página necesaria ya está presente en memoria. ¿Cómo debe clasificarse el fallo de la primera ejecución?
  1. Asíncrono, porque las dos ejecuciones fueron distintas
  2. Síncrono, porque lo causó la instrucción de memoria
  3. Una interrupción de hardware causada solo por el tiempo transcurrido
  4. Una señal creada directamente por el búfer de la biblioteca de C
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 5: Diagnostica las interacciones entre procesos y núcleo10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

El resultado de un hijo hace que WIFSIGNALED sea verdadero después de que waitpid tenga éxito. ¿Qué macro proporciona el número de la señal que lo terminó?
  1. WEXITSTATUS(status)
  2. WIFEXITED(status)
  3. WTERMSIG(status)
  4. WNOHANG
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Una función envoltorio de escritura informa de que se escribieron 5 bytes de un búfer de 9 bytes solicitado. ¿Cuántos bytes solicitados aún deben transferirse?
  1. 4 bytes
  2. 5 bytes
  3. 9 bytes
  4. 14 bytes
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un proceso lee una dirección no válida en Linux y el núcleo entrega SIGSEGV. ¿Qué secuencia distingue los dos eventos?
  1. Una señal al proceso va seguida de una excepción de memoria de la CPU.
  2. Una interrupción asíncrona de dispositivo se entrega directamente como SIGSEGV.
  3. Una trampa deliberada de llamada al sistema solicita la entrega de SIGSEGV.
  4. Una excepción de instrucción va seguida de una señal del SO al proceso.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un SO impone restricciones de modo usuario y recibe interrupciones del temporizador. Su manejador del temporizador guarda los registros de usuario, pero siempre retorna al mismo proceso. Una solución propuesta solo cambia la frecuencia con la que se activa el temporizador. Otros procesos siguen listos. ¿Por qué puede seguir fallando esta solución al darles turnos de CPU?
  1. La entrada del temporizador garantiza por sí misma turnos equitativos antes de que retorne el manejador.
  2. Recuperar el control proporciona un mecanismo, no una política de selección equitativa.
  3. Los límites del modo usuario hacen que cada proceso listo se ejecute en el siguiente pulso.
  4. Guardar los registros de usuario pasa automáticamente al siguiente proceso listo.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una carga de trabajo repite turnos útiles de CPU de 600 µs con un coste de cambio de 6 µs. Pasa a turnos de 1200 µs con el mismo coste. ¿Cómo cambia la proporción dedicada al cambio?
  1. Aumenta de aproximadamente 0,50 % a aproximadamente 0,99 %.
  2. Disminuye de aproximadamente 0,99 % a aproximadamente 0,50 %.
  3. Permanece en aproximadamente 1 % porque el coste de cambio no varía.
  4. Disminuye de aproximadamente 9,9 % a aproximadamente 5,0 %.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un intérprete de comandos abre un archivo de redirección de entrada y recibe el descriptor 0 porque la entrada estándar estaba cerrada. Llama a dup2(fd, 0), cierra fd incondicionalmente y ejecuta el comando mediante exec. ¿Por qué puede estar cerrada la entrada estándar del comando?
  1. Cerrar fd solo cierra una entrada antigua; el descriptor 0 sigue siendo una copia distinta.
  2. Exec cierra el descriptor 0 porque dup2 activó su indicador de cierre al ejecutar exec.
  3. dup2 rechaza números de descriptor iguales y elimina la entrada.
  4. Fd ya es 0, por lo que cerrar fd cierra la entrada deseada.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un programa tiene una variable privada x igual a 2. Todas las llamadas a fork tienen éxito. ¿Cuántos procesos imprimen «hit»?

pid_t p = fork();
if (p > 0) {
    x = 7;
    fork();
}
if (x == 7) puts("hit");
  1. 2
  2. 3
  3. 4
  4. 1
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un intérprete de comandos inicia dos hijos. Uno termina normalmente con estado 0; el otro es terminado por una señal. El intérprete debe informar de ambos resultados. ¿Qué enfoque de gestión de resultados se necesita?
  1. Recoger a ambos hijos una vez y decodificar ambos como salidas normales.
  2. Recoger un resultado y decodificarlo una vez como salida y otra como señal.
  3. Recoger ambos resultados y elegir las macros de decodificación por separado para cada uno.
  4. Recoger ambos resultados y decodificar sus enteros sin procesar como códigos de salida.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

A se bloquea en una lectura de terminal y B se ejecuta. Después de que la entrada haga que A quede listo, el planificador selecciona A. Un cambio propuesto restaura el contador de programa de usuario de A, pero conserva la pila del núcleo y el contexto del espacio de direcciones de B. ¿Por qué no puede esto reanudar correctamente la lectura pendiente de A?
  1. El marco de retorno de usuario de A restaura automáticamente el resto de su ruta en el núcleo.
  2. Cambiar el contador de programa de usuario también selecciona la pila del núcleo correspondiente.
  3. La lectura puede terminar en la pila del núcleo de B usando solo los registros de usuario de A.
  4. Deben seleccionarse el contexto del núcleo, la pila y el contexto del espacio de direcciones propios de A.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un programa de usuario conoce la dirección de una rutina del núcleo y el número de una llamada al sistema válida. ¿Por qué puede solicitar el servicio, pero no simplemente llamar a esa dirección privilegiada como una función normal?
  1. Una trampa entra en una ruta configurada del núcleo que valida y despacha la solicitud.
  2. Una llamada directa obtiene privilegios cuando su destino coincide con un número de servicio válido.
  3. Un número de servicio concede a quien llama acceso al núcleo antes de comprobar sus argumentos.
  4. Una llamada directa y una trampa heredan privilegios solo de la dirección de destino.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

75 Términos Clave, cada uno con su definición

A

Abstracción
Una abstracción es una interfaz o modelo útil que oculta detalles de implementación de nivel inferior mientras conserva las operaciones que necesitan los programas.
La abstracción de archivo permite que un programa lea bytes sin conocer el formato de comandos del dispositivo de almacenamiento.
Anillo de protección
Un anillo de protección es un nivel de privilegio del hardware x86; los sistemas habituales usan normalmente el anillo 0 para los núcleos y el anillo 3 para las aplicaciones.
El paso del anillo 3 de aplicación al anillo 0 del núcleo sigue una ruta de entrada controlada configurada por el SO.

B

Bifurcación
La bifurcación es la operación de creación de procesos de Unix que crea un hijo y retorna tanto al padre como al hijo después de la misma llamada.
Después de una bifurcación que tiene éxito, el padre recibe el PID del hijo y el hijo recibe un valor de retorno de 0.
Bloque de control de proceso (PCB)
Un bloque de control de proceso (PCB) es el registro del núcleo de un proceso, que incluye su identidad, estado, recursos y contexto guardado.
El núcleo consulta un bloque de control de proceso para encontrar la información de memoria y el padre de un proceso detenido.
Búfer de salida
Un búfer de salida es almacenamiento en espacio de usuario que contiene salida con formato antes de que una biblioteca transfiera esos bytes al núcleo.
El texto pendiente en un búfer de salida puede copiarse mediante fork y vaciarse más tarde una vez por cada proceso.
Búfer de traducción adelantada (TLB)
Un búfer de traducción adelantada (TLB) almacena traducciones de direcciones en caché para que la CPU evite buscarlas repetidamente en memoria.
Un cambio de proceso puede requerir volver a cargar traducciones, aunque las entradas etiquetadas pueden conservar traducciones útiles en caché.

C

Cambio de contexto
Un cambio de contexto guarda un contexto de ejecución y restaura otro; un cambio de proceso también selecciona el espacio de direcciones adecuado.
Cuando un lector se bloquea, un cambio de contexto permite que un cálculo listo se reanude en la misma CPU lógica.
Cambio de modo
Un cambio de modo cambia el nivel de privilegio de la CPU, como al entrar en el núcleo para un servicio y retornar al mismo proceso de usuario.
Una llamada al sistema no bloqueante puede implicar cambios de modo sin reanudar un proceso distinto.
Cierre al ejecutar exec
El cierre al ejecutar exec es un indicador de descriptor que solicita el cierre automático de ese descriptor cuando un proceso sustituye correctamente su programa.
Un intérprete de comandos puede impedir que un descriptor interno llegue al comando marcándolo para cierre al ejecutar exec.
Comando interno
Un comando interno es una operación implementada por el propio intérprete de comandos, lo que le permite cambiar el estado persistente de su propio proceso.
El comando interno cd cambia el directorio del intérprete para que los comandos posteriores hereden el directorio recién seleccionado.
Compartición espacial
La compartición espacial divide la capacidad de un recurso en partes que distintos procesos o usuarios poseen al mismo tiempo.
Las regiones de memoria separadas pueden permanecer asignadas a varios procesos mientras solo uno dispone de la CPU.
Concurrencia
La concurrencia significa que varias actividades están en curso durante el mismo periodo, incluso cuando sus instrucciones se intercalan.
Dos programas son concurrentes en una CPU lógica cuando cada uno recibe turnos repetidamente antes de que termine cualquiera de ellos.
Contador de programa
El contador de programa es un registro de la CPU que contiene la dirección de la siguiente instrucción en un contexto de ejecución.
Restaurar el contador de programa permite que un proceso pausado continúe en la instrucción correcta después de un cambio.
Contexto del núcleo
Un contexto del núcleo es el estado guardado de registros y pila necesario para reanudar la ruta de ejecución del núcleo de un proceso suspendido.
Al cambiar al proceso B, la rutina de cambio restaura el contexto del núcleo de B antes de que el código de salida del núcleo pueda restaurar los registros de usuario de B.
Control cooperativo
El control cooperativo depende de que los programas cedan la CPU, realicen llamadas al sistema o provoquen excepciones para que el SO vuelva a ejecutarse en la CPU.
Un bucle infinito de usuario revela la debilidad del control cooperativo si nunca alcanza ninguna ruta de regreso al SO.
Copia en escritura
La copia en escritura comparte inicialmente páginas protegidas de memoria física y crea copias privadas cuando las escrituras requieren contenidos separados.
Un hijo que llama inmediatamente a exec puede descartar las páginas heredadas sin copiar primero cada página.

D

Descripción de archivo abierto
Una descripción de archivo abierto es el estado que mantiene el núcleo para un archivo abierto, incluido su desplazamiento, y que varios descriptores pueden compartir.
Las lecturas del padre y del hijo mediante un descriptor heredado hacen avanzar el desplazamiento de una misma descripción de archivo abierto.
Descriptor de archivo
Un descriptor de archivo es un entero pequeño de la tabla de descriptores de un proceso que hace referencia a un archivo abierto u otro recurso de entrada/salida.
Un intérprete de comandos conecta el descriptor de archivo 1 a un archivo antes de ejecutar un comando cuya salida se redirige.

E

Ejecución directa limitada
La ejecución directa limitada ejecuta instrucciones de usuario en el hardware mientras los límites de privilegio y la entrada provocada por el temporizador conservan el control del SO.
Una aplicación en bucle se ejecuta directamente, pero sigue sin poder desactivar el temporizador que puede interrumpirla.
errno
errno es un indicador de error de la biblioteca de C que muchas interfaces establecen cuando fallan y que se consulta después de que el valor de retorno indique un error.
Una llamada fallida a open puede establecer errno en ENOENT, mientras que una llamada posterior que tiene éxito no tiene por qué borrar ese valor anterior.
Espacio de direcciones
Un espacio de direcciones es el conjunto de direcciones de memoria disponibles para un proceso y el código, los datos, el montículo y la pila mapeados en esa vista.
Las direcciones virtuales iguales en dos espacios de direcciones privados pueden hacer referencia a valores distintos en la memoria física.
Espera no bloqueante
Una espera no bloqueante comprueba si hay un resultado de un hijo disponible y retorna sin suspender a quien llama cuando no hay ningún resultado listo.
Un intérprete de comandos usa una espera no bloqueante para recoger trabajos en segundo plano terminados mientras mantiene disponible el indicador de entrada.
Estado bloqueado
El estado bloqueado significa que un proceso no puede continuar hasta que ocurra un evento, como que esté disponible la entrada solicitada.
Una lectura bloqueante de terminal pone un proceso en estado bloqueado hasta que la entrada permite continuar la solicitud.
Estado de ejecución
El estado de ejecución significa que un proceso está ejecutando instrucciones en una CPU en ese momento, en lugar de estar listo para ejecutarse o esperando un evento.
Cuando un compilador listo recibe una CPU, entra en estado de ejecución y puede ejecutar su siguiente instrucción.
Estado de salida
Un estado de salida es el pequeño resultado que un proceso comunica al terminar normalmente, por convenio 0 para éxito y un valor distinto de cero para fallo.
Después de comprobar que la terminación fue normal, el padre extrae el estado de salida con la macro de espera adecuada.
Estado devuelto por wait
Un estado devuelto por wait es un valor codificado que describe cómo terminó o cambió de estado un hijo y se interpreta mediante las macros de espera correspondientes.
En Linux, un estado devuelto por wait sin decodificar de 768 puede codificar el código de salida normal 3, por lo que imprimirlo directamente da un código incorrecto.
Estado listo
El estado listo significa que un proceso puede ejecutarse, pero espera a que haya una CPU disponible o a que el planificador lo seleccione.
Un temporizador puede pasar un cálculo sin terminar del estado de ejecución al estado listo sin ninguna operación de entrada/salida.
Excepción
Una excepción es un evento que surge de la instrucción actual y requiere una gestión especial de la CPU y del núcleo, como un fallo de página.
Un acceso prohibido a memoria genera una excepción antes de que la aplicación pueda continuar normalmente.

F

Fallo de página
Un fallo de página es un evento causado por una instrucción de acceso a memoria cuya traducción o permisos requieren una gestión especial.
Una página válida ausente puede cargarse después de un fallo de página, lo que permite al núcleo volver a intentar la instrucción interrumpida.
Fin de archivo (EOF)
El fin de archivo es un resultado de lectura que indica que no hay más datos disponibles; en una tubería requiere un búfer vacío y que no haya escritores abiertos.
Un lector puede esperar en lugar de recibir el fin de archivo si el intérprete de comandos conserva accidentalmente un extremo de escritura de la tubería.
Función envoltorio de biblioteca
Una función envoltorio de biblioteca es código de espacio de usuario que presenta una interfaz invocable y prepara los argumentos y la entrada para un servicio del núcleo.
La función envoltorio de biblioteca de write sigue el convenio de registros de llamadas al sistema antes de entrar en el núcleo.

I

Identificador de proceso (PID)
Un identificador de proceso (PID) es un identificador numérico asignado a un proceso y único entre los procesos activos del mismo espacio de nombres de PID.
Un listado de procesos usa el PID y el PID del padre para mostrar que un comando fue iniciado por un intérprete de comandos concreto.
Instrucción privilegiada
Una instrucción privilegiada cambia el estado protegido de la máquina y no puede ser ejecutada libremente por código normal en modo usuario.
Desactivar las interrupciones es una operación privilegiada porque, de otro modo, podría impedir que el SO recuperara el control.
Intérprete de comandos
Un intérprete de comandos es un programa de usuario que interpreta comandos y usa operaciones de procesos y descriptores para iniciar y conectar otros programas.
Un intérprete de comandos en primer plano espera al proceso hijo de su comando antes de mostrar el siguiente indicador de entrada.
Interrupción de hardware
Una interrupción de hardware es una notificación de un dispositivo o temporizador que hace que la CPU gestione un evento independientemente de la instrucción actual.
Un controlador de almacenamiento genera una interrupción de hardware cuando se completa una transferencia solicitada anteriormente.
Interrupción del temporizador
Una interrupción del temporizador es un evento de hardware procedente de un temporizador configurado que da al núcleo la oportunidad de recuperar el control de una CPU.
Una interrupción del temporizador puede entrar en el núcleo incluso mientras el proceso actual ejecuta un bucle sin llamadas al sistema.
Intervalo de tiempo asignado
Un intervalo de tiempo asignado es un periodo de ejecución de CPU concedido a un trabajo antes de que la planificación pueda dar un turno a otro proceso disponible.
Con un coste de cambio fijo, acortar un intervalo de tiempo asignado aumenta la fracción de tiempo dedicada a los cambios.

L

Llamada al sistema
Una llamada al sistema es una solicitud controlada de un programa de usuario para obtener un servicio del núcleo, realizada mediante una interfaz de entrada definida.
Abrir un archivo requiere una llamada al sistema porque el código del núcleo gestiona el acceso al recurso de archivo abierto.

M

Mecanismo
Un mecanismo es el medio para realizar una operación del SO, como conservar el estado de un proceso y restaurar el de otro.
El mecanismo de cambio de contexto permite aplicar varias reglas para decidir qué proceso listo se ejecuta a continuación.
Micronúcleo
Un micronúcleo mantiene una pequeña parte central privilegiada y sitúa más servicios del SO en procesos separados en modo usuario que se comunican mediante mensajes.
Un controlador en modo usuario que falla en un diseño de micronúcleo a menudo puede reiniciarse mientras otros servicios continúan.
Modo núcleo
El modo núcleo es el nivel de privilegio de la CPU que permite al SO gestionar el estado protegido del hardware y ejecutar instrucciones privilegiadas.
La CPU entra en modo núcleo para gestionar una solicitud realizada por la aplicación de un usuario normal.
Modo usuario
El modo usuario es el nivel de privilegio de la CPU que ejecuta instrucciones de aplicación con acceso restringido a la memoria y a las operaciones protegidas.
El editor de un administrador sigue ejecutándose en modo usuario y usa llamadas al sistema para solicitar servicios protegidos.
Multiprogramación
La multiprogramación mantiene varios trabajos disponibles en memoria para que uno pueda usar la CPU mientras otro está bloqueado por una operación de entrada/salida.
La multiprogramación permite que un compilador calcule mientras otro proceso espera a que termine una lectura de almacenamiento.

N

Nivel de excepción
Un nivel de excepción es un nivel de privilegio de ejecución de AArch64, que incluye EL0 para aplicaciones y normalmente EL1 para el núcleo del SO.
AArch64 nombra los niveles de privilegio de forma distinta a los anillos de x86, pero sigue separando las aplicaciones del núcleo.
Núcleo
El núcleo es la parte central privilegiada de un sistema operativo que controla las operaciones protegidas del hardware y gestiona los recursos de los procesos.
Una aplicación de terminal pide al núcleo que lea la entrada en lugar de controlar ella misma el dispositivo de teclado.
Núcleo monolítico
Un núcleo monolítico ejecuta la mayoría de los servicios del SO juntos en modo núcleo, lo que permite llamadas directas, pero comparte los riesgos de los fallos en código privilegiado.
Un módulo de controlador de Linux se incorpora al núcleo monolítico y puede dañar el estado del núcleo si contiene un error grave.
Número de llamada al sistema
Un número de llamada al sistema es un identificador específico de la arquitectura que el núcleo despacha a una implementación de servicio concreta.
Linux usa números de llamada al sistema distintos para write en x86-64 y AArch64, por lo que los números directos no son portables.

P

Paralelismo
El paralelismo significa que el trabajo se ejecuta en el mismo instante en recursos de procesamiento separados, como distintas CPU lógicas.
Un compilador y un programa de renderizado pueden ejecutarse en paralelo cuando cada uno se ejecuta en una CPU lógica distinta.
PATH
PATH es una variable de entorno que enumera los directorios en los que interfaces como execvp buscan nombres de ejecutables.
Un comando encontrado mediante PATH puede iniciarse con execvp aunque su archivo no esté en el directorio actual.
Pila del núcleo
Una pila del núcleo contiene el estado de usuario guardado y los datos de ejecución del núcleo mientras este se ejecuta en nombre de un proceso o contexto de ejecución.
Cambiar a otro proceso incluye restaurar la pila del núcleo usada por la ruta de retorno guardada de ese proceso.
Planificador
El planificador es el componente del SO que elige qué contexto de ejecución disponible debe recibir tiempo de CPU a continuación.
Después de que termina una lectura de disco, el planificador puede mantener el proceso actual en ejecución antes de seleccionar al lector.
Política
Una política es una regla para elegir cómo usar los mecanismos disponibles, como decidir qué proceso listo debe recibir tiempo de CPU.
Una política de planificación puede cambiar mientras el código de guardado de registros usado para cambiar de proceso sigue siendo el mismo.
Procesamiento por lotes
El procesamiento por lotes reúne los trabajos enviados y los ejecuta sin entrada interactiva de la persona que envió cada trabajo.
En el procesamiento por lotes, un cálculo enviado espera a los trabajos anteriores en lugar de recibir un turno inmediato.
Proceso
Un proceso es una instancia activa de un programa junto con la memoria, los valores de registros y el estado de entrada/salida necesarios para su ejecución.
Dos procesos que ejecutan el mismo archivo ejecutable pueden mantener distintas variables privadas y directorios actuales.
Proceso hijo
Un proceso hijo es un proceso nuevo creado por un padre, con su propia identidad y una copia de la memoria privada ordinaria del padre.
El proceso hijo puede cambiar una variable privada después de fork sin cambiar el valor del padre.
Proceso huérfano
Un proceso huérfano es un proceso cuyo padre ha terminado y al que se asigna un nuevo padre para que otro proceso pueda recoger más tarde su resultado.
Un huérfano puede seguir calculando después de que termine su padre original; no necesariamente ha terminado.
Proceso padre
Un proceso padre es el proceso que crea un hijo; puede usar operaciones de espera para recoger el resultado de terminación de ese hijo.
Un intérprete de comandos sigue siendo el proceso padre mientras su hijo sustituye su propio programa por un comando externo.
Proceso zombi
Un proceso zombi es un proceso terminado cuyo registro de resultados permanece en el núcleo porque su padre aún no ha recogido ese resultado.
Un servidor de larga duración evita la acumulación de zombis recolectando a los hijos que han terminado.
Programa
Un programa consiste en instrucciones y datos almacenados que pueden cargarse para su ejecución; el archivo en sí no tiene un estado de ejecución cambiante.
El mismo archivo de programa de un intérprete de comandos puede usarse para iniciar procesos separados en tres ventanas de terminal.
Puntero de pila
El puntero de pila es un registro que localiza la posición actual de una pila usada para llamadas a funciones y estado de ejecución.
Un cambio de contexto restaura el puntero de pila para que la ejecución reanudada use su propia pila guardada.

R

Recolección de procesos terminados
La recolección de procesos terminados consiste en recoger el resultado de un hijo terminado mediante una operación de espera para que el núcleo pueda liberar el registro de proceso restante.
Una espera que tiene éxito recolecta un hijo; un padre con varios hijos debe seguir recogiendo resultados.
Redirección
La redirección cambia el descriptor de entrada estándar, salida estándar o error estándar de un comando para que haga referencia a otro recurso de entrada/salida abierto.
La redirección de salida permite que un programa sin modificar escriba su salida estándar habitual en un archivo elegido.
Retorno de trampa
Un retorno de trampa restaura el estado de ejecución guardado y vuelve de la gestión del núcleo al contexto de ejecución de usuario previsto.
El SO puede preparar el estado inicial de un proceso nuevo para que la ruta de restauración inicie ese programa por primera vez.

S

Señal
Una señal es una notificación de software que el SO entrega a un proceso, con una acción predeterminada o un comportamiento de gestión instalado.
Una terminal envía SIGINT a su trabajo en primer plano cuando el usuario pulsa Ctrl-C, lo que normalmente termina el trabajo.
Sistema operativo
Un sistema operativo gestiona los recursos de hardware y proporciona servicios que permiten a los programas ejecutarse, comunicarse y almacenar datos de forma segura.
El sistema operativo comparte el tiempo de CPU entre un navegador y un compilador mientras gestiona sus solicitudes de archivos.
Sobrecarga
La sobrecarga es el tiempo o la memoria adicionales que se dedican a gestionar una operación en lugar de realizar directamente el trabajo útil de la aplicación.
Guardar registros durante un cambio de contexto añade sobrecarga antes de que otro proceso reanude sus cálculos.
Sustitución del programa
La sustitución del programa mediante exec reemplaza la imagen de programa del proceso que llama por un programa nuevo, mientras conserva la identidad del proceso y determinados recursos.
El hijo conserva su PID cuando exec sustituye el código del intérprete de comandos por el código del comando solicitado.

T

Tabla de trampas
Una tabla de trampas asigna tipos de eventos a destinos protegidos de manejadores del núcleo; su organización exacta depende de la CPU.
Durante el arranque, el SO prepara los destinos de los manejadores para que el código de usuario no pueda redirigir una entrada posterior en el núcleo.
Tiempo compartido
El tiempo compartido divide el acceso a un recurso en turnos sucesivos, lo que permite que varios procesos o usuarios lo compartan a lo largo del tiempo.
El tiempo compartido da a un editor otro turno de CPU mientras un cálculo largo sigue en curso.
Trabajo en segundo plano
Un trabajo en segundo plano es un trabajo que se inicia sin que el intérprete de comandos espere inmediatamente a que termine, lo que permite seguir introduciendo comandos.
El intérprete de comandos muestra el indicador de entrada mientras se ejecuta un trabajo en segundo plano, pero debe recolectar al hijo cuando ese trabajo termine.
Trampa
Una trampa de llamada al sistema es una entrada deliberada en el núcleo causada por la solicitud de servicio de un programa, mediante una instrucción de entrada protegida.
La solicitud de escribir una salida provoca una trampa de llamada al sistema incluso cuando no hay ningún error en el programa.
Tubería
Una tubería es un canal unidireccional de bytes gestionado por el núcleo, con un extremo de lectura y otro de escritura, que puede conectar procesos que cooperan.
Un intérprete de comandos conecta la salida de un productor a una tubería y la entrada de un consumidor al extremo de lectura de esa misma tubería.

U

Utilización de la CPU
La utilización de la CPU es la fracción de un intervalo transcurrido durante la cual la CPU está ocupada, expresada como proporción o porcentaje.
Si los cálculos útiles ocupan 9 ms en un seguimiento de 12 ms sin sobrecarga, la utilización de la CPU es del 75 %.

V

Vector de argumentos
Un vector de argumentos es un array de punteros a cadenas, terminado en un puntero nulo, que se proporciona a un nuevo programa como sus argumentos de línea de comandos.
Un vector de argumentos para un comando de recuento tiene entradas separadas para el nombre del programa, la opción y el nombre del archivo.
Virtualización
La virtualización presenta un recurso físico compartido como un recurso virtual cómodo que cada programa puede usar mediante una vista más sencilla.
La virtualización de la CPU permite que cientos de procesos avancen en una máquina con solo unas pocas CPU lógicas.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar