这个一直没搞太明白,相识度高是一回事,不会用又是另外一回事儿。
因此今天又温故了一遍:web
为何须要exec函数?
fork子进程是为了执行新程序(fork建立了子进程后,子进程和父进程同时被OS调度执行,所以子进程能够单独的执行一个程序,这个程序宏观上将会和父进程程序同时进行)数组
能够直接在子进程的if中写入新程序打代码。但这样不够灵活,由于咱们只能把子进程程序的源代码贴过来执行(必须知道源代码,并且源代码太长了也很差控制)
使用exec族函数运行新的可执行程序。exec族函数能够直接把一个编译好的可执行程序直接加载运行。svg
有了exec族函数后,典型打父子进程程序是这样的:子进程须要运行的程序被单独编写、单独编译连接成一个可执行程序(hello)。主进程为父进程,fork建立了子进程后在子进程中exec来执行hello,达到父子进程分别作不一样程序同时(宏观上)运行的效果。函数
#include<unistd.h> int execve(const char *path,char *const argv[],char *const envp[]);//这个是真正的系统调用 //如下的函数最后都是调用这个函数 int execl(const char *path,char *const argv,···); int execlp(const char *file,char *const argv,···); int execle(const char *path,char *const argv,···· ,char *const envp[]); int execv(const char *path,char *const argv[]); int execvp(const char *file,char *const argv,);
exec函数族装入并运行程序path/file,并将参数arg0(arg1, arg2, argv[], envp[])传递给子程序,出错返回-1.spa
看一下后缀:.net
后缀 | 功能 |
---|---|
l | 但愿接收以逗号分隔的参数列表,列表以NULL指针做为结束标志 |
v | 但愿接收到一个以NULL结尾的字符串数组的指针 |
p | 是一个以NULL结尾的字符串数组指针,函数能够DOS的PATH变量查找子程序文件 |
e | 函数传递指定参数envp,容许改变子进程的环境,无后缀e时,子进程使用当前程序的环境 |
下面我找到一些通俗易懂的栗子,算是让我明白了一点:指针
#ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> int main(int argc, char *argv[]) { //以NULL结尾的字符串数组的指针,适合包含v的exec函数参数 char *arg[] = { "ls", "-a", NULL}; /** * 建立子进程并调用函数execl * execl 中但愿接收以逗号分隔的参数列表,并以NULL指针为结束标志 */ if( fork() == 0 ) { // in clild printf( "1------------execl------------\n" ); if( execl( "/bin/ls", "ls","-a", NULL ) == -1 ) { perror( "execl error " ); exit(1); } } /** *建立子进程并调用函数execv *execv中但愿接收一个以NULL结尾的字符串数组的指针 */ if( fork() == 0 ) { // in child printf("2------------execv------------\n"); if( execv( "/bin/ls",arg) < 0) { perror("execv error "); exit(1); } } /** *建立子进程并调用 execlp *execlp中 *l但愿接收以逗号分隔的参数列表,列表以NULL指针做为结束标志 *p是一个以NULL结尾的字符串数组指针,函数能够DOS的PATH变量查找子程序文件 */ if( fork() == 0 ) { // in clhild printf("3------------execlp------------\n"); if( execlp( "ls", "ls", "-a", NULL ) < 0 ) { perror( "execlp error " ); exit(1); } } /** *建立子里程并调用execvp *v 望接收到一个以NULL结尾的字符串数组的指针 *p 是一个以NULL结尾的字符串数组指针,函数能够DOS的PATH变量查找子程序文件 */ if( fork() == 0 ) { printf("4------------execvp------------\n"); if( execvp( "ls", arg ) < 0 ) { perror( "execvp error " ); exit( 1 ); } } /** *建立子进程并调用execle *l 但愿接收以逗号分隔的参数列表,列表以NULL指针做为结束标志 *e 函数传递指定参数envp,容许改变子进程的环境,无后缀e时,子进程使用当前程序的环境 */ if( fork() == 0 ) { printf("5------------execle------------\n"); if( execle("/bin/ls", "ls", "-a", NULL, NULL) == -1 ) { perror("execle error "); exit(1); } } /** *建立子进程并调用execve * v 但愿接收到一个以NULL结尾的字符串数组的指针 * e 函数传递指定参数envp,容许改变子进程的环境,无后缀e时,子进程使用当前程序的环境 */ if( fork() == 0 ) { printf("6------------execve-----------\n"); if( execve( "/bin/ls", arg, NULL ) == 0) { perror("execve error "); exit(1); } } return EXIT_SUCCESS; }
本文分享 CSDN - 看,将来。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。code