Linux下的进程控制-进程程序替换

这篇主要说一下Linux下的进程控制中最后一部分内容:进程程序替换
Linux下的进程控制-进程程序替换_第1张图片

文章目录

  • 1. 进程程序替换
    • 1.1 为什么要进程程序替换
    • 1.2 替换原理
    • 1.3 如何进行程序替换
      • 1.3.1 execl函数
      • 1.3.2 引入子进程的程序替换
      • 1.3.3 execv函数
      • 1.3.4 execlp函数和execvp函数
      • 1.3.5 如何执行其它语言的程序
      • 1.3.6 execle函数
      • 1.3.7 execve函数和execvpe函数

1. 进程程序替换

1.1 为什么要进程程序替换

我们知道:子进程一般执行的是父进程的代码片段。但是如果我们想让创建出来的子进程去执行其它的程序呢?我们就需要进程程序替换!!!

我们一般在服务器设计(Linux编程)的时候,往往需要子进程干两件种类的事:
1.让子进程执行父进程的代码片段(服务器代码)
2.让子进程执行磁盘中一个全新的程序(shell,想让客户端执行对应的程序,通过我们的进程执行其他人写的进程代码等等)。

1.2 替换原理

Linux下的进程控制-进程程序替换_第2张图片
这是我们父进程在运行时,把磁盘中可执行程序中的代码和数据加载到内存中。当我们父进程fork后。子进程的PCB和虚拟内存以父进程为模板,代码共享父进程的,数据也以写时拷贝的方式共享。
Linux下的进程控制-进程程序替换_第3张图片
此时,在磁盘中有个新的程序,让子进程数据和代码不在和父进程共享。让子进程去执行这个新文件。这样子进程的页表会进行更新指向新的代码段和数据段。
Linux下的进程控制-进程程序替换_第4张图片
替换原理:
1.将磁盘中的程序,加载入内存结构。
2.重新建立页表映射,谁执行程序替换,就重新建立谁的映射。
效果:让父子进程彻底分离,并让子进程执行一个全新的程序。在这里也并没有产生新的进程。

1.3 如何进行程序替换

因为我们是从磁盘加载到内存,一个硬件把数据转移到另外一个硬件中,这个工作是由操作系统完成的,所以我们需要一个系统函数来完成。在Linux云服务器上由7个程序替换函数。

1.3.1 execl函数

我们先来看一个最简单的:
在这里插入图片描述
这三个点叫做可变参数:它的作用是按照用户的意愿传入大小或者数量不等的各个参数。

那么,如果我们想执行一个全新的程序,我们需要做几件事情呢
1. 先找到这个程序在哪里?
2. 程序是怎么执行的?是带选项执行,还是不带选项执行?

那么,这个execl函数第一个参数的意思是:就是传入程序的路径,第二个传入的就是你程序是如何来执行的(命令行怎么写,这个参数就怎么填),最后必须是NULL,标识如何执行程序的参数传递完毕

现在我们写一个最简单的例子:
Linux下的进程控制-进程程序替换_第5张图片
Linux下的进程控制-进程程序替换_第6张图片
在OS中,命令也是一个程序,我们来运行一下:
Linux下的进程控制-进程程序替换_第7张图片
我们可以从结果看到:它这里执行了ls -a -l这个命令。我们再来看一个:
Linux下的进程控制-进程程序替换_第8张图片
这个不带选项的。我们运行一下:
Linux下的进程控制-进程程序替换_第9张图片
它也执行了pwd这个命令。但是大家有没有发现一个问题:它第二个打印没有进行。
原因是:一旦替换成功,是将当前的代码和数据全部替换了所以,后面的printf已经被替换了,该代码已经不存在了。

在这里插入图片描述
那么我们看这个函数的返回值有什么用呢?要不要判断返回值呢
答案是:不需要。因为当替换成功了,就不会有返回值了,它就执行其它的代码了,你的返回值没有任何作用。而失败的时候,必然会继续向后执行,最多通过得到什么原因导致的替换失败!!!

我们可以用一个失败的来运行一下:
Linux下的进程控制-进程程序替换_第10张图片
这里我们是没有这个命令的。
Linux下的进程控制-进程程序替换_第11张图片

