1什么是进程替换
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("test.c...begin\n");
execl("/usr/bin/ls","ls","-l","-a",NULL);
printf("test.c...end\n");
return 0;
}
可以看到,进程在运行到一半,最后一句的printf没有执行,这是为什么呢?
因为程序被替换了
exec*系列的函数,可以替换当前的程序,进程的程序替换,本质上还是那一个进程,进程不变,但是进程里的程序变了,
要是把代码改成多进程版本,让子进程替换,那么父子共享的代码和数据,都要进行写时拷贝
2.exec*系列函数
#include <unistd.h>`
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[]);
int execve(const char *path, char *const argv[], char *const envp[]);
对于int execl(const char *path, const char *arg, ...);
参数的含义,第一个参数path:表示怎么找到函数,所以要传函数的路径,第二个参数arg:表示怎么用函数,怎么用,所以要传命令行指令,比如:
execl("/usr/bin/ls", "ls","-l","-a",NULL)
如果是多个命令,就用逗号分开,结尾要用NULL
对于int execv(const char *path, char *const argv[]);
第二个参数变成argv指针数组,我们可以自己写一个数组,把命令行指令写进数组里,直接传数组就可以
··
char *const argv[] =
{
(char*)"ls",
(char*)"-l",
(char*)"-a",
(char*)"--color",
NULL};
因为argv的类型是char*,"ls"是const char*,所以给"ls"加个(char*)会比较好,注意,结尾依然是NULL,
所以我们传参时可以
execv("/usr/bin/ls", argv);
对于int execvp(const char *file, char *const argv[]);
我们可以把第一个参数变成文件名字,然后execvp就可以根据文件名字查找这个文件
对于int execve(const char *path, char *const argv[], char *const envp[]);
第三个参数是环境变量
替换环境变量
- 替换全新的环境变量
- 用父进程的环境变量environ
- 也可以修改父进程的环境变量,然后替换给子进程
比如:
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[], char *env[])
{
int i = 0;
for(; argv[i]; i++)
{
printf("argv[%d] : %s\n", i, argv[i]);
}
printf("-------------------------------\n");
for(i=0; env[i]; i++)
{
printf("env[%d] : %s\n", i, env[i]);
}
printf("-------------------------------\n");
cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
printf("testexec ... begin!\n");
pid_t id = fork();
if(id == 0)
{
putenv("HHHH=111111111111111111");//修改父进程的环境变量
// 我的父进程本身就有一批环境变量!!!, 从bash来
char *const argv[] = //命令行参数
{
(char*)"mypragma",
(char*)"-a",
(char*)"-b",
NULL
};
//char *const envp[] =
//{
// (char*)"HAHA=111111",
// (char*)"HEHE=222222",
// NULL
//};
extern char**environ;
printf("child pid: %d\n", getpid());
sleep(2);
execvpe("./mypragma", argv, environ);
//execvpe("./mypragma", argv, envp);
//execl("/usr/bin/python3", "python3", "test.py", NULL);
//execl("/usr/bin/bash", "bash", "test.sh", NULL);
//execl("./mypragma", "mypragma", NULL);
//sleep(2);
//char *const argv[] =
//{
// (char*)"ls",
// (char*)"-l",
// (char*)"-a",
// (char*)"--color",
// NULL
//};
child
//execl("/usr/bin/top", "top", NULL);
//execlp("top", "top", NULL);
//execv("/usr/bin/ls", argv);
//execvp("ls", argv);
exit(1);
}
// fahter
int status = 0;
pid_t rid = waitpid(id, &status, 0);
if(rid > 0)
{
printf("father wait success, child exit code: %d\n", WEXITSTATUS(status));
}
printf("testexec ... end!\n");
return 0;
}
可以看出,我们可以修改父进程的环境变量,然后替换给子进程