exec函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
简单来说就是,子程序可以在不影响父程序下,执行别的程序
功能:
在调用进程内部执行一个可执行文件。可执行文件既可以是一个二进制文件,也可以是任何linux下可执行的脚本文件。
函数族:
分别是:execl,execlp,execle,execv,execvp,execvpe
函数原型:
#include <unistd.h> //exec函数族的头文件
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
- 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回;
- 如果调用出错则返回-1;
- 所以exec函数只有出错的返回值而没有成功的返回值;
快速分辨不同函数方法:
l(list) : 表示参数采用列表;
v(vector) : 参数用数组;
p(path) : 有p自动搜索环境变量PATH;
e(env) : 表示自己维护环境变量;(深入使用Linux再学习)
1.execl使用:
代码:
实现子进程ls功能;键入whereis ls 查找ls位置,如图:
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>int main()
{pid_t pid = fork();if(pid == 0){//child processprintf("child pid:%d\n",getpid());execl("/bin/ls","ls","-a","-l",NULL);// printf("child pid:%d",getpid());//exit child processexit(0);}//father processwait(NULL);printf("i am father[%d] ,do my thing ,不会被子进程的[%d]execl函数影响\n",getpid(),pid);return 0;
}
结果:
execl具体解释:这里引用呋喃吖_Leetcode,c++,Linux-CSDN博客
推荐看她的,写的很清楚
这里介绍一下perror函数
1、作用:
打印系统错误信息
2、原型
#include <stdio.h>
void perror(const char *s);
#include <errno.h>
3、代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{
int fd;
fd=open("./file", O_RDWR);//打开文件file,读写方式
if(fd < 0){
printf("open failure\n");
perror("why");//打印失败的原因
}
close(fd);
return 0;
}
运行结果:
//我的目录下是没有文件file的open failure
why: No such file or directory
linux下data与ps指令同理
2.execlp函数
execlp和execl的区别在于,execlp在第一个参数时候,不需要全路径,只需要写上执行命令的文件名即可,表示你需要执行谁,往后的参数也就是和execl的传参一样。
p为环境变量:使用时需要调用环境变量,方法如下:
pwd:查看当前路径
echo $PATH:显示当前PATH环境变量,该变量的值由一系列以冒号分隔的目录名组成。
export PATH=$PATH:路径名:环境变量的配置
代码:这里引用上述作者的:
#include<stdio.h>
#include<unistd.h>//使用fork,exec函数
#include<sys/wait.h>//使用waitpid
#include<stdlib.h> //使用exit的头文件
int main()
{if(fork() == 0){// execl("/usr/bin/ls","ls","-a","-l",NULL);execlp("ls","ls","-a","-l",NULL); //等价上面的execl()//虽然这里的第一个参数和第二个参数都一样,但是含义不一样;//第一个参数表示iexeclp函数要执行命令的路径文件名,//第二个参数表示execlp在命令行上如何执行该命令exit(1);}int waitRet = waitpid(-1,NULL,0); //阻塞等待所有子进程结束if(waitRet< 0){perror("wait error\n");}printf("parent wait child success\n");return 0;
}
结果:
3.execv函数
与execl函数没啥区别,就是传参的时候使用数组,而不是列出来
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);int main(void)
{printf("this is system date\n");char *argv[]={"ps",NULL,NULL};//数组形式if(execv("/bin/ps",argv) == -1){printf("execl failed!\n"); perror("why");}printf("after execl\n");return 0;
}
4.execvp可以类比execlp