Pregunta ¿Cuál es el propósito de fork ()?


En muchos programas y páginas man de Linux, he visto código usando fork(). ¿Por qué tenemos que usar fork() y cual es su proposito?


74
2018-06-12 04:49


origen


Respuestas:


fork() es cómo crear nuevos procesos en Unix. Cuando usted llama fork, estás creando una copia de tu propio proceso que tiene su propio espacio de dirección. Esto permite que varias tareas se ejecuten independientemente una de la otra como si cada una de ellas tuviera la memoria completa de la máquina.

Aquí hay algunos ejemplos de usos de fork:

  1. Tu cáscara usos fork ejecutar los programas que invocas desde la línea de comando.
  2. Servidores web como apache utilizar fork para crear múltiples procesos de servidor, cada uno de los cuales maneja las solicitudes en su propio espacio de direcciones. Si uno muere o pierde memoria, otros no se verán afectados, por lo que funciona como un mecanismo para la tolerancia a fallas.
  3. Google Chrome usos fork manejar cada página dentro de un proceso separado. Esto evitará que el código del lado del cliente en una página reduzca todo el navegador.
  4. fork se usa para generar procesos en algunos programas paralelos (como los escritos usando MPI) Tenga en cuenta que esto es diferente de usar trapos, que no tienen su propio espacio de direcciones y existen dentro un proceso.
  5. Uso de lenguajes de scripting fork indirectamente para comenzar procesos secundarios. Por ejemplo, cada vez que utilizas un comando como subprocess.Popen en Python, tú fork un proceso hijo y leer su salida. Esto permite que los programas trabajen juntos.

Uso típico de fork en un caparazón podría ser algo como esto:

int child_process_id = fork();
if (child_process_id) {
    // Fork returns a valid pid in the parent process.  Parent executes this.

    // wait for the child process to complete
    waitpid(child_process_id, ...);  // omitted extra args for brevity

    // child process finished!
} else {
    // Fork returns 0 in the child process.  Child executes this.

    // new argv array for the child process
    const char *argv[] = {"arg1", "arg2", "arg3", NULL};

    // now start executing some other program
    exec("/path/to/a/program", argv);
}

El shell genera un proceso secundario usando exec y espera a que se complete, luego continúa con su propia ejecución. Tenga en cuenta que no tiene que usar el tenedor de esta manera. Siempre puede generar muchos procesos secundarios, como lo haría un programa paralelo, y cada uno podría ejecutar un programa al mismo tiempo. Básicamente, cada vez que estás creando nuevos procesos en un sistema Unix, estás usando fork(). Para el equivalente de Windows, eche un vistazo a CreateProcess.

Si quieres más ejemplos y una explicación más larga, Wikipedia tiene un resumen decente Y aquí hay algunas diapositivas aquí sobre cómo funcionan los procesos, los hilos y la concurrencia en los sistemas operativos modernos.


95
2018-06-12 04:55



fork () es cómo Unix crea nuevos procesos. En el punto que llamó fork (), su proceso se clona, ​​y dos procesos diferentes continúan la ejecución desde allí. Uno de ellos, el niño, tendrá fork () return 0. El otro, el padre, tendrá fork () devolverá el PID (identificación del proceso) del niño.

Por ejemplo, si escribe lo siguiente en un intérprete de comandos, el programa shell llamará a fork (), y luego ejecutará el comando que pasó (telnetd, en este caso) en el elemento secundario, mientras que el padre mostrará el mensaje de nuevo también. como un mensaje que indica el PID del proceso de fondo.

$ telnetd &

En cuanto a la razón por la que creas procesos nuevos, así es como tu sistema operativo puede hacer muchas cosas al mismo tiempo. Es por eso que puede ejecutar un programa y, mientras se está ejecutando, cambiar a otra ventana y hacer otra cosa.


10
2018-06-12 04:53



fork () se usa para crear un proceso hijo. Cuando se llama a una función fork (), se generará un nuevo proceso y la llamada a la función fork () devolverá un valor diferente para el hijo y el padre.

