Aprenda a crear un proceso UNIX. Semántica especial de execlp() y execvp(). El niño muere antes que el padre.

La llamada al sistema exec se utiliza para ejecutar un archivo que reside en un proceso activo. Cuando se llama a exec, el archivo ejecutable anterior se reemplaza 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 archivo o programa nuevo. 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 al llamar a exec().

El nuevo programa se carga en el mismo espacio de proceso. El proceso actual simplemente se convierte en un proceso nuevo y, por lo tanto, el ID del proceso PID no se cambia, esto se debe a que no son Al crear un nuevo proceso, simplemente reemplazamos un proceso con otro proceso en exec.

Si el proceso actualmente en ejecución contiene más de un subproceso, todos los subprocesos finalizarán y la nueva imagen del proceso se cargará y luego se ejecutará. No hay funciones destructoras que finalicen subprocesos del proceso actual.

El PID del proceso no se cambia sino los datos, el código, la pila, el montón, etc. del proceso se cambian y se reemplazan con 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. excl
  2. ejecle
  3. execlp
  4. ejecutivo
  5. ejecutivo
  6. vicepresidente ejecutivo

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:

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

yo: l es para los argumentos de la línea de comando que se pasan 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 comando. 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

Considerar la siguiente puntos para entender el funcionamiento del ejecutivo:

  1. La imagen de proceso actual se sobrescribe con una imagen de proceso nueva.
  2. La nueva imagen de proceso es la que pasó como argumento ejecutivo
  3. El proceso actualmente 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 el proceso no se reemplaza, la imagen de proceso se reemplaza)
  5. Las estadísticas de la CPU y la memoria virtual se ven afectadas. El mapeo de memoria virtual de la imagen de proceso actual se reemplaza por la memoria virtual de la nueva imagen de proceso.

Sintaxis de funciones familiares ejecutivas:

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 exitosamente, 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á configurado.

  1. camino se utiliza para especificar el nombre de ruta completo del archivo que se va a ejecutar.
  1. argumento 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 ruta es el mismo.
  1. carácter constante* arg en las funciones execl(), execlp() y execle() se considera como arg0, arg1, arg2,…, argn. Es básicamente 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. archivo 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 en mi se utilizan para cambiar el entorno de la nueva imagen del proceso. Estas funciones pasan la lista de configuración del entorno utilizando 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 utilizar las funciones de la familia exec, debe incluir el siguiente archivo de encabezado en su programa C:

#incluir

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

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

ejemplo.c

#incluir
#incluir
#incluir

{
imprimirf( "PID de ejemplo.c = %d\n ", getpid() );
char * args = ( "Hola", "C", "Programación", NULL);
execv("./hola", argumentos);
printf ("Volver al ejemplo.c");
devolver 0;
}

hola.c

PID de ejemplo.c = 4733
Estamos en Hola.c
PID de hola.c = 4733

En el ejemplo anterior tenemos un archivo example.c y 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 serie de punteros de caracteres. El último elemento de esta matriz debe ser NULL como punto final.

Luego hemos utilizado 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 utilizado ./ 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 sí está en el proceso. Se puede ver que el ID del proceso es el mismo ya sea que hello.c sea una imagen de proceso o example.c sea una imagen de proceso porque el proceso es el mismo y la imagen de proceso solo se reemplaza.

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

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

La llamada al sistema fork() se utiliza para crear un 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. Mientras que la llamada al sistema exec() se utiliza 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ó la función exec, sino que ejecutará el nuevo proceso. El control sólo se devolverá 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 llamadas al sistema fork() y exec() en el mismo programa:

ejemplo.c

