Específicamente, ¿cómo maneja fork() la memoria dinámicamente asignada de malloc () en Linux?


Tengo un programa con un proceso padre y un proceso hijo. Antes de la bifurcación(), el proceso padre llamó a malloc () y llenó una matriz con algunos datos. Después de la bifurcación (), el hijo necesita esos datos. Sé que podría usar una tubería, pero el siguiente código parece funcionar:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main( int argc, char *argv[] ) {
    char *array;
    array = malloc( 20 );
    strcpy( array, "Hello" );
    switch( fork() ) {
    case 0:
        printf( "Child array: %s\n", array );
        strcpy( array, "Goodbye" );
        printf( "Child array: %s\n", array );
        free( array );
        break;
    case -1:
        printf( "Error with fork()\n" );
        break;
    default:
        printf( "Parent array: %s\n", array );
        sleep(1);
        printf( "Parent array: %s\n", array );
        free( array );
    }
    return 0;
}

La salida es:

Parent array: Hello
Child array: Hello
Child array: Goodbye
Parent array: Hello

Sé que los datos asignados en la pila están disponibles en el hijo, pero parece que los datos asignados en el montón también están disponibles para el hijo. Y del mismo modo, el niño no se pueden modificar los datos del padre en la pila, el hijo no puede modificar los datos del padre en el montón. Así que asumo que el niño obtiene su propia copia de los datos de pila y montón.

¿Es esto siempre el caso en Linux? Si es así, ¿dónde está la documentación que respalda esto? Revisé la página man de fork (), pero no mencionó específicamente la memoria dinámicamente asignada en el montón.

Gracias

Author: Greg Hewgill, 2011-01-04

3 answers

Cada página que se asigna para el proceso (ya sea una página de memoria virtual que tiene la pila o el montón) se copia para que el proceso bifurcado pueda acceder a ella.

En realidad, no se copia directamente al principio, se establece en Copy-on-Write, lo que significa que una vez que uno de los procesos (padre o hijo) intenta modificar una página, se copia para que no se dañe entre sí, y todavía tiene todos los datos desde el punto de bifurcación() accesibles para ellos.

Por ejemplo, el código las páginas, aquellas a las que el ejecutable real fue mapeado en memoria, generalmente son de solo lectura y por lo tanto se reutilizan entre todos los procesos bifurcados-no se copiarán de nuevo, ya que nadie escribe allí, solo se leen, por lo que nunca será necesario copiar - sobre-escribir.

Más información está disponible aquí y aquí.

 32
Author: abyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-04 20:10:15

Después de una bifurcación, el hijo es completamente independiente del padre, pero puede heredar ciertas cosas que son copias del padre. En el caso del montón, el hijo tendrá conceptualmente una copia del montón de los padres en el momento de la bifurcación. Sin embargo, las modificaciones en la cabeza en el espacio de direcciones del niño solo modificarán la copia del niño (por ejemplo, a través de copiar al escribir).

En cuanto a la documentación: he notado que la documentación suele indicar que todo está copiado, , excepto para bla, bla, bla.

 4
Author: Noah Watkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-04 20:11:35

La respuesta corta es 'sucio al escribir' - la respuesta más larga es .. mucho más.

Pero para todos los propósitos - el modelo de trabajo que en el nivel C es seguro asumir es que justo después de la bifurcación() los dos procesos son absolutamente idénticos i es decir, el hijo obtiene una copia 100% exacta. (pero por un poquito alrededor del valor devuelto de la bifurcación()) - y luego comienza a divergir a medida que cada lado modifica su memoria, pila y montones.

Así que su conclusión es un poco fuera de lugar-niño comienza off con los mismos datos que el padre copiado en su propio espacio-a continuación, lo modifica - y ver s como modificado-mientras que el padre continúa con su propia copia.

En realidad las cosas son un poco más complejas, ya que trata de evitar una copia completa haciendo algo sucio; evitando copiar hasta que tiene que hacerlo.

Dw.

 2
Author: Dirk-Willem van Gulik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-04 20:12:04