本片作为进程控制的最后一篇博客,来讲述进程控制中的最后一模块:程序替换的内容。
目录
程序替换
1.内容
在真正了解程序替换之前,我们首先来明确两个知识点:pcb的内容和创建子进程的作用。
前者我们在进程概念中详细阐述过,在此我们简要概述一下,pcb是运行中程序的描述,底层的实现上是一个结构体;
后者从进程的角度而言,创建一个进程的目的即是为了完成某项任务,创建子进程的作用亦然,也是为了完成某项任务,对于子进程而言,它运行的程序内容可能和父进程相同--分摊压力;也可能是为了运行另一个程序--if(ret == 0)。
但是当子进程运行新的程序时,会见新任务的代码同当前的代码糅杂在一起,导致程序内容繁多,难以模块化处理。
因此我们创建了新的方法来实现,即对于书写的新任务程序,让子进程的pcb来管理调度和执行,这便是程序替换的主要思想。
总而言之,程序替换即是:将一个pcb所描述的调度管理程序,替换成另一个程序。换而言之,我们将一个新程序加载到内存当中,然后修改当前pcb进程的页表映射信息,初始化地址空间,让该pcb来管理调度新程序。
在了解完程序替换的内容之后,接下来我们讲述程序替换操作,即一些和程序替换相关的系统调用接口。
2.接口
2.1execve
int execve(char *path, char *argv[], char *env[]);
execve接口的作用:是将path这个路径名称所指定的程序加载到内存中,然后让当前进程调度管理这个程序的运行。
对于程序的运行会存在运行参数和环境变量,正如main函数中的参数会记录函数的运行参数和环境变量的内容和个数。
所以execve中参数:argv用于设定该程序的运行参数;env用于设定该程序的环境变量。
最后,exevec的返回值内容是:失败返回-1;成功无返回值内容(代表新程序的运行)。
进行一个简单的接口操作示范便如上图所示,其中对于运行参数和环境变量是随意设置的,不用关心。主要体会程序替换的逻辑和execve接口实现的效果。
2.2execv
值得注意的是,对于环境变量env的设置,其实没有很明显的必要性,很多时候我们只需要使用原有的环境变量便可,所以为了节省程序替换的事件,设计者们推出execv函数来实现程序替换。
int exevc(char *path, char *argc[]);
对于exevc函数,它并不关心环境变量的设置,它在进行程序替换的时候会直接使用已有的环境变量。
2.3execvp
无论是exevce接口还是execv函数,我们对于替换的程序都需要指明它的路径。这样的行为伴随着一个十分明显的问题:当我们需要对系统指令进行多次调用时,每次的路径指明就很耗费时间。
针对上述execve和execv所存在的一定局限性,于是execvp应运而生,execvp时设计者所封装的一个库函数。
int exevcp(char *file, char *argc[]);
exevcp中的第一个参数不用指明具体的路径,默认会在PATH环境变量指定的路径下进行寻找。
2.4execl
对于上述接口中每次调用时都需要设定一个参数字符指针数组,较为繁琐,尤其在参数较少的情况下,每次定义就十分赘余,所以设计出execl来对其进行优化。
int execl(char *path, …/* char *arg */);
其中形参…(C语言)代表不定参(后面是加入的注释),即参数的个数不定。这样在我们进行程序替换的时候,当参数较少我们只需要将参数挨个输入到execl函数中作为形参,即可保证程序替换的正常运行。
这样很好的避免了当参数较少时,程序替换中设计参数的字符指针数据的步骤。
2.5execlp
同样的,对于指定路径也存在优化,即execlp接口。
int execlp(char *file, …);
2.6execle
int execle(char *path, … ,char *env[]);
和需要指明环境变量的调用接口execle,同样对于程序参数为函数的不定参。