¿Cuál es la diferencia entre fork () y vfork ()?

13

Me gustaría entender en detalle la diferencia entre fork () y vfork (). No pude digerir la página de manual por completo.

También me gustaría aclarar el comentario de uno de mis colegas " En Linux actual, no hay vfork (), incluso si lo llamas, internamente llamará fork () ".

Sen
fuente

Respuestas:

24

Las páginas de manual suelen ser documentos de referencia concisos. Wikipedia es un mejor lugar para buscar explicaciones conceptuales.

Fork duplica un proceso: crea un proceso hijo que es casi idéntico al proceso padre (la diferencia más obvia es que el nuevo proceso tiene una ID de proceso diferente). En particular, fork (conceptualmente) debe copiar toda la memoria del proceso padre.

Como esto es bastante costoso, vfork fue inventado para manejar un caso especial común donde la copia no es necesaria. A menudo, lo primero que hace el proceso secundario es cargar una nueva imagen del programa, así que esto es lo que sucede:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

La execvellamada carga un nuevo programa ejecutable, y esto reemplaza el código del proceso y la memoria de datos por el código del nuevo ejecutable y una nueva memoria de datos. Así que toda la copia de memoria creada por forkfue para nada.

Así vforkse inventó la llamada. No hace una copia de la memoria. Por vforklo tanto, es barato, pero es difícil de usar ya que debe asegurarse de no acceder a ninguno de los espacios de pila o montón del proceso en el proceso secundario. Tenga en cuenta que incluso la lectura podría ser un problema, porque el proceso principal sigue ejecutándose. Por ejemplo, este código está roto (puede o no funcionar dependiendo de si el niño o el padre obtienen un intervalo de tiempo primero):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Desde la invención de vfork, se han inventado mejores optimizaciones. La mayoría de los sistemas modernos, incluido Linux, utilizan una forma de copia en escritura , donde las páginas en la memoria del proceso no se copian en el momento de la forkllamada, sino más tarde cuando el padre o hijo escribe por primera vez en la página. Es decir, cada página comienza como compartida y permanece compartida hasta que cualquiera de los procesos escribe en esa página; El proceso que escribe obtiene una nueva página física (con la misma dirección virtual). Copy-on-write hace que vfork sea inútil en su mayoría, ya forkque no hará ninguna copia en los casos en vforkque sería utilizable.

Linux retiene vfork. La forkllamada al sistema aún debe hacer una copia de la tabla de memoria virtual del proceso, incluso si no copia la memoria real; vforkNi siquiera necesita hacer esto. La mejora del rendimiento es insignificante en la mayoría de las aplicaciones.

Gilles 'SO- deja de ser malvado'
fuente
1
Gracias por esta brillante respuesta. Al hacer fork (), el niño de todos modos obtendrá un nuevo ID de proceso y su espacio virtual asociado, entonces ¿por qué debería hacer una copia de la tabla de memoria virtual del proceso? No estoy claro en esa parte.
Sen
@Sen: forknecesita crear una asignación de memoria virtual separada para que las copias posteriores de copia en escritura solo afecten a uno de los dos procesos.
Gilles 'SO- deja de ser malvado'
¿estás seguro de que el proceso principal se está ejecutando?
qbolec
2

Los fork()y vfork()syscalls son diferentes.

La fork()llamada al sistema genera dos procesos idénticos con memoria separada. La vfork()llamada al sistema genera dos procesos que comparten la misma memoria.

Con vfork()el padre esperará a que el hijo termine. El padre hereda de las variables que comparte el programa. Entonces, después de que se llamó al niño, todas las variables modificadas dentro del niño aún se modificarán dentro del padre.

Para más información haga clic aquí.

Yogeesh HT
fuente