目录
- 一、前言
- 二、什么是进程程序替换?
- 三、进程程序替换的原理
- 四、为什么要进行进程程序替换?
- 五、如何进行进程程序替换?(常见进程程序替换系统调用接口)
- 六、利用所学综合知识实现一个shell
- 总结
一、前言
一般情况下,对应的语言写的程序只能调用对应的语言的接口,而不能调用其他语言的接口,如C++不能调用Java或者Python或者Shell等语言的接口,那么如果我们想要调用别人写的程序应该怎么办呢?那么进程程序替换就能够很好地帮助我们解决这个问题,这在很大程度上减少了我们编程的成本,学会进程程序替换,在很多时候,如果有现成的程序,那么我们不需要自己再去写一个,是不是方便很多了?
二、什么是进程程序替换?
所谓进程程序替换,顾名思义,就是使用一个新的程序替换原有的程序,进程将执行新程序的代码,而不再执行原有程序的代码,前面我们已经学习了如何创建一个进程,一般情况下,进程程序替换都不会使用父进程直接进行进程程序替换,而是让父进程调用fork()函数创建一个子进程,让子进程去执行一个新的程序即可
三、进程程序替换的原理
- 进程替换前的效果图
当一个进程成功创建一个子进程之后,父子进程的情况如下图所示:
这个时候,我们这里先针对代码和数据进行分析,其他内容暂不做考虑,此时父子进程都没有修改代码和数据,因此,父子进程的代码和数据都是指向同一块内容的,也就是代码和数据是共享的,如果其中一方对数据进行修改,则这一方就会进行写时拷贝,如果想要执行不同的代码,则此时就要进行进程程序替换
- 进程程序替换的原理:
假如刚开始父子进程都是执行程序a.exe
,后面,想要让子进程执行b.exe
了,那么此时就要进行进程程序替换,替换的过程就是首先将b.exe从磁盘加载进内存,然后重新建立子进程的页表,更新子进程的页表中的映射关系,注意,这里修改的是页表中的物理地址而不是虚拟地址,此时父子进程代码块中虚拟地址是一样的,但是通过页表映射出来的物理地址是不一样的,从而实现父子进程的代码彻底分离,此时父子进程的代码是互不干扰的,很好地满足了进程的独立性
- 进程替换之后的效果图
四、为什么要进行进程程序替换?
在学习进程程序替换之前,我们知道当一个父进程创建一个子进程之后,父子进程的代码是共享的,子进程只能执行父进程的代码块,但是现在我们的需求增加了,我们不仅要让子进程能够执行父进程的代码块,也要能够让子进程能够做一些父进程不能做的事情,也就是能够执行一个全新的代码(程序),这样就能实现父子进程做的事情有所差异,大大提高了办事效率,同时也使父子进程的代码彻底分离,维护进程的独立性
五、如何进行进程程序替换?(常见进程程序替换系统调用接口)
在学习使用进程程序替换的相关接口之前我们首先需要明确一点,这个在使用接口的时候需要做什么事情,很明显,最基本的我们首先得知道这个程序在哪里,其次,我们还需要知道怎么执行这个程序,在我们前面学习一些指令的时候,有些指令是可以携带选项的有些指令可以不用携带选项。总结起来就是我们需要知道要执行的程序的路径和怎么执行新程序
- execl
- 查看execl的使用方法
- execl的使用
- 源代码
- makefile文件
- 实验结果
上面的实验是没有子进程的,是一个纯单进程的实验,下面将演示一个多进程的例子执行ls指令,而且我们会发现一个现象,我们明明在源代码中写了两条printf函数语句,但是结果只有一条打印出来,原因是,当我们进行程序替换之后,子进程将不再执行原来的父进程的代码块,由进程程序替换的结果我们可以知道,子进程中的代码内容完全被替换
成新程序的代码 - execl多进程实验
源代码
makefile文件
实验结果
实验分析
上面的实验思路就是父进程创建一个子进程,然后本来子进程是要执行父进程的代码块和父进程进行代码共享的,但是我们在子进程中调用execl函数接口,因此,在子进程中会进行程序替换
- execv函数接口的使用
- 查看手册
这个函数和上面介绍的execl是类似的,都需要做两件事,第一知道新程序的路径,第二知道怎么执行新程序(是否携带选项进行执行),但是这个函数和上面介绍的函数的区别就是这个函数的第二个参数是一个字符指针数组,上面哪个函数是一个一级字符指针,其实区别就在于,上面那个函数传参传的是字符串列表,这个函数传参传的是字符指针数组
实验演示: - 源代码
- makefile文件
- 实验结果
需要注意的是: - execv函数中使用的是字符指针数组,而不是传字符串列表
- 数组中的字符串是常量字符串,也就是const char类型的,而这个字符指针数组中存放的又是char的,是支持修改的,因此这里需要将const char强转为char类型
- execlp函数接口的使用
- 查看手册
- execlp的使用(实验演示)
源代码
makefile文件
实验结果
execlp中的p指的是环境变量中的PATH,指的是系统直接到环境变量PATH中去寻找对应程序,因此在传第一个参数的时候不需要带路径
注意:
这个参数列表中有两个"ls",我们需要知道的是这两个ls的含义是不一样的,是不能省略的,第一个是告诉系统要执行哪个程序,好让系统知道去找谁,第二个是在函数的第二个参数之中的,也就是为了告诉系统怎么执行这个程序
- execvp的使用
- 查看手册
- 实验演示使用方法
源代码
makefile文件
实验结果
- execle函数接口的使用
- 查看手册
- execle的使用
源代码
makefile文件(形成多可执行程序)
导出自己的环境变量
实验结果
注意:
上面的实验中,我们使用函数execle传入第三方变量environ,environ的作用是获取系统中的环境变量,上面这个代码的意思就是将这个变量environ传给test程序,那么如果想要在该程序中打印出自定义的环境变量,则需要将自定义环境变量加入系统环境变量,test程序才能获取,如果没有加入系统环境变量,则getenv()函数获取不到对应的环境变量则会返回空指针,那么就会导致printf函数打印空指针从而造成程序崩溃
六、利用所学综合知识实现一个shell
敬请期待