【lesson16】进程控制之进程替换(1)

进程替换是什么?

我们知道fork()之后,父子进程各自执行父进程的一部分代码,如果子进程就想执行一个全新的程序呢?

以前:父子代码共享,数据写时拷贝各自一份

如果子进程想要有自己的代码呢?
我们可以用进程的程序替换来完成以上功能。

程序替换:是通过特定的接口,找到磁盘上的一个权限程序(代码+数据),把它加载到调用进程的物理内存中。
原理:
在这里插入图片描述
所以想进行程序替换我们只要将新的磁盘上的程序加载到内存,并和当前的进程页表重新建立映射关系即可

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
在这里插入图片描述
所以进程替换没有创建新的进程,因为OS并没有为该程序创建新的task_struct,用的全部都是之前程序的task_struct。

进程替换怎么用?

不创建子进程时使用

函数介绍:
在这里插入图片描述
可变参数列表:可以传入不定个数个参数。

我们在命令行上怎么执行的在这里就一个一个怎么填。
例如:ls -a -l 就直接填入"ls",‘’-a’',“-l”。
代码演示:
首先要知道ls的路径
在这里插入图片描述

#include <stdio.h>      
#include <unistd.h>      
                                             
int main()                                   
{
                                               
  printf("当前进程的开始代码\n");            
  execl("/usr/bin/ls","ls",NULL);    
    
                                                                                                                                                                        
  printf("当前进程的结束代码\n");    
  return 0;                          
} 

运行结果对比
在这里插入图片描述

我们看到确实可以查出来
再多传几个查看一下

#include <stdio.h>      
#include <unistd.h>      
      
int main()      
{
         
  printf("当前进程的开始代码\n");      
  //execl("/usr/bin/ls","ls",NULL);      
  execl("/usr/bin/ls","ls","-a","-l",NULL);    

                                                                                                                                                                        
  printf("当前进程的结束代码\n");      
  return 0;              
}

运行结果:
在这里插入图片描述
系统自身运行结果:
在这里插入图片描述

这里大家肯会有个一行为什么最后要传一个NULL因为execl函数是可变参数列表,所以我们要传一个NULL来告知它参数已经传递完毕。

这里大家肯会有疑惑为什么系统使用ls时查出来的信息是带颜色的,而自己查出来时并没有。
其实是系统起了别名:
在这里插入图片描述我们知道多传递一个==–color=auto==参数列表即可

#include <stdio.h>    
#include <unistd.h>    
    
int main()    
{
       
  printf("当前进程的开始代码\n");    
  //execl("/usr/bin/ls","ls",NULL);    
  execl("/usr/bin/ls","ls","-a","-l","--color=auto",NULL);                                                                                                              
    
    
  printf("当前进程的结束代码\n");    
  return 0;    
}

在这里插入图片描述

这里我就有一个问题了,我们代码后面不是有printf吗?为什么没有打印呢?
在这里插入图片描述
因为execl是程序替换,调用该函数成之后,会将当前进程的所有代码和数据都进行替换,包括已经执行的代码和未执行的代码。
所以一旦调用成功execl,后续所有代码,全部不会执行!
测试一下如果调用失败,我们后续代码会执行吗?
我们传入一个根本不存在的执行试一下

#include <stdio.h>    
#include <unistd.h>    
    
int main()    
{
       
  printf("当前进程的开始代码\n");    
  //execl("/usr/bin/ls","ls",NULL);    
  execl("/usr/bin/lss","lss","-a","-l","--color=auto",NULL);    
    
    
  printf("当前进程的结束代码\n");    
  return 0;                                                                                                                                                             
}   

在这里插入图片描述
我们这里看到execl函数调用失败之后,确实后续代码成功的输出,并没有被替换。

**execl为什么调用成功了,为什么不用它的返回值呢?**因为根本就不需要,返回值毫无用处,execl调用成功是会把自己都替换掉。

#include <stdio.h>      
#include <unistd.h>                                                           
#include <stdlib.h>      
    
int main()    
{
       
  printf("当前进程的开始代码\n");    
  //execl("/usr/bin/ls","ls",NULL);    
  execl("/usr/bin/ls","ls","-a","-l","--color=auto",NULL);                                                                                                              
  exit(1);                                               
                                                         
  printf("当前进程的结束代码\n");                        
  return 0;                                              
}

在这里插入图片描述
我们可以看到这里的退出码是0,而不是1.

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2023-12-16 19:44:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-16 19:44:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-16 19:44:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-16 19:44:04       20 阅读

热门阅读

  1. MATLAB安装

    2023-12-16 19:44:04       36 阅读
  2. cp scp rsync 的备份用法举例

    2023-12-16 19:44:04       47 阅读
  3. 数据结构-图

    2023-12-16 19:44:04       30 阅读
  4. vue3 uniapp定时器 每天定时触发任务

    2023-12-16 19:44:04       38 阅读
  5. leetCode算法—4.寻找两个正序数组的中位数

    2023-12-16 19:44:04       38 阅读
  6. 疯狂SQL转换系列- SQL for Tencent Cloud VectorDB

    2023-12-16 19:44:04       37 阅读
  7. MVVM和MVC以及MVP的原理以及它们的区别

    2023-12-16 19:44:04       38 阅读
  8. 使用Spring Boot和领域驱动设计实现模块化整体

    2023-12-16 19:44:04       34 阅读
  9. 绘制饼状图的编程实现

    2023-12-16 19:44:04       31 阅读