Red de conocimiento informático - Material del sitio web - Cómo ejecutar comandos de shell en lenguaje C

Cómo ejecutar comandos de shell en lenguaje C

El sujeto puede utilizar la serie de funciones ejecutivas. Estas funciones están definidas en el archivo de encabezado unistd.h, así que incluya ese encabezado antes de usarlas. Hay cinco funciones en esta serie: execl,?execlp,?execv,?execvp,?execle

Las primeras cuatro funciones son las más utilizadas. Los prototipos de las primeras cuatro funciones son: int?execl(const?char?*path, ?const?char?*arg, ?...);

int?execlp(const?char?* file ,?const?char?*arg,?...);

int?execvp(const?char?*file,?char?*const?argv[]);

Las principales diferencias entre estas cuatro funciones son los tipos de parámetros y el uso de comandos sin entrada, y el uso de rutas absolutas con o sin comandos de entrada.

En forma de ruta, cualquier función que contenga p en su nombre (execlp, execvp) solo necesita proporcionar el nombre del comando, y la función encontrará automáticamente la ruta al comando en la variable de entorno actual $PATH. Sin p (execl, execv) debe proporcionar la ruta absoluta al comando; de lo contrario, la función no podrá encontrar la ubicación del comando. A continuación se muestran ejemplos de execl y execlp. El siguiente es el código para ejecutar el comando ls?-l

: #include?lt;stdio.hgt;

#include?lt;unistd.hgt;

int?main()?{

//?exec? Las funciones de la serie devuelven?-1, generalmente devuelven?0, por lo que puedes

//?Imprimir el correspondiente mensaje de error

//?El primer "ls" es el nombre del comando. La función execlp imprimirá automáticamente el mensaje de error en?$PATH para encontrar el comando

//?.

//?El "ls" después es el primer parámetro ingresado en "shell" (es decir, el nombre del comando en sí)

//?Usando "NULL" como La marca de terminación del parámetro es "exec" Requisitos de función de la serie.

if(execlp("ls","ls","-l",?NULL)? ==?-1)

perror("¿Error? ¿Ejecutando? Comando. \n");

return?0;

}

El resultado de ejecutar este programa C en el shell

es el Lo mismo que escribir directamente ls -l en el shell tiene el mismo resultado. Sin embargo, usar execl sin p genera un error.

#include?lt;stdio.hgt;

#include?lt;unistd.hgt;

int?main()?{

//?execl ?Solo acepta rutas absolutas a los comandos, por lo que debe ingresar el

//?/bin/ls completo, es decir:

/?if(execl("/bin/ls" ,?"ls",?"-l",?NULL)?-1)

if(execl("ls",?"ls",?"-l",?NULL)? = =?-1)

perror("¿Error?Ejecutando?Comando.\n");

return?0;

}

El resultado de salida es:

Por tipo de parámetro, cualquier función con l en su nombre (execl, execlp) necesita pasar todos los parámetros a la función, y cualquier función con l en su nombre (execl, execlp) todos deben pasar todos los parámetros del comando del sistema a la función. Todas las funciones con una v en su nombre (execv, execvp) deben colocar los parámetros del comando del sistema en una matriz y luego pasar la matriz a la función.

Por ejemplo, este #include?lt;stdio.hgt;

#include?lt;unistd.hgt;

int?main()?{

if(execlp("ls",?"ls",?"-l",?NULL)? ==?

perror("¿Error? ¿Ejecutando? Comando.\ n");

return?0;

}

Si escribes execvp en su lugar sería #include?lt; stdio.hgt;

# include?lt;unistd.hgt;

int?main()?{

//?Esta matriz de cadenas contiene todos los parámetros (incluido el nombre del comando en sí y NULL al final)

char?*?argv[]?{"ls",?" -l",?NULL};

//?Aquí solo necesitas agregue el nombre del comando y la matriz de parámetros se puede pasar a la función "execvp",

//? No es necesario pasar los parámetros uno por uno. De manera similar, la función agregará automáticamente el nombre del comando. y matriz de parámetros a $PATH

/? en

if(execvp("ls",?argv)?==?-1)

perror. ("¿Error? Ejecutando? Comando.\n");

return?0;

}

El efecto de ejecutarlo es el mismo que escribir ls -l directamente.

execv y execvp. La diferencia es si se debe ingresar la ruta absoluta, así que no diré más

Una cosa a tener en cuenta es si exec es. exitoso, el nuevo proceso iniciado por la función de la serie exec reemplazará completamente el proceso actual. Esto significa que el proceso actual desaparecerá. Es por eso que exec generalmente se usa junto con fork, para bifurcar un proceso hijo y luego usar exec para ejecutar otro. programa en el proceso hijo para evitar que exec sobrescriba el proceso padre.

Por ejemplo, si modificas ligeramente el código

#include?lt;stdio.hgt;

#include?lt;unistd.hgt;

int? main ()?{

char?{"ls",?"-l",?NULL};

if(execvp("ls",?argv)?== ? -1)

perror("¿Error? ¿Ejecutando? Comando.\n");

/?Agregar una declaración printf

printf("¿Principal? el proceso ?¿aún?se está ejecutando.\n");

return?0;

}

El proceso principal aún se está ejecutando y no aparecerá después de ejecutarse. declaración porque el proceso generado al ejecutar la función principal después de que exec aún se esté ejecutando. El proceso generado al ejecutar la función principal después de exec ha sido completamente sobrescrito por el proceso generado por el comando ls, por lo que las siguientes declaraciones en la función exec no se ejecutarán en absoluto. Puede usar fork para crear un nuevo proceso hijo para ejecutar la función ejecutiva.

#include?lt;stdio.hgt;

#include?lt;unistd.hgt;

#include?lt;sys/types.hgt;

#include?lt;sys/wait.hgt;

#include?

int?main()?{

int ?r;

//?fork()? es mayor que cero, proceso padre

if((r?=?fork())? gt;?0)?{

int?status;

if?((espera(amp; estado)?! =?-1)?{

//?Espera el proceso hijo para salir

if(WIFEXITED(status))?{

printf("¿Proceso principal?is?still?running.\n");

return?0 ;

}

}

}

//?Ejecutar exec

}

} else if(r ==?0)?{

char?{"ls",?" -l",?NULL};

if?(execvp( "ls",?argv)?==?-1)

perror("Error?Ejecutando?Command.\n");

return?0 ;

/?fork()? es menor que cero, error

}?else?{

perror("Fork");

}

return?0;

}

El resultado de esta operación es que

el proceso principal aún se está ejecutando y luego mostrarlo en la pantalla.