linux exec函数 不复制父进程,Linux下使用exec族函数进行进程替换

在Linux下使用fork或者vfork函数创建的子进程是完全复制父进程的代码来执行的。虽然我们可以使用fork函数返回值的不同来使得父进程和子进程执行的代码不同。但是有时候父进程是一段c程序,子进程却是个shell。这个时候,fork就没法解决这个问题。因此exec函数是必须的。

exec函数族共包括7个函数,函数形式如下:

系统调用

int execve(const char *filename, char *const argv[],

char *const envp[]);

库函数

int execl(const char *path, const char *arg, ...

/* (char *) NULL */);

int execlp(const char *file, const char *arg, ...

/* (char *) NULL */);

int execle(const char *path, const char *arg, ...

/*, (char *) NULL, char * const envp[] */);

int execv(const char *path, char *const argv[]);

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

int execvpe(const char *file, char *const argv[],

char *const envp[]);

注意:实际上只有execve函数是系统调用,其余6个都是在execve基础上封装而来的库函数。

函数参数的意义:

path:指定要执行的程序的名称和路径

file:指定要执行的程序的名称,可以不指定路径,但是必须配置环境变量PATH。

arg...:以逐个列举的方式表示要执行的程序的格式:例如准备执行“创建子进程”这个程序,那么应该传递参数为:“./创建子程序”, NULL(因为exec启动了一个新的程序,这个程序将从它的main函数开始执行,NULL是传递给main函数的命令行参数终止符号)

argv[]:以指针数组的形式表示要执行的程序的格式。

envp[]:环境变量参数。

这些函数之间的区别是第一个参数,有的是路径名,有的是文件名。如果文件名包含了/,那么就将其视作路径名。否则就按PATH环境变量,在它指定的目录中搜索可执行文件。

这些函数名字中的p代表了使用当前环境变量;e表示使用envp数组,不使用当前环境变量;l表示参数是一个一个独立的;v表示参数被整合为一个数组argv。l和v是互斥的。

exec函数簇只有出错的时候有返回值,因为,一旦exec成功就去运行另外一段代码了。

当一个程序中使用exec函数来调用了另外的可执行文件后,那么该进程中所有的资源完全由新进程替换。所以使用的时候应当注意,如果还想回到原来的进程继续执行,那么需要先使用fork函数来创建一个进程,在这个进程中使用exec函数来完成进程替换。这样才能保证原进程能在exec调用后不被破坏。

exec函数调用后虽然替换了进程,但是却保留PID。来段代码跑一跑

#include

#include

#include

#include

int main()

{

pid_t pid;

pid = fork();

if(0 == pid)

{

execl("./创建子进程","创建子进程",NULL);

}

if(0 < pid)

{

sleep(2);

printf("I am father!\n");

}

return 0;

}

运行结果如下:

12d806aee063daac748661b0674c18c7.png

代码里的创建子进程是上一篇博客提到的代码,在这里。

vfork在exec函数(或者是exit)调用之前的这段时间是和父进程共享数据的,直到遇到exec函数(或者是exit函数),才会成为一个独立进程,拥有自己的地址空间。不再和父进程共享地址空间。因此使用fork可以避免很多错误(尤其是你在vfork产生的子进程中,除了exec以外还做其他的操作)。

但是使用fork的的缺点是必须无法确定执行顺序,在这里我让父进程挂起2秒,从而使得子进程先于父进程执行。另外使用exec函数也可以完成shell命令。例如下面的代码。

#include

#include

#include

#include

int main()

{

pid_t pid;

pid = fork();

if(0 == pid)

{

execl("/bin/pwd","pwd",NULL);

}

if(0 < pid)

{

sleep(1);

printf("I am father process!\n");

}

return 0;

}

执行结果如下:

0e1bd0ae85edf8b518b7f13dae94aadb.png

成功执行了shell命令。

本文同步分享在 博客“zy010101”(CSDN)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值