Si el valor devuelto es 0, sabe que es el proceso hijo y si el valor devuelto es un número (que es el id. De proceso secundario), sabe que es el padre. (y si es un número negativo, el tenedor falló y no se creó ningún proceso secundario)

http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html


9
2018-06-12 04:55



fork () creará un nuevo proceso hijo idéntico al padre. De modo que todo lo que ejecute en el código después de eso será ejecutado por ambos procesos, muy útil si tiene, por ejemplo, un servidor y desea manejar múltiples solicitudes.


5
2018-06-12 04:53



fork () se usa básicamente para crear un proceso hijo para el proceso en el que está llamando a esta función. Siempre que llame a un tenedor (), devuelve un cero para la identificación del niño.

pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process

con esto puede proporcionar diferentes acciones para el padre y el hijo y hacer uso de la función de subprocesamiento múltiple.


5
2018-06-12 05:02



Probablemente no necesite utilizar el tenedor en la programación diaria si está escribiendo aplicaciones.

Incluso si desea que su programa inicie otro programa para realizar alguna tarea, existen otras interfaces más simples que usan fork detrás de escena, como "sistema" en C y perl.

Por ejemplo, si desea que su aplicación inicie otro programa como bc para hacer algunos cálculos por usted, puede usar 'system' para ejecutarlo. El sistema hace un 'fork' para crear un nuevo proceso, luego un 'exec' para convertir ese proceso en bc. Una vez que bc completa, el sistema devuelve el control a su programa.

También puede ejecutar otros programas de forma asíncrona, pero no recuerdo cómo.

Si está escribiendo servidores, shells, virus o sistemas operativos, es más probable que quiera usar fork.


4
2018-06-12 14:09



Fork crea nuevos procesos. Sin fork, tendrías un sistema Unix que solo podría ejecutar init.


4
2018-04-17 12:04



System call fork () se utiliza para crear procesos. No requiere argumentos y devuelve un ID de proceso. El propósito de fork () es crear un nuevo proceso, que se convierte en el proceso secundario de la persona que llama. Después de que se crea un nuevo proceso hijo, ambos procesos ejecutarán la siguiente instrucción siguiendo la llamada al sistema fork (). Por lo tanto, tenemos que distinguir el padre del niño. Esto se puede hacer probando el valor devuelto de fork ():

Si fork () devuelve un valor negativo, la creación de un proceso secundario no tuvo éxito. fork () devuelve un cero al proceso hijo recién creado. fork () devuelve un valor positivo, el ID de proceso del proceso hijo, al padre. El ID del proceso devuelto es del tipo pid_t definido en sys / types.h. Normalmente, el ID del proceso es un número entero. Además, un proceso puede usar la función getpid () para recuperar el ID de proceso asignado a este proceso. Por lo tanto, después de la llamada del sistema a fork (), una prueba simple puede indicar qué proceso es el niño. Tenga en cuenta que Unix hará una copia exacta del espacio de direcciones de los padres y se lo dará al niño. Por lo tanto, los procesos padre e hijo tienen espacios de direcciones separados.

Permítanos entenderlo con un ejemplo para aclarar los puntos anteriores. Este ejemplo no distingue los procesos padre e hijo.

#include  <stdio.h>
#include  <string.h>
#include  <sys/types.h>

#define   MAX_COUNT  200
#define   BUF_SIZE   100

void  main(void)
{
     pid_t  pid;
     int    i;
     char   buf[BUF_SIZE];

     fork();
     pid = getpid();
     for (i = 1; i <= MAX_COUNT; i++) {
          sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
          write(1, buf, strlen(buf));
     } 
}

Supongamos que el programa anterior se ejecuta hasta el punto de la llamada a fork ().

Si la llamada a fork () se ejecuta con éxito, Unix hará dos copias idénticas de espacios de direcciones, una para el padre y la otra para el niño. Ambos procesos comenzarán su ejecución en la siguiente instrucción después de la llamada fork (). En este caso, ambos procesos comenzarán su ejecución en la asignación

