#include <unistd.h>`
//间隔都是相似的
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execve(const char *path, char *const argv[], char *const envp[]);
如果想要子进程进行一个新的程序
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变
execl函数:
如果调用失败,不会执行该代码
如果调用成功则加载新的程序从启动代码开始执行,不再返回。 如果调用出错则返回-1, 所以exec函数只有出错的返回值而没有成功的返回值
int execl(const char *path, const char *arg, ...);
//全路径/文件名 //可变参数列表怎么执行就写什么命令,结束用NULL
1 #include <iostream>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <unistd.h>
7 #include <stdio.h>
8
9 using namespace std;
10
11
12 int main()
13 {
14 cout << "hello world" << endl;
15
16 execl("/usr/bin/ls", "ls", "-a", "-l", "-d", NULL);
17 //之后不会进行下面代码
18 cout << "hello world" << endl;
19
20
21 return 0;
22 }
程序替换的本质是把程序的进程代码+数据加载进特定进程的上下文中
C/C++程序运行,必须的先加载到内存中!
如何加载? 加载器:exec*程序替换函数
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)
子进程调用一种exec函数执行另一个程序,此时发生写实拷贝,不影响父进程
makefile如何生成两个可执行文件?
.PHONY:all
all:mytest1 mytest2
mytest2:test2.c
gcc $^ -o $@
mytest1:test1.c
gcc $^ -o $@
.PHONY:clean
clean:
rm -f mytest1 mytest2
使用execl用一个可执行程序执行另外一个可执行程序
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
if(fork() == 0)
{
printf("link start\n");
execl("./mytest2", "./mytest2", NULL);
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
就是把指令放在一个数组里
int main()
{
if(fork() == 0)
{
char* const argv[] = {
"ls",
"-a",
"-l",
"-d",
NULL
};
printf("link start\n");
// execl("/usr/bin/ls", "ls", "-a", "-l", "-d", NULL);
execv("/usr/bin/ls", argv);
printf("end of order\n");
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
和上面一样
可以从环境变量自动找到文件去执行
int execlp(const char *file, const char *arg, ...);
//指令名称, 指令如何执行
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
if(fork() == 0)
{
printf("link start\n");
execlp("ls", "ls", "-a", "-l", "-d");
/*
char* const argv[] = {
"ls",
"-a",
"-l",
"-d",
NULL
};
execvp("ls", argv);
*/
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
也是用一个程序调用另外一个程序,但环境变量是自己的环境变量,不是系统的,通过获取环境变量查看:
test1:
int main()
{
if(fork() == 0)
{
printf("link start\n");
char* const env[]= {
"env = 123",
NULL
};
/*
char* const argv[] = {
"./mytest2",
NULL
};
execve("./mytest2",argv,NULL,env);
*/
execle("./mytest2","./mytest2",NULL,env);
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
test2
#include <stdio.h>
int main()
{
extern char** environ;
for(int i = 0; environ[i]; i++)
{
printf("%s\n", environ[i]);
}
printf("over");
return 0;
}
py:
#!/usr/bin/python3
print("hello world\n");
test1.c
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
if(fork() == 0)
{
printf("link start\n");
execl("/usr/bin/python3","python","test3.py",NULL);
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
2的手册是系统调用,3的手册是库
这里面缺少了一个execve
这里的几个都是经过封装,最终还是调用execve的