Llamada al sistema Linux Exec

Linux Exec System Call



La llamada al sistema ejecutivo se utiliza para ejecutar un archivo que reside en un proceso activo. Cuando se llama a exec, se reemplaza el archivo ejecutable anterior y se ejecuta el nuevo archivo.

Más precisamente, podemos decir que el uso de la llamada al sistema exec reemplazará el archivo o programa antiguo del proceso con un nuevo archivo o programa. Todo el contenido del proceso se reemplaza por un nuevo programa.







El segmento de datos del usuario que ejecuta la llamada al sistema exec () se reemplaza con el archivo de datos cuyo nombre se proporciona en el argumento mientras se llama a exec ().



El nuevo programa se carga en el mismo espacio de proceso. El proceso actual simplemente se convierte en un nuevo proceso y, por lo tanto, el ID de proceso PID no se cambia, esto se debe a que no estamos creando un nuevo proceso, solo estamos reemplazando un proceso con otro proceso en exec.



Si el proceso que se está ejecutando actualmente contiene más de un subproceso, todos los subprocesos se terminarán y la nueva imagen del proceso se cargará y luego se ejecutará. No hay funciones destructoras que terminen subprocesos del proceso actual.





El PID del proceso no se cambia, pero los datos, el código, la pila, el montón, etc. del proceso se cambian y se reemplazan por los del proceso recién cargado. El nuevo proceso se ejecuta desde el punto de entrada.

La llamada al sistema Exec es una colección de funciones y en el lenguaje de programación C, los nombres estándar para estas funciones son los siguientes:



  1. execl
  2. execle
  3. execlp
  4. execv
  5. ejecutivo
  6. execvp


Cabe señalar aquí que estas funciones tienen la misma base ejecutivo seguido de una o más letras. Estos se explican a continuación:

Y: Es una matriz de punteros que apunta a variables de entorno y se pasa explícitamente al proceso recién cargado.

los: l es para los argumentos de la línea de comando pasados ​​una lista a la función

pag: p es la variable de entorno de ruta que ayuda a encontrar el archivo pasado como argumento para cargarlo en el proceso.

v: v es para los argumentos de la línea de comandos. Estos se pasan como una matriz de punteros a la función.

¿Por qué se utiliza exec?

exec se utiliza cuando el usuario desea iniciar un nuevo archivo o programa en el mismo proceso.

Trabajo interno del ejecutivo

Considere los siguientes puntos para comprender el funcionamiento del ejecutivo:

  1. La imagen de proceso actual se sobrescribe con una nueva imagen de proceso.
  2. La nueva imagen de proceso es la que pasó como argumento ejecutivo
  3. El proceso en ejecución ha finalizado.
  4. La nueva imagen de proceso tiene el mismo ID de proceso, el mismo entorno y el mismo descriptor de archivo (porque no se reemplaza el proceso, se reemplaza la imagen de proceso)
  5. La estadística de la CPU y la memoria virtual se ven afectadas. El mapeo de la memoria virtual de la imagen del proceso actual se reemplaza por la memoria virtual de la nueva imagen del proceso.

Sintaxis de las funciones de la familia ejecutiva:

Las siguientes son las sintaxis para cada función de exec:

int execl (const char * ruta, const char * arg,…)
int execlp (const char * archivo, const char * arg,…)
int execle (const char * ruta, const char * arg,…, char * const envp [])
int execv (const char * ruta, const char * argv [])
int execvp (const char * archivo, const char * argv [])
int execvpe (const char * archivo, const char * argv [], char * const envp [])

Descripción:

El tipo de retorno de estas funciones es Int. Cuando la imagen del proceso se reemplaza con éxito, no se devuelve nada a la función de llamada porque el proceso que la llamó ya no se está ejecutando. Pero si hay algún error, se devolverá -1. Si se produce algún error, errno Está establecido.

En la sintaxis:

  1. sendero se utiliza para especificar el nombre completo de la ruta del archivo que se va a ejecutar.
  1. enfadado es el argumento pasado. En realidad, es el nombre del archivo que se ejecutará en el proceso. La mayoría de las veces, el valor de arg y path es el mismo.
  1. const char * arg en las funciones execl (), execlp () y execle () se considera arg0, arg1, arg2,…, argn. Básicamente es una lista de punteros a cadenas terminadas en nulo. Aquí, el primer argumento apunta al nombre del archivo que se ejecutará como se describe en el punto 2.
  1. envp es una matriz que contiene punteros que apuntan a las variables de entorno.
  1. expediente se utiliza para especificar el nombre de la ruta que identificará la ruta del nuevo archivo de imagen de proceso.
  1. Las funciones de llamada ejecutiva que terminan con Y se utilizan para cambiar el entorno de la nueva imagen de proceso. Estas funciones pasan la lista de configuración del entorno mediante el argumento envp . Este argumento es una matriz de caracteres que apunta a una cadena terminada en nulo y define la variable de entorno.

Para usar las funciones de la familia ejecutiva, debe incluir el siguiente archivo de encabezado en su programa C:

#incluir

Ejemplo 1: uso de la llamada al sistema exec en un programa C