1.3.2 引入子进程的程序替换

看下面的代码:
Linux下的进程控制-进程程序替换_第12张图片
运行一下:
Linux下的进程控制-进程程序替换_第13张图片
子进程进行程序替换,会不会影响父进程?
答案是:不会的。因为进程的独立性。
那么它是如何做到的呢?
原因是:当程序替换时,我们可以理解为:代码和数据都发生了写时拷贝完成父子的分离

1.3.3 execv函数

在这里插入图片描述
这个函数也是程序替换函数。第一个参数是:程序的路径。第二个参数:如何执行。
它和execv的区别就是它是一个指针数组。execl是一个一个传参数,而这个是把参数放到数组里,然后传这个数组。

举个例子:
Linux下的进程控制-进程程序替换_第14张图片
运行结果如下:
Linux下的进程控制-进程程序替换_第15张图片

1.3.4 execlp函数和execvp函数

在这里插入图片描述
这里的第一个参数有什么含义呢?它和execl有什么区别呢?
它第一个参数传的是你要执行什么程序,但是execl需要我们写路径,而这个execlp不需要我们写路径,直接写程序名就行了。因为它是默认在PATH下去寻找的

举个例子:
Linux下的进程控制-进程程序替换_第16张图片
我们来看一下运行结果:
Linux下的进程控制-进程程序替换_第17张图片
那么execvp也是一样的道理,这里就不多说了。
在这里插入图片描述

1.3.5 如何执行其它语言的程序

目前我们执行的都是系统命令,如果要执行自己写的C/C++程序,或者执行其它语言写的程序呢
我们写一个C++的程序:
Linux下的进程控制-进程程序替换_第18张图片
我们要形成两个可执行程序,让其中一个可执行程序去执行另外一个可执行程序:
Linux下的进程控制-进程程序替换_第19张图片
但是我们来运行一下:
在这里插入图片描述
但是我们只能执行第一个,因为makefile默认执行一个可执行程序。我们需要这样写:
Linux下的进程控制-进程程序替换_第20张图片
这样我们就可以一下形成两个可执行程序:
Linux下的进程控制-进程程序替换_第21张图片
然后看一下我们写的程序:
Linux下的进程控制-进程程序替换_第22张图片
这里用相对路径也可以,只要能找到它就行了:
在这里插入图片描述
然后,我们看一下运行结果:
Linux下的进程控制-进程程序替换_第23张图片
成功的用myexec执行了mycmd。

1.3.6 execle函数

在这里插入图片描述
这里的第三个参数是:环境变量的意思。

举个例子:
Linux下的进程控制-进程程序替换_第24张图片
这里我们写了一个系统里的环境变量PATH,和一个我们自己写的环境变量MYPATH(系统里没有)。
Linux下的进程控制-进程程序替换_第25张图片
这样就是我们自己写了一个环境变量,然后调用这个函数时导入。然后我们看一下运行结果:
Linux下的进程控制-进程程序替换_第26张图片
我们看到什么都没有打印,我们把PATH先注释掉:
Linux下的进程控制-进程程序替换_第27张图片
然后看运行结果:
Linux下的进程控制-进程程序替换_第28张图片
我们看到它把MYPATH打印出来了。原因是:添加环境变量给目标进程,是覆盖式的。
那么我们该如何解决这个问题呢?
Linux下的进程控制-进程程序替换_第29张图片
我们这里使用环境变量的指针来传入。
Linux下的进程控制-进程程序替换_第30张图片
因为系统里没有MYPATH环境变量,所以我们要export设置一下。
Linux下的进程控制-进程程序替换_第31张图片
这样就都能打印出来了。

1.3.7 execve函数和execvpe函数

Linux下的进程控制-进程程序替换_第32张图片
那么execvpe我就不多说了,就是把上面的结合起来就行了。
Linux下的进程控制-进程程序替换_第33张图片
那么现在就出现一个问题:为什么execve是单独的
原因是:execve是系统接口,而其余6个是对系统接口的封装。这样做的原因就是适配各种应用场景

这些函数原型看起来很容易混,但只要掌握了规律就很好记:
Linux下的进程控制-进程程序替换_第34张图片

你可能感兴趣的:(Linux,linux,程序替换)