#incluir
#incluir
#incluir
int principal(int argc, char * argv)
{
imprimirf( "PID de ejemplo.c = %d\n ", getpid() );
pid_tp;
p = bifurcación();
si (p==- 1 )
{
{
imprimirf( "Estamos en el proceso de padres") ;
}
devolver 0;
}

hola.c:

PID de ejemplo.c = 4790
Estamos en Proceso de Padres
Estamos en proceso infantil
Llamando a hello.c desde el proceso hijo
Estamos en hola.c
PID de hola.c = 4791

En este ejemplo hemos utilizado la llamada al sistema fork(). Cuando se crea el proceso hijo, se asignará 0 a p 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 secundario actual, que es ejemplo.c, se reemplazará con hello.c. Antes de que execv() llamara a los procesos padre e hijo eran los mismos.

Se puede ver que el PID de example.c y hello.c ahora es diferente. Esto se debe a que example.c es el proceso padre. imagen y hola.c es la imagen del proceso hijo.

Función Funciones que cargan y lanzan otros programas. Sintaxis int execl(char * nombre de ruta, char * arg0, arg1, ..., argn, NULL); int execle(char * nombre de ruta, char * arg0, arg1, ..., argn, NULL, char ** envp); int execlp(char * nombre de ruta, char * arg0, arg1, ..., argn, NULL); int execlpe(char * nombre de ruta, char * arg0, arg1, ..., argn, NULL, char ** envp); RUTA DOS. Sin el sufijo p, la búsqueda sólo se realizará en el directorio de trabajo. Si el parámetro de ruta no contiene una ruta, entonces la búsqueda se realiza en el directorio actual y luego a lo largo de las rutas definidas por la variable de entorno PATH. l: indica que los punteros de dirección (arg0, arg1, ..., argn) se pasan como argumentos separados. Normalmente, el sufijo l se utiliza cuando se sabe de antemano el número de argumentos que se pasarán. v: indica que los punteros de dirección (arg, arg,...arg[n]) se pasan como una matriz de punteros. Normalmente, el sufijo v se utiliza al transmitir numero variable argumentos. e: indica que al proceso "secundario" se le puede pasar un argumento envp, que le permite seleccionar el entorno del proceso "secundario". Sin el sufijo e, el proceso "secundario" heredará el entorno del proceso "principal"., que se asigna a cada variable envvar. El último elemento en la matriz envp la dirección cero es NULL. Cuando envp es NULL, el proceso "secundario" hereda las asignaciones de entorno del proceso "principal". La longitud total de arg0+ arg1+...+argn (o arg+ arg+...+arg[n]), incluidos los espacios que separan los argumentos, debe ser inferior a 128 bytes. Los finales nulos no se cuentan. Cuando se llama a exec..., todos los archivos abiertos permanecen abiertos en el proceso secundario. Devuelto Al completar exitosamente la función exec..., no se devuelve ningún valor. Si se produce un error, las funciones exec... devuelven -1 y la variable global errno se establece en uno de los siguientes valores: E2BIG: la lista de argumentos es demasiado larga. EACCES - Acceso denegado. EACCES - Acceso denegado. EMFILE: demasiados archivos abiertos.<=argc;loop++) puts(argv); return 0; } #includeEACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. ENOENT: no se encontró la ruta de acceso (RUTA) o el nombre del archivo.<=argc;loop++) puts(argv); /* напечатать первый параметр среды */ printf("env = %s\n",env); return 0; } #includeEACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. ENOEXEC - Error de formato EXEC.<=argc;loop++) puts(argv); return 0; } #includeEACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. ENOMEM: memoria insuficiente. La portabilidad de exec... es exclusiva de DOS. Ver también: abort, atexit,_exit, exit, _fpreset, searchpath, spawn..., system. Ejemplo: #incluir EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. void main(int argc,char **argv) ( printf("Iniciando CHILD con arg1, arg2 ...\n"); execv("CHILD.EXE",argv); perror("Error EXEC"); exit( 1); ) #incluir EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. void main(int argc,char **argv,char **envp) ( printf("Iniciar CHILD con arg1, arg2 ...\n"); execve("CHILD.EXE",argv,envp); perror(" Error EXEC"); salir(1); ) #incluir EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. void main(int argc,char **argv) ( printf("Iniciando CHILD con arg1, arg2 ...\n"); execvp("CHILD.EXE",argv); perror("Error EXEC"); exit( 1); ) #incluir EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. EACCES - Acceso denegado. int main(int argc,char **argv,char **envp) ( printf("Iniciar CHILD con arg1, arg2 ...\n"); execvpe("CHILD.EXE",argv,envp); perror(" Error EXEC"); salida(1); )