Considere el siguiente ejemplo en el que hemos utilizado la llamada al sistema exec en la programación C en Linux, Ubuntu: Tenemos dos archivos c aquí example.cy hello.c:

ejemplo.c

CÓDIGO:

#incluir
#incluir
#incluir
En tprincipal(En targc, carbonizarse *argv[])
{
printf ('PID de ejemplo.c =% d orte',getpid());
carbonizarse *argumentos[] = {'Hola', 'C', 'Programación',NULO};
execv('./Hola',argumentos);
printf ('Volver a ejemplo.c');
regreso 0;
}

Hola C

CÓDIGO:

#incluir
#incluir
#incluir
En tprincipal(En targc, carbonizarse *argv[])
{
printf ('Estamos en Hello.c orte');
printf ('PID de hola.c =% d orte',getpid());
regreso 0;
}

PRODUCCIÓN:

PID de example.c = 4733
Estamos en Hello.c
PID de hola.c = 4733

En el ejemplo anterior tenemos un archivo example.cy un archivo hello.c. En el archivo .c de ejemplo, en primer lugar, hemos impreso el ID del proceso actual (el archivo example.c se está ejecutando en el proceso actual). Luego, en la siguiente línea, hemos creado una matriz de punteros de caracteres. El último elemento de esta matriz debe ser NULL como punto de terminación.

Luego hemos usado la función execv () que toma el nombre del archivo y la matriz de punteros de caracteres como argumento. Cabe señalar aquí que hemos usado ./ con el nombre del archivo, especifica la ruta del archivo. Como el archivo está en la carpeta donde reside example.c, no es necesario especificar la ruta completa.

Cuando se llama a la función execv (), nuestra imagen de proceso será reemplazada ahora el archivo example.c no está en el proceso pero el archivo hello.c está en el proceso. Se puede ver que el ID del proceso es el mismo si hello.c es la imagen del proceso o example.c es la imagen del proceso porque el proceso es el mismo y la imagen del proceso solo se reemplaza.

Entonces tenemos otra cosa a tener en cuenta aquí, que es la declaración printf () después de que execv () no se ejecuta. Esto se debe a que el control nunca vuelve a la imagen de proceso anterior una vez que la reemplaza por una nueva imagen de proceso. El control solo vuelve a llamar a la función cuando la sustitución de la imagen del proceso no se realiza correctamente. (El valor de retorno es -1 en este caso).

Diferencia entre las llamadas al sistema fork () y exec ():

La llamada al sistema fork () se utiliza para crear una copia exacta de un proceso en ejecución y la copia creada es el proceso hijo y el proceso en ejecución es el proceso padre. Considerando que, la llamada al sistema exec () se usa para reemplazar una imagen de proceso con una nueva imagen de proceso. Por lo tanto, no existe el concepto de procesos padre e hijo en la llamada al sistema exec ().

En la llamada al sistema fork (), los procesos padre e hijo se ejecutan al mismo tiempo. Pero en la llamada al sistema exec (), si el reemplazo de la imagen del proceso es exitoso, el control no regresa al lugar donde se llamó a la función exec, sino que ejecutará el nuevo proceso. El control solo se transferirá de nuevo si hay algún error.

Ejemplo 2: combinación de llamadas al sistema fork () y exec ()

Considere el siguiente ejemplo en el que hemos utilizado las llamadas al sistema fork () y exec () en el mismo programa:

ejemplo.c

CÓDIGO:

#incluir
#incluir
#incluir
En tprincipal(En targc, carbonizarse *argv[])
{
printf ('PID de ejemplo.c =% d orte',getpid());
pid_t p;
pag=tenedor();
si(pag==-1)
{
printf ('Hay un error al llamar a fork ()');
}
si(pag==0)
{
printf ('Estamos en el proceso del niño orte');
printf ('Llamar a hello.c desde el proceso hijo orte');
carbonizarse *argumentos[] = {'Hola', 'C', 'Programación',NULO};
execv('./Hola',argumentos);
}
demás
{
printf ('Estamos en el proceso de padres');
}
regreso 0;
}

Hola C:

CÓDIGO:

#incluir
#incluir
#incluir
En tprincipal(En targc, carbonizarse *argv[])
{
printf ('Estamos en Hello.c orte');
printf ('PID de hola.c =% d orte',getpid());
regreso 0;
}

PRODUCCIÓN:

PID de example.c = 4790
Estamos en proceso de padres
Estamos en proceso infantil
Llamar a hello.c desde el proceso hijo
Estamos en hello.c
PID de hello.c = 4791

En este ejemplo, hemos utilizado la llamada al sistema fork (). Cuando se crea el proceso hijo, se asignará 0 ap y luego pasaremos al proceso hijo. Ahora se ejecutará el bloque de declaraciones con if (p == 0). Se muestra un mensaje y hemos utilizado la llamada al sistema execv () y la imagen del proceso hijo actual, que es example.c, se reemplazará por hello.c. Antes de ejecutar execv (), los procesos hijo y padre eran los mismos.

Se puede ver que el PID de example.cy hello.c es diferente ahora. Esto se debe a que example.c es la imagen del proceso principal y hello.c es la imagen del proceso secundario.