一、进程的程序替换
1. 程序替换函数命名理解
- l(list) : 表示参数采用列表 (可变参数列表)
- v(vector) : 参数用数组
- p(path) : 有p自动搜索环境变量PATH
- e(env) : 表示自己维护环境变量
#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并未改变
2. execl进程替换 路径 + 执行指令
execl函数:
int execl(const char *path, const char *arg, ...);
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;
}
3. execv 路径 + 使用数组存储指令
就是把指令放在一个数组里
int main()
{
if(fork() == 0)
{
char* const argv[] = {
"ls",
"-a",
"-l",
"-d",
NULL
};
printf("link start\n");
execv("/usr/bin/ls", argv);
printf("end of order\n");
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
和上面一样
4. execlp 文件名+ 执行指令 + execvp介绍
可以从环境变量自动找到文件去执行
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");
exit(1);
}
waitpid(-1, NULL, 0);
printf("over\n");
return 0;
}
5. execle 路径 + 执行指令 + 自己组建环境变量写进数组env + execve介绍
也是用一个程序调用另外一个程序,但环境变量是自己的环境变量,不是系统的,通过获取环境变量查看:
test1:
int main()
{
if(fork() == 0)
{
printf("link start\n");
char* const env[]= {
"env = 123",
NULL
};
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;
}
6. 运行一个py程序
py:
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的
|