首页 > 代码库 > 【Linux&Unix--exec 与 fock 系统调用】
【Linux&Unix--exec 与 fock 系统调用】
个人学习整理,如有不足之处,请不吝指教。转载请注明:@CSU-Max
系列博文:
进程和程序
简单的说,进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。
(2)进程由程序和数据两部分组成,进程是竞争计算机系统有限资源的基本单位,也是进程处理机调度的基本单位。
(3)程序是静态的概念;进程是程序在处理机上一次执行的过程,是动态的概念。
(4)进程有生存周期,有诞生有消亡。是短暂的;而程序是相对长久的。
(5)一个程序可以作为多个进程的运行程序;一个进程也可以运行多个程序。
(6)进程具有创建其他进程的功能;而程序没有。
exec和fock简述
exec系统调用从指定程序重新初始化进程,虽然进程还在,但程序已经改变了。
fock系统调用仅通过复制指令、用户数据和系统数据段来创建从现存进程克隆的新进程,该新进程不是从程序初始化得来的,所以旧进程和新进程执行同样的指令。
除启动UNIX内核本身外,exec是程序在UNIX上获得执行的唯一方法,不仅shell使用exec执行程序,而且shell和其祖先shell也会被exec调用。fock是创建新进程的唯一方式。
详解exec系统调用
事实上,并没有叫做“exec ”的系统调用,所谓的“ exec ”系统调用实际上是6个以execAB形式命名的系统调用,其搭配方式如下图所示:
这里的A可以为 l 或 v ,这取决于参数是直接在调用(列表)中,还是在数组(向量)中;B要么没有,要么为 p ,p 表示使用 PATH 环境变量查找程序,要么为 e ,e 表示使用特定环境。(用户不能在同一调用中同时获得特征 p 和 e 。因此,这6个调用分别为execl,execv, execlp, execvp, execle, execve。
函数原型及解释
//execl -- 执行带参数列表的文件 int execl( const char *path, /*program pathname*/ const char *arg0, /*first arg (file name)*/ const char *arg1, /*second arg (if needed)*/ . . . , (char *) NULL /*arg list terminator*/ );
path参数是一个可由有效用户ID(比如说模式755)执行的程序文件路径名,该可执行程序的内容要正确。
path 参数后面的一组参数收入到一个字符指针数组,且最后一个参数的值为NULL,用来停止收入和终止数组,这组参数的第一个都是程序文件的名字(并不是整个路径)。
通过重新初始化栈,来自程序的指令覆盖了进程的指令段,并且来自程序的数据也覆盖了进程的用户数据,然后进程从顶端执行该新程序(也就是说,调用了它的 mian 函数)。
其他5个 exec 系统调用
//execv -- 执行带参数向量的文件 int execv( const char *path, /*program pathname*/ char *const argv[] /*argument vector*/ ); //execlp -- 执行带参数列表和路径搜索的文件 int execlp( const char *file, /*program file name*/ const char *arg0, /*first arg (file name)*/ const char *arg1, /*second arg (if needed)*/ . . . , (char *) NULL /*arg list terminator*/ ); //execvp -- 执行带参数向量和路径搜索的文件 int execvp( const char *file, /*program file name*/ char *const argv[] /*argument vector*/ ); //execle -- 执行带参数列表和环境变量的文件 int execle( const char *path, /*program pathname*/ const char *arg0, /*first arg (file name)*/ const char *arg1, /*second arg (if needed)*/ . . . , (char *) NULL /*arg list terminator*/ char *const envv[] /*environment vector*/ ); //execve -- 执行带参数向量和环境变量的文件 int execve( const char *path, /*program pathname*/ char *const argv[] /*argument vector*/ char *const envv[] /*environment vector*/ );
注意一下 execlp 和 execvp ,由前面的介绍可知,当B为 p 时,表示使用 PATH 环境变量查找程序,下面让我们来简单的看一下。
若 execlp 或 execvp 的 file 参数没有斜线,则把PATH环境变量中所列出的字符串一个一个与之比较,直到定位到一个带有结果路径名的普通文件,其中结果路径名具有执行权限。
情况一:如果这个文件包含一个可执行程序(在它的第一个字处由一个代码号指示的),便执行它;
情况二:如果不包含一个程序,则将其假定为一个脚本文件,通常为了运行这个脚本文件,都把路径作为shell的第一个参数来执行shell。
如果 PATH 查找的结果证明没有任何内容是可在执行的,则 exec 失败。
若 file 参数中有“ / ”,就不用进行查找,即认为完成了路径查找,但是它仍然可能是一个脚本文件。
详解fock系统调用
在某种程度上,我们可以将 fock与 exec 看作是相反的:fock 可以创建一个新进程,但它并不初始化新程序中的这个进程,相反,新进程的指令、用户数据段和系统数据段几乎就是旧进程的完全复制。
函数原型及解释
//fock -- 创建新进程 pid_t fock(void);
fock调用返回后,两个进程(子进程和父进程)都接收返回值,但返回值是不同的,父进程将接受子进程的进程ID,而子进程接收到的返回值为0.返回 -1 表示出错,但是由于 fock 没有参数,所以极少出错,引发错误的唯一原因便是资源耗尽,如交换空间不足或执行了太多的进程。
当调用 fock 成功后,一般子进程接着执行exec ,而父进程要么等待子进程终止,要么离开去做其他的事情。
fock调用下的父进程与子进程
fork创建的子进程继承了父进程的大部分属性,因为它的系统数据段是从父进程复制而来的。但是也有极少属性没有得到继承:子进程ID与父进程ID是不同的,它们是不同的进程;若父进程正在运行多线程,那么只有执行 fock 的那个线程会存在与子进程中,父进程中的多个线程不会受到什么影响;子进程的累计执行时间会被重置为零,因为它处在生命期的开始。
***************************************************************************
* 转载请注明出处: @CSU-Max http://blog.csdn.net/csu_max *
***************************************************************************