GNU/Linux >> Tutoriales Linux >  >> Linux

Aprenda y use las llamadas al sistema fork(), vfork(), wait() y exec() en todos los sistemas Linux

Se encuentra que en cualquier sistema operativo basado en Linux/Unix es bueno entender fork y vfork llamadas al sistema, cómo se comportan, cómo podemos usarlas y diferencias entre ellas. Junto con estos espera y ejecutivo las llamadas al sistema se utilizan para generar procesos y otras tareas relacionadas.

La mayoría de estos conceptos se explican mediante ejemplos de programación. En este artículo, cubriré qué son las llamadas al sistema fork, vfork, exec y wait, sus caracteres distintivos y cómo se pueden utilizar mejor.

bifurcación()

bifurcación(): Llamada al sistema para crear un proceso hijo.

[email protected] ~}$ man fork

Esto producirá un resultado que menciona para qué se usa la bifurcación, la sintaxis y junto con todos los detalles requeridos.

La sintaxis utilizada para la llamada al sistema de bifurcación es la siguiente,

pid_t fork(void);

La llamada al sistema de bifurcación crea un hijo que difiere de su proceso principal solo en pid (ID de proceso) y ppid (ID del proceso principal) . La utilización de recursos se establece en cero. Los bloqueos de archivos y las señales pendientes no se heredan. (En Linux, "fork" se implementa como "copy-on-write() “).

Nota:-Copiar al escribir ” -> Cada vez que se llama al sistema fork(), se crea una copia de todas las páginas (memoria) relacionadas con el proceso principal y el sistema operativo las carga en una ubicación de memoria separada para el proceso secundario. Pero esto no es necesario en todos los casos y puede ser necesario solo cuando algún proceso escribe en este espacio de direcciones o área de memoria, entonces solo se crea/proporciona una copia separada.

Valores devueltos :- PID (ID de proceso) del proceso secundario se devuelve en el hilo principal de ejecución y "cero ” se devuelve en el hilo de ejecución del niño. El siguiente es el ejemplo de programación c que explica cómo funciona la llamada al sistema de bifurcación.

[email protected] ~}$ vim 1_fork.c
#include<stdio.h>
#include<unistd.h>
Int main(void)
{
printf("Before fork\n");
fork();
printf("after fork\n");
}
[email protected] ~}$ 
[email protected] ~}$ cc 1_fork.c
[email protected] ~}$ ./a.out
Before fork
After fork
[email protected] ~}$

Cada vez que se realiza una llamada al sistema, hay muchas cosas que suceden detrás de escena en cualquier máquina unix/linux.

En primer lugar, el cambio de contexto ocurre del modo de usuario al modo kernel (sistema). Esto se basa en la prioridad del proceso y el sistema operativo Unix/Linux que estemos utilizando. En el código de ejemplo de C anterior, estamos usando "{" llave de apertura que es la entrada del contexto y "}" llave de cierre es para salir del contexto. La siguiente tabla explica muy claramente el cambio de contexto.

vfork()

vfork –> crear un proceso secundario y bloquear el proceso principal.

Nota:- En vfork, los controladores de señales se heredan pero no se comparten.

[email protected] ~}$ man vfork

Esto producirá un resultado que menciona para qué se usa vfork, la sintaxis y junto con todos los detalles requeridos.

pid_t vfork(void);

vfork es igual que fork, excepto que el comportamiento no está definido si el proceso creado por vfork modifica cualquier dato que no sea una variable de tipo pid_t utilizada para almacenar el valor de retorno p de vfork o llama a cualquier otra función entre llamar a _exit() o uno de los exec () familia.

Nota: A veces se hace referencia a vfork como un caso especial de clonación.

El siguiente es el ejemplo de programación en C para vfork() cómo funciona.