familia de funciones exec()

La familia de funciones exec() reemplaza el programa que se ejecuta en el proceso actual con otro programa. Cuando un programa llama a la función exec(), su ejecución se detiene inmediatamente y comienza a ejecutarse un nuevo programa.

Las funciones incluidas en la familia exec() difieren ligeramente en sus capacidades y en la forma en que se llaman.

Las funciones con un sufijo "p" en sus nombres (execvp() y execlp()) toman el nombre de un programa como argumento y buscan ese programa en los directorios especificados por la variable de entorno PATH. A todas las demás funciones se les debe pasar la ruta completa del programa.

Las funciones con un sufijo "v" en sus nombres (execv(), execvp() y execve()) aceptan una lista de argumentos del programa como una matriz de punteros de cadena, que termina con un puntero NULL. Las funciones con el sufijo "l" (execl(), execlp() y execle()) aceptan una lista de argumentos de longitud variable.

Las funciones con el sufijo "e" en sus nombres (execve() y execle()) toman una serie de variables de entorno como argumento adicional. Esta matriz contiene punteros de cadena y termina con un puntero nulo. Cada línea debería verse como " VARIABLE=significado" .

Debido a que exec() reemplaza un programa por otro, nunca devuelve un valor, solo si no se pudo llamar al programa debido a un error.

La lista de argumentos pasados ​​al programa es similar a los argumentos de la línea de comando especificados al ejecutar el programa de forma interactiva. También se pueden obtener utilizando los parámetros argc y argv de la función main(). Recuerde, cuando el intérprete de comandos inicia un programa, el primer elemento de la matriz argv contendrá el nombre del programa, seguido de los argumentos pasados ​​al programa. Debes hacer lo mismo al generar una lista de argumentos para la función exec().

Ejeclp (3) lanzar un archivo para su ejecución

Otros alias

execl, execle, execv, execvp, execvpe

REVISAR

#incluir

carácter externo **entorno;

int execl(carácter constante *camino, carácter constante *argumento, ...
/* (char *) NULL */);
int execlp(carácter constante *archivo, carácter constante *argumento, ...
/* (char *) NULL */);
int execle(const char *camino, carácter constante *argumento, ...
/*, (char *) NULL, char * constanteenvp */);
int execv(carácter constante *camino, carácter *constargv);
int execvp(carácter constante *archivo, carácter *constargv);
int execvpe(carácter constante *archivo, carácter *constargv,
carácter *constenvp);

Requisitos para la macro de prueba de propiedades para glibc (consulte característica_prueba_macros(7)):

ejecutivo():_GNU_SOURCE

DESCRIPCIÓN

familia de funciones ejecutivo() reemplaza la imagen del proceso actual por una nueva. Las funciones descritas en esta página de manual son contenedores para ejecutivo(2) (Para obtener detalles sobre cómo reemplazar el actual, consulte la página de manual ejecutivo(2)).

El primer argumento de estas funciones es el nombre del archivo ejecutable.

Parámetro carácter constante *arg y parámetros posteriores en funciones excl(), execlp() Y ejecle() pueden considerarse como parámetros arg0, arg1, ..., argón. Juntos describen una lista de uno o más punteros de cadena terminados en nulo que representan una lista de parámetros disponibles para el programa en ejecución. El primer parámetro, por convención, debe apuntar al nombre asociado con el archivo que se va a ejecutar. Lista de parámetros debe termina con un puntero nulo y, dado que se trata de una función con un número variable de argumentos, este puntero debe convertirse a (carácter *) NULO.

