linux系统编程之进程(三)

时间:2020-12-30 14:45:52

今天继续学习进程相关的东东,继上节最后简单介绍了用exec函数替换进程映像的用法,今天将来深入学习exec及它关联的函数,话不多说,正式进入正题:

exec替换进程映象:
linux系统编程之进程(三)
 

对于fork()函数,它创建了一个新进程,新进程与原进程几乎是一样的,而对于shell命令,如:

linux系统编程之进程(三)

对于shell命令,它本身就是一个进程,要想执行ls程序,则需去加载ls程序,这时shell命令进程则需fork()创建一个新进程,而我们知道新创建的进程与原进程几乎是一样的,也就意味着新的进程的代码还是跟shell程序本身是一样的,也就无法执行ls程序,所以,这时我们只有将新进程用ls程序替换,也就是用exec系列函数来替换,这也就是它的意义所在。

linux系统编程之进程(三)

下面以实际代码来简单对exec系列的函数有个初步的认识,下面还会一一对其展开学习的:

exec关联函数组:

 linux系统编程之进程(三)

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

说明:关于execlp函数的具体使用先不用太关心,下面会有详细介绍的,目前先只是拿它来说明一些问题】

那如果被execlp函数替换后的进程ID是否会发生变化呢?为了说明这个问题,我们先编写一个打印进程ID的程序:

linux系统编程之进程(三)

hello.c:

linux系统编程之进程(三)

编译,会用execl替换我们编写的程序,来论证我们提出的问题:

linux系统编程之进程(三)

再来用execl替换成我们写的hello程序:

linux系统编程之进程(三)

这时运行:

linux系统编程之进程(三)

如果将程序做一点小改动,如下:

linux系统编程之进程(三)

这时编译运行:

linux系统编程之进程(三)

这时为什么呢?这是因为execlp函数执行失败了,所以没有替换成功,可以打印一下错误信息:

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

这时因为:

linux系统编程之进程(三)

其中linux的环境变量如下:

linux系统编程之进程(三)

下面就具体对execlp系列的每个函数进行研究,先从整体上来看一下这些函数:

linux系统编程之进程(三)

下面用代码来演示一下execlp与execvp这两个函数用法的差别:

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

换成不带l的函数,看下它的使用方式:

linux系统编程之进程(三)

其运行结果跟上面一样,这就是带l的函数与不带l函数的使用区别。

 下面来说明一下函数参数的意义:

linux系统编程之进程(三)

下面,我们来研究一下下面两个函数的区别:

linux系统编程之进程(三)

 linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

这是因为execl中的程序名需要带上全路径,而execlp不需要定全路径,会自动在环境变量中去搜寻,这就是带p与不带p的区别,于是我们看一下ls命令的路径:

linux系统编程之进程(三)

于是,将这个路径替换一下:

linux系统编程之进程(三)

再次编译运行:

linux系统编程之进程(三)

所以,对于下面这两个函数也就明白啥区别了:

linux系统编程之进程(三)

这里就不做实验了,对于exec系列的函数,最后还剩一个execle函数:

linux系统编程之进程(三)

下面就以实际代码来解析下这个参数的含义: 

 linux系统编程之进程(三)

hello.c还是之前的代码,再贴出来:

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

下面我们将hello.c来输出程序的环境变量,实际上有对应的shell命令能够输出,效果如下:

linux系统编程之进程(三)

于是改装我们的hello.c:

linux系统编程之进程(三)

而对于environ的数据结构是这样的:

linux系统编程之进程(三)

这时,编译一下执行hello:

linux系统编程之进程(三) 

这时,我们再执行之前替换hello的函数,这时也会输出环境信息:

linux系统编程之进程(三)

这时我们将execl函数,改为execle,并传递我们自己的环境信息:

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

至此,我们已经把exec系列相关的函数的区别,就已经全部学完了,可以好好体会下,对于这些函数,下面再来说明下:

linux系统编程之进程(三)

execve我们可以看一下帮助:

linux系统编程之进程(三)

linux系统编程之进程(三)

最后,再来补充一个知识,在之前我们学过了fcntl函数,可以参考博文:http://www.cnblogs.com/webor2006/p/3500354.html,该函数功能很强大,其中还漏了一个没有学到,就是:

linux系统编程之进程(三)

linux系统编程之进程(三)

看一下具体代码:

linux系统编程之进程(三)

编译运行:

linux系统编程之进程(三)

如果没有用fcntl设置,我们是能看到./hello程序的输出结果的,这也就是FD_CLOEXEC标志的作用了,它会对exec系列的函数产生影响,记住这点就可以了。

其实,打开一个文件时,也可以带上FD_CLOEXEC:

linux系统编程之进程(三)

好了,今天的学习学到这,下节见!