进程程序替换和shell模拟实现

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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值