程序/进程替换(讲解)

本文旨在讲解进程替换的知识!希望读完本文,能使读者对进程替换有更深一步的认识!!好的,废话不多说,干货来了!


进程替换的引进!

为什么要引进进程替换呢?我们创建子进程总不能做和父进程做一样的事情把!子进程也应该能做自己想做的事情吧!就拿我们日常生活中的例子来言:一个父亲经营一家公司,其儿子也不一定非得子承父业来选择和其父亲做一样的事情把。所以这就把进程替换这个概念引了进来!

进程替换的概念!

何谓进程替换呢?进程替换就是子进程不再运行父进程的代码和数据了,而是另起炉灶,选择新的代码和数据来执行!

既然进程替换的概念已经简单的介绍了,那么我们就来见一见进程替换把!

进程替换的实例

多进程的进程替换!

下面通过一个简单的多进程的代码来看一看什么是进程替换!

通过上图我们可以看出结果!子进程开始跑之后,调用了一个execl函数!然后父进程一直在跑!等待子进程的退出!最后通过监视进程窗口看见,子进程跑完了,但是子进程跑的代码是我们日常命令行中的ls命令?这难道进行进程替换么?

也有眼尖的小伙伴发现了,直至子进程退出之后,也没有执行其execl之后的代码!这是为什么?而且进程替换之后也没有创建新的进程!从这点我们可以看出,进程的替换并不会引起新的进程的产生!

那么为什么excel之后的代码就不再执行了呢?这就要从进程替换的原理来讲解了!

所谓的进程替换,本质上只是将子进程的代码和数据块进行了修改,其他的结构 并没有做出修改!那么是如何修改的呢?是从磁盘中获取新的代码和数据块,然后在内存中重新找空间,用于这些新的代码和数据块,然后修改子进程从父进程那边继承过来的页表的信息,简单的进程替换就做完了!


那么知道了原理,那该如何解释是如何进行进程替换的呢?

通过上面的调用execl函数可以看出,首先要找到被替换的可执行程序,然后进行选择如何执行这个程序即可!

要想彻底搞懂进程的替换原理,那么我们就不得不介绍系统提供的进程替换函数了!

进程替换函数讲解

通过上图我们可以看出进程替换有很多,他们都是在第三手册(也就是系统调用),下面我们就来详细介绍其中的一些函数!已经他们的使用方法!

execl

函数原型:

其中exec是这些函数的开头,l可以理解成list的意思,即用list传递参数!

可以看出,有两个参数!根据我们刚才多进程的进程替换的实例中,我们可以看出,其中第一个path就是替换后的程序的路径与文件名  其中第二个参数就是我们日常在bash命令行中怎么写,就在函数传参怎么写就行!后面的三个点代码此函数是一个可变参数列表!表示参数不固定!但是需要注意的是:最后必须以NULL结尾,表示传参完毕!


execlp

函数原型:

其中exelc中的p代表的是PATH,即系统默认的PATH环境变量,所以第一个参数为file,表明只需要写你要替换的程序的名字即可!其中第二个参数上面execl中相同!

下面来看一下此函数的使用方式!

其中第一个参数,只需要将替换后程序的名字写上去就行,无需再进行声明路径即可!


execv

函数原型:

其中execv中的v代表的是一个数组,用于存放命令的选项!

下面来简单来看一下此函数的使用方式!

其中只需要创建一个函数指针数组即可,将程序的选项写入到argv数组即可!其中警告原因是因为前面没有用const修饰,因为它们指向的都是字符串常量!切记:此数组中的结尾也必须以NULL结尾,表示传递参数结束!


execvp

函数原型:

其中p代表的仍然是默认的环境变量,与execv的差距只是第一个参数传参不必再进行传路径了,只需要传被替换的程序名字即可!

使用就不再累赘了!

execvpe

函数原型:

其中e表示的环境变量!

表示该函数继承其父进程的环境变量,其中第三个参数指的是环境变量参数,可以传递系统自带的environ,或者自己自定义的环境变量的字符串指针数组!

具体使用如下:

只要将其中的参数进行正确的传参即可!其中第一个参数,也可以直接将arg[0]传入,第二个传的就命令行参数,第三个就环境变量参数,可以自己定义,也可以传系统自带的environ!


至此,将部分的exec簇家族的函数讲解一番,其他的函数只需要对照其上述的函数使用方式即可!