Funciones ejecutivo(), vicepresidente ejecutivo() Y ejecutivo() proporciona al nuevo programa una lista de argumentos en forma de una matriz de punteros a cadenas terminadas en nulo. El primer argumento, por convención, debe apuntar al nombre asociado con el archivo que se va a ejecutar. Conjunto de punteros debe terminar con un puntero nulo.

Funciones ejecle() Y ejecutivo() permite a la persona que llama asignar un entorno al programa ejecutable a través de un parámetro envp. Argumento envp es una matriz de punteros a cadenas terminadas en nulo, debe terminar con un puntero nulo. Las funciones restantes recuperan el entorno para la nueva imagen del proceso a partir de una variable externa. reinar proceso de llamada.

Semántica especial de execlp() y execvp()

Funciones execlp(), vicepresidente ejecutivo() Y ejecutivo() duplicar acciones de Shell relacionadas con la búsqueda de un archivo ejecutable si el nombre del archivo especificado no contiene un carácter de barra diagonal (/). La ruta de búsqueda se establece en la variable de entorno. CAMINO(lista de directorios separados por dos puntos). Si esta variable no está definida, entonces, de forma predeterminada, la lista de directorios devueltos se agrega al directorio actual. confstr(_CS_PATH)(llamar confstr(3) normalmente devuelve "/bin:/usr/bin").

Si el nombre del archivo especificado contiene un carácter de barra diagonal, la variable CAMINO se ignorará y se iniciará el archivo en la ruta especificada.

Además, existen diferencias en el manejo de algunos errores.

Si se deniega el acceso a un archivo (al intentar ejecutar ejecutivo(2) se devuelve un error ACCESO), entonces estas funciones continuarán buscando en las rutas restantes. Sin embargo, si no se encuentran más archivos, asignan el valor a la variable global. errno igual ACCESO.

Si no se reconoce el encabezado del archivo (al intentar ejecutar ejecutivo(2) devoluciones ENOEXEC), entonces estas funciones inician el shell ( /bin/sh) con el nombre completo del archivo como primer parámetro (si esto también produce un error, la búsqueda se detiene).

VALOR DEVUELTO

Funciones ejecutivo() devuelve un valor sólo si se produce un error. Esto devuelve -1, y errno se asigna un código de error.

VERSIONES

Función ejecutivo() apareció por primera vez en glibc 2.11.

ATRIBUTOS

Para obtener una descripción de los términos de esta sección, consulte atributos(7).
Interfaz Atributo Significado
excl(), ejecle(), ejecutivo() inofensividad en hilosinofensivo (MT-Safe)
execlp(), vicepresidente ejecutivo(), ejecutivo() inofensividad en hilosinofensivo (entorno MT-Safe)

CUMPLIMIENTO DE NORMAS

POSIX.1-2001, POSIX.1-2008.

Función ejecutivo() es una extensión GNU.

NOTAS

En algunos sistemas, la ruta de búsqueda predeterminada (utilizada cuando no hay ninguna variable en el entorno) CAMINO) comienza con directorios /papelera Y /usr/bin y luego se realiza la búsqueda en el directorio actual (para no iniciar un programa troyano incorporado). Linux utiliza el método tradicional: la búsqueda comienza desde el directorio actual.

Comportamiento de la función execlp() Y vicepresidente ejecutivo() para errores durante los intentos de ejecutar un archivo se ha desarrollado históricamente, pero no está descrito ni definido en el estándar POSIX. En BSD (y posiblemente en otros sistemas) hay una espera y un reintento automáticos si ocurre un error. ETXTBSY. En Linux, esto se trata como un error irrecuperable y regresa inmediatamente.

Tradicionalmente, funciones execlp() Y vicepresidente ejecutivo() ignoró todos los errores excepto los descritos anteriormente, y también ENOMEMA Y E2BIG que regresan. En Linux, estas funciones devuelven cualquier error distinto de los enumerados anteriormente.




Arriba