目录
1.进程程序替换
1.进程程序替换概念
子进程执行的是父进程的代码片段
如果我们想要创建出来的子进程,执行一个全新的程序呢?
这个时候就要用到进程程序替换
2.为什么要进程程序替换
我们一般在服务器设计(linux编程)的时候,
往往需要子进程干二件种类的事
1.让进程执行父进程代码片段(服务器代码)
2.让子进程执行磁盘中一个权限的程序,想让客户端执行对应的程序,比如通过我们的进程来执行别人的进程
3.进程程序替换原理
1.将磁盘中的程序,加载如内存结构
2.重新建立页表映射,谁执行程序替换,就重新建立谁的映射(子进程)效果:让我们的父进程和子进程彻底分离,并让子进程执行一个全新的程序(这里的调用不是通过我们来调用的,而是通过操作系统来完成的,我们只要调用接口就行了)
那么这里有没有创建新的进程呢?
答案是没有,他只是让他的子进程执行了不同的代码而已,但是他的pid等等是不变的
4.进程程序替换使用
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("我是一个进程,我的pid是: %d\n",getpid());
execl("/usr/bin/ls", "ls", "-l", "-a",NULL);
printf("我是一个进程,我的pid是: %d\n",getpid());
return 0;
}
运行结果
可以看到他运行ls -al的命令
上面可以看到代码是有二个打印代码的,但是最后的打印代码不执行,为什么?
因为执行了execl,一旦替换成功,就会把当前进程的代码和数据全部替换,后面的printf是代码吗?显而易见是的,所以printf才不会被执行,因为他已经被替换了,他都不在了还怎么执行
如果把execl(“usr/bin/ls”,“ls”,“-a”,“-l”,NULL);改成下面的
execl("ls","ls","-a","-l",NULL);
能跑吗?答案是能跑的
因为第一个ls是给系统查找,剩下的都是执行方式
那么有了上面的推理那么上面替换成功它是不会返回值,那么返回值还有用吗?
答案是有用的,因为替换失败的时候,你可以返回错误码
那么子进程执行程序替换会影响父进程码?
答案是不会的,因为进程具有独立性
那么是怎么做到的?
数据层面发生写实拷贝,当程序替换的时候,我们可以理解成,代码和数据都发生了写实拷贝完成了父子进程的分离!
验证代码
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int main()
{
printf("我是一个进程,我的pid是: %d\n",getpid());
pid_t id = fork();
if(id == 0)
{
//child
//我们想让子进程执行全新的程序,以前是执行父进程的代码片
printf("我是一个子进程,我的pid是: %d\n",getpid());
execl("usr/bin/ls","ls","-a","-l",NULL);
exit(1);//只要执行了exit就代表了execl替换执行失败
}
//执行到这里的一定是父进程
int status = 0;
int ret = waitpid(id,&status,0);
if(ret == id)
{
sleep(2);
printf("父进程等待成功!\n");
}
return 0;
}
运行结果
但是上面的程序调用的都是系统的代码而不是我们自己写的,所以我们就要自己调用一下自己的文件
先写个文件,文件名字mycmd.c这个文件名字可以自己定义,但是要和自己写的makefile对应起来
#include<iostream>
int main()
{
std::cout << "hello c++" << std::endl;
return 0;
}
makefile之前的文章有讲过,这个all的意思是先生成all再生成下面的
.PHONY:all
all:myexec mycmd
myexec:myexec.c
gcc -o $@ $^
mycmd:mycmd.cpp
g++ -o $@ $^
.PHONY: clean
clean:
rm -f myexec mycmd
我们再用pwd获得当前的路径,再用execl来实现调用,记得pwd出来的路径之后加上你要运行的文件名,这个也可以不用绝对路径,相对路径也可以的
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
int main()
{
printf("我是一个进程,我的pid是: %d\n",getpid());
pid_t id = fork();
if(id == 0)
{
//child
//我们想让子进程执行全新的程序,以前是执行父进程的代码片
printf("我是一个子进程,我的pid是: %d\n",getpid()