扩充:

但是当我们进行查找2号手册的时候,我们还会发现还有一个exel簇函数,它为什么在2号手册,和这些簇函数不同呢?

下面我们看一下2号手册的exec函数!

他为什么处于二号手册呢,这里简单介绍一番,其中位于三号手册的系统调用本质上都是调用的此函数!都是对本函数的封装!这是为什么呢?因为每次进程替换的时候,格式不确定,所以不能仅仅通过此函数来调用,因此就封装了这个函数,产生了位于三号手册的那些exec簇函数!


通过上述的进程替换我们可以看出,进程替换替换的都是bash命令行已经存在的命令,那么是否能够替换成我们自己写的程序呢?答案是肯定的!下面我就来写一个代码替换为我们自己写的C++进程!

Makefile

mytest.cc

运行之后,就可以看到将我们的代码替换成c++运行的代码了!

进程替换中环境变量的变化!

1.在进行进程替换的时候,子进程对应的环境变量,可以直接从父进程那边继承过来!  可以使用export新增导入环境变量观察即可!

2.环境变量被子进程继承下来是一种默认的行为不受程序替换的影响!(因为程序替换只是简单的替换代码和数据段,然后修改页表中的部分内容,对虚拟地址空间也是直接拷贝过来!)

3.子进程获取环境变量的三种方式

一、直接原封不动的由父进程那边继承过来

二、传递自己定义的环境变量参数!

三、新增传递,即原封不动从父进程继承过来之后,再自己进行putenv()操作即可!


至此,关于进行替换的知识介绍完毕,希望能对读者有一定的收获!

  • 74
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 40
    评论
进程与线程是操作系统的核心概念,也是C语言中常用的概念。本文将详细讲解C语言中进程与线程的概念、特点、创建与销毁等相关知识。 一、进程 1.概念 进程是操作系统中的一种基本概念,是指正在执行的一个程序。每个进程都有自己的地址空间、内存、文件描述符和其他系统资源,它们是独立的,相互之间不能直接访问。在操作系统中,每个进程都有一个唯一的标识符,称为进程ID。 2.特点 (1)每个进程都有自己独立的地址空间,不同进程之间的变量和数据不能相互访问。 (2)进程是系统分配资源的基本单位,每个进程都有自己的文件描述符、信号处理程序、内存空间、CPU时间等资源。 (3)进程之间是相互独立的,一个进程的崩溃不会影响其他进程的正常运行。 3.创建与销毁 在C语言中,可以通过fork()函数来创建一个新的进程。fork()函数的返回值有两个,父进程获取到的是子进程进程ID,而子进程得到的则是0。在子进程中,可以通过exec()系列函数来启动一个新的程序,从而实现进程替换进程的销毁可以通过exit()函数来实现,exit()函数会向操作系统发送一个信号,让操作系统停止当前进程的运行。 二、线程 1.概念 线程是进程中的一条执行路径,它是操作系统调度的基本单位,每个线程都拥有自己的栈空间、寄存器、状态等信息。在同一个进程中,多个线程共享相同的地址空间和其他资源,它们之间可以直接访问同一块内存区域。 2.特点 (1)多个线程可以在同一时间内并发执行,提高了程序的并发性和效率。 (2)线程之间共享相同的地址空间和其他资源,可以直接访问同一块内存区域。 (3)线程的创建和销毁的开销比进程小很多,可以更快速地响应用户的请求。 3.创建与销毁 在C语言中,可以通过pthread_create()函数来创建一个新的线程。pthread_create()函数的第一个参数是线程的ID,第二个参数是线程的属性,第三个参数是线程执行的函数,第四个参数是传递给线程函数的参数。 线程的销毁可以通过pthread_exit()函数来实现,它会通知操作系统停止当前线程的执行。 三、进程与线程的区别 (1)进程是操作系统分配资源的基本单位,线程是进程中的一条执行路径。 (2)每个进程都有独立的地址空间和系统资源,进程之间不能直接访问,而线程共享相同的地址空间和其他资源。 (3)创建和销毁线程的开销比进程小很多,可以更快速地响应用户请求。 (4)进程之间是相互独立的,一个进程的崩溃不会影响其他进程的正常运行,而线程之间共享相同的地址空间,一个线程的崩溃会影响整个进程的运行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值