GNU/Linux >> Tutoriales Linux >  >> Linux

Pérdida de tiempo de execv() y fork()

Ya no más. Hay algo llamado COW (Copiar al escribir), solo cuando uno de los dos procesos (principal/secundario) intenta escribir en un dato compartido, se copia.

En el pasado:
El fork() La llamada del sistema copió el espacio de direcciones del proceso de llamada (el padre) para crear un nuevo proceso (el hijo). La copia del espacio de direcciones del padre en el hijo fue la parte más costosa del fork() operación.

Ahora:
Una llamada a fork() es seguido casi inmediatamente por una llamada a exec() en el proceso hijo, que reemplaza la memoria del hijo con un nuevo programa. Esto es lo que normalmente hace el shell, por ejemplo. En este caso, el tiempo dedicado a copiar el espacio de direcciones del padre se desperdicia en gran medida, porque el proceso hijo usará muy poca memoria antes de llamar a exec() .

Por esta razón, las versiones posteriores de Unix aprovecharon el hardware de memoria virtual para permitir que el padre y el hijo compartieran la memoria asignada a sus respectivos espacios de direcciones hasta que uno de los procesos la modificara. Esta técnica se conoce como copia sobre escritura. . Para hacer esto, en fork() el kernel copiaría las asignaciones de espacio de direcciones del padre al hijo en lugar del contenido de las páginas asignadas y, al mismo tiempo, marcaría las páginas ahora compartidas como de solo lectura. Cuando uno de los dos procesos intenta escribir en una de estas páginas compartidas, el proceso detecta un error de página. En este punto, el kernel de Unix se da cuenta de que la página era realmente una copia "virtual" o de "copia en escritura", por lo que crea una copia nueva, privada y grabable de la página para el proceso de error. De esta forma, los contenidos de las páginas individuales no se copian hasta que se escriben. Esta optimización hace un fork() seguido de un exec() en el niño mucho más barato:el niño probablemente solo necesitará copiar una página (la página actual de su pila) antes de llamar a exec() .


¿Cuál es la ventaja que se logra al usar este combo (en lugar de alguna otra solución) que hace que la gente siga usando esto aunque tengamos desperdicios?

Tienes que crear un nuevo proceso de alguna manera. Hay muy pocas maneras de que un programa de espacio de usuario logre eso. POSIX solía tener vfork() junto al lado fork() , y algunos sistemas pueden tener sus propios mecanismos, como clone() específico de Linux , pero desde 2008, POSIX especifica solo fork() y el posix_spawn() familia. El fork + exec La ruta es más tradicional, se entiende bien y tiene pocos inconvenientes (ver más abajo). El posix_spawn la familia está diseñada como un propósito especial sustituto para uso en contextos que presentan dificultades para fork(); puede encontrar detalles en la sección "Fundamento" de su especificación.

Este extracto de la página man de Linux para vfork() puede ser esclarecedor:

En Linux, fork (2) se implementa utilizando páginas de copia en escritura, por lo que la única penalización incurrida por fork (2) es el tiempo y la memoria necesarios para duplicar las tablas de páginas de los padres y crear una estructura de tareas única para el hijo . Sin embargo, en los viejos tiempos, un fork (2) requeriría hacer una copia completa del espacio de datos de la persona que llama, a menudo innecesariamente, ya que generalmente inmediatamente después aparece un exec (3) está hecho. Por lo tanto, para una mayor eficiencia, BSD introdujo el vfork () llamada al sistema, que no copió completamente el espacio de direcciones del proceso padre, pero tomó prestada la memoria del padre y el hilo de control hasta una llamada a execve (2) o se produjo una salida. El proceso padre se suspendió mientras el hijo estaba usando sus recursos. El uso de vfork () era complicado:por ejemplo, no modificar datos en el proceso principal dependía de saber qué variables se mantienen en un registro.

(Énfasis añadido)

Por lo tanto, su preocupación por el desperdicio no está bien fundada para los sistemas modernos (no se limita a Linux), pero de hecho fue un problema históricamente y, de hecho, hubo mecanismos diseñados para evitarlo. Actualmente, la mayoría de esos mecanismos están obsoletos.


Otra respuesta dice:

Sin embargo, en los viejos tiempos, una bifurcación (2) requería hacer una copia completa del espacio de datos de la persona que llama, a menudo innecesariamente, ya que generalmente se realiza inmediatamente después un exec (3).

Obviamente, los malos viejos tiempos de una persona son mucho más jóvenes de lo que otros recuerdan.

Los sistemas UNIX originales no tenían la memoria para ejecutar múltiples procesos y no tenían una MMU para mantener varios procesos en la memoria física listos para ejecutarse en el mismo espacio de direcciones lógicas:intercambiaron procesos en el disco que no era actualmente en ejecución.

La llamada al sistema de bifurcación fue casi completamente igual que cambiar el proceso actual al disco, excepto por el valor devuelto y por no reemplazando la copia restante en memoria intercambiando en otro proceso. Dado que tenía que cambiar el proceso principal de todos modos para ejecutar el secundario, fork+exec no incurría en ningún gasto general.

Es cierto que hubo un período de tiempo en el que fork+exec era incómodo:cuando había MMU que proporcionaban un mapeo entre el espacio de direcciones lógico y físico, pero las fallas de página no retenían suficiente información como para copiar en escritura y una serie de otros virtuales. -los esquemas de paginación de memoria/demanda eran factibles.

Esta situación fue lo suficientemente dolorosa, no solo para UNIX, que el manejo de fallas de página del hardware se adaptó para volverse "reproducible" bastante rápido.


Linux
  1. ¿Sustitución de proceso y tubería?

  2. Estados de proceso de Linux

  3. La diferencia entre fork(), vfork(), exec() y clone()

  4. Llamada al sistema fork() y función execv

  5. Obtener la hora actual en horas y minutos

Servidor NTP y mejores prácticas

Cómo suspender un proceso y reanudarlo más tarde en Linux

Cómo configurar la fecha, la hora y la zona horaria en RHEL 8

Cómo encontrar la fecha y hora de instalación del sistema operativo Linux

Cómo configurar la fecha y la hora en Linux

marca de tiempo, hora de modificación y hora de creación de un archivo