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

发布时间:2023年12月17日

进程替换是什么?

我们知道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.

文章来源:https://blog.csdn.net/m0_67077469/article/details/135031346
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。