pid = .....;

Ambos procesos comienzan su ejecución justo después de que el sistema llame a fork (). Como ambos procesos tienen espacios de direcciones idénticos pero separados, las variables inicializadas antes de la llamada fork () tienen los mismos valores en ambos espacios de direcciones. Como cada proceso tiene su propio espacio de direcciones, cualquier modificación será independiente de las demás. En otras palabras, si el padre cambia el valor de su variable, la modificación solo afectará a la variable en el espacio de direcciones del proceso principal. Otros espacios de direcciones creados por fork () llamadas no se verán afectados aunque tengan nombres de variable idénticos.

¿Cuál es el motivo de usar write en lugar de printf? Se debe a que printf () está "almacenado", lo que significa que printf () agrupará la salida de un proceso. Al almacenar en búfer la salida para el proceso principal, el niño también puede usar printf para imprimir cierta información, que también se almacenará en búfer. Como resultado, dado que el resultado no se enviará a la pantalla de inmediato, es posible que no obtenga el orden correcto del resultado esperado. Peor aún, la salida de los dos procesos puede mezclarse de maneras extrañas. Para superar este problema, puede considerar utilizar la escritura "sin búfer".

Si ejecuta este programa, puede ver lo siguiente en la pantalla:

................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
     ................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
     ................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
     ................

El proceso ID 3456 puede ser el asignado al padre o al hijo. Debido al hecho de que estos procesos se ejecutan al mismo tiempo, sus líneas de salida se entremezclan de una manera bastante impredecible. Además, el orden de estas líneas está determinado por el programador de la CPU. Por lo tanto, si ejecuta este programa nuevamente, puede obtener un resultado totalmente diferente.


4
2017-12-26 19:24



El multiprocesamiento es fundamental para la informática. Por ejemplo, su IE o Firefox pueden crear un proceso para descargar un archivo mientras navega por Internet. O bien, mientras está imprimiendo un documento en un procesador de textos, aún puede mirar diferentes páginas y aún editarlas con él.


3
2018-06-12 04:55



Fork () se utiliza para crear nuevos procesos como todo el mundo ha escrito.

Aquí está mi código que crea procesos en forma de árbol binario ... Solicitará escanear el número de niveles hasta los cuales desea crear procesos en árbol binario

#include<unistd.h> 
#include<fcntl.h> 
#include<stdlib.h>   
int main() 
{
int t1,t2,p,i,n,ab;
p=getpid();                
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);                
printf("root %d\n",p);fflush(stdout);
for(i=1;i<n;i++)    
{        
    t1=fork();

    if(t1!=0)
        t2=fork();        
    if(t1!=0 && t2!=0)        
        break;            
    printf("child pid %d   parent pid %d\n",getpid(),getppid());fflush(stdout);
}   
    waitpid(t1,&ab,0);
    waitpid(t2,&ab,0);
return 0;
}

SALIDA

  enter the number of levels
  3
  root 20665
  child pid 20670   parent pid 20665
  child pid 20669   parent pid 20665
  child pid 20672   parent pid 20670
  child pid 20671   parent pid 20670
  child pid 20674   parent pid 20669
  child pid 20673   parent pid 20669

3
2018-01-12 19:08



fork() se usa para engendrar un proceso hijo. Por lo general, se usa en situaciones similares como el enhebrado, pero existen diferencias. A diferencia de los hilos, fork() crea procesos separados, lo que significa que el niño y el padre son copias directas el uno del otro en el punto que fork()se llama, están completamente separados, ninguno puede acceder al espacio de la memoria del otro (sin ir a los problemas normales para acceder a la memoria de otro programa).

fork() todavía lo usan algunas aplicaciones de servidor, la mayoría de las cuales se ejecutan como raíz en una máquina * NIX que retira los permisos antes de procesar las solicitudes de los usuarios. Todavía hay algunos otros casos de uso, pero la mayoría de la gente ahora se ha cambiado a multihilo.


0
2018-06-12 04:55