[email protected] ~}$ vim 1.vfork.c
#include<stdio.h>
#include<unistd.h>
Int main(void)
{
printf("Before fork\n");
vfork();
printf("after fork\n");
}
[email protected] ~}$ vim 1.vfork.c
[email protected] ~}$ cc 1.vfork.c
[email protected] ~}$ ./a.out
Before vfork
after vfork
after vfork
a.out: cxa_atexit.c:100: __new_exitfn: Assertion `l != NULL' failed.
Aborted

Nota: – Como se explicó anteriormente, muchas veces el comportamiento de la llamada al sistema vfork no es predecible. Como en el caso anterior, se imprimió una vez antes y dos veces después, pero canceló la llamada con la función _exit(). Es mejor usar la llamada al sistema de bifurcación a menos que sea de otra manera y evite usar vfork tanto como sea posible.

Diferencias entre fork() y vfork()

Vfork() comportamiento explicado con más detalles en el siguiente programa.

[email protected] ~}$ cat vfork_advanced.c
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
    int n =10;
    pid_t pid = vfork(); //creating the child process
    if (pid == 0)          //if this is a chile process
    {
        printf("Child process started\n");
    }
    else//parent process execution
    {
        printf("Now i am coming back to parent process\n");
    }
    printf("value of n: %d \n",n); //sample printing to check "n" value
    return 0;
}
[email protected] ~}$ cc vfork_advanced.c
[email protected] ~}$ ./a.out
Child process started
value of n: 10
Now i am coming back to parent process
value of n: 594325573
a.out: cxa_atexit.c:100: __new_exitfn: Assertion `l != NULL' failed.
Aborted

Nota: Nuevamente, si observa que el resultado de vfork no está definido. El valor de "n" se imprimió por primera vez como 10, lo que se esperaba. Pero la próxima vez en el proceso padre imprimió algún valor basura.

esperar()

La llamada al sistema wait() suspende la ejecución del proceso actual hasta que un hijo haya salido o hasta que se haya enviado una señal cuya acción sea terminar el proceso actual o llamar al controlador de señales.

pid_t wait(int * status);

Hay otras llamadas al sistema relacionadas con la espera como se muestra a continuación,

1) esperarpid() :suspende la ejecución del proceso actual hasta que un hijo especificado por los argumentos pid haya salido o hasta que se entregue una señal.

pid_t waitpid (pid_t pid, int *status, int options);

2) esperar3() :Suspende la ejecución del proceso actual hasta que un niño haya salido o hasta que se entregue la señal.

pid_t wait3(int *status, int options, struct rusage *rusage);

3) esperar4() :Igual que wait3() pero incluye el valor pid_t pid.

pid_t wait3(pid_t pid, int *status, int options, struct rusage *rusage);

ejecutivo()

ejec() familia de  funciones o llamadas al sistema reemplaza la imagen del proceso actual con una nueva imagen del proceso.

Hay funciones como execl , excepto ,execle ,ejecutivo , execvp y execvpe se utilizan para ejecutar un archivo.

Estas funciones son combinaciones de una matriz de punteros a cadenas terminadas en nulo que representan la lista de argumentos, esto tendrá una variable de ruta con algunas combinaciones de variables de entorno.

salir()

Esta función se utiliza para la terminación normal del proceso. El estado del proceso se captura para referencia futura. Hay otras funciones similares exit(3) y _exit(). , que se usan en función del proceso de salida que uno está interesado en usar o capturar.

Conclusión:-

Las combinaciones de todas estas llamadas/funciones del sistema se utilizan para la creación, ejecución y modificación de procesos. También se les llama conjunto de funciones de desove de "cáscara". Uno tiene que usar estas funciones con cautela teniendo en cuenta el resultado y el comportamiento.


Linux
  1. Cómo usar instantáneas LVM para restaurar sistemas Linux

  2. Cómo instalar y usar Git en el sistema Linux

  3. Cómo instalar y usar Telnet en sistemas Linux

  4. Cómo usar los comandos strace y ltrace en Linux

  5. Cómo instalar y usar Glances para monitorear sistemas Linux

Cómo instalar y usar Skype en el sistema Linux. Ahora es más fácil

Cómo instalar y usar el compilador GCC en el sistema Linux

Cómo montar y usar una unidad exFAT en un sistema Linux

Cómo instalar y usar Tmux (terminal multiplexor) en el sistema Linux

Cómo instalar y usar AsciiDoc en el sistema Linux

Cómo instalar y usar el emulador de terminal Konsole en el sistema Linux