您的位置:首页 > 编程语言

exec 函数族 --多进程编程

2015-06-28 00:57 344 查看
(1)exec 函数族说明。 

fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容。我们能否让子进程执行一

个新的程序呢?exec 函数族就提供了一个在进程中执行另一个程序的方法。它可以根据指定的文件名或目

录名找到可执行文件,并用它来取代当前进程的数据段、代码段和堆栈段。在执行完之后,当前进程除了

进程号外,其他内容都被替换了。这里的可执行文件既可以是二进制文件,也可以是 Linux 下任何可执行
的脚本文件。 

只有PID是自己的其他的都被替换掉了,这神似“金蝉脱壳”。其实我们已经知道了fork()之后会原封不动的复制父进程的资源,

这样很消耗时间,如果我们在fork之后直接调用exec,那么复制的资源就没有任何作用了,所以人们设计了“写时拷贝”。

在 Linux 中使用 exec 函数族主要有两种情况。 

① 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用 exec 函数族中的任意一个函数

让自己重生。 

② 如果一个进程想执行另一个程序,那么它就可以调用 fork()函数新建一个进程,然后调用 exec 函
数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。 

(2)exec 函数族语法。 

实际上,在 Linux 中并没有 exec()函数,而是有 6 个以 exec 开头的函数,它们之间语法有细微差别,

本书在下面会详细讲解。 

表 3.2 所示为 exec 函数族的 6 个成员函数的语法。 



这 6 个函数在函数名和使用语法的规则上都有细微的区别,下面就可执行文件查找方式、参数表传递

方式及环境变量这几个方面进行比较。 

① 查找方式。读者可以注意到,表 3.2 中的前 4 个函数的查找方式都是完整的文件目录路径,而最

后 2 个函数(也就是以 p 结尾的两个函数)可以只给出文件名,系统就会自动按照环境变量“PATH”所包

含的路径进行查找。 

② 参数传递方式。exec 函数族的参数传递方式有两种:一种是逐个列举的方式,另一种是将所有参

数通过指针数组传递。在这里是以函数名的第 5 位字母来区分的,字母为 l(list)的表示逐个列举参数

的方式,其类型为 const char *arg;字母为 v(vertor)的表示通过指针数组传递,其类型为 char *const 

argv[]。读者可以观察 execl()、execle()、execlp()的语法与 execv()、execve()、execvp()的区别。

它们具体的用法在后面的实例讲解中会具体说明。 

这里的参数实际上就是用户在使用这个可执行文件时所需的全部命令选项字符串(包括该可执行程序

命令本身)。要注意的是,这些参数必须以 NULL 结尾。 

③ 环境变量。exec 函数族可以使用默认的环境变量,也可以传入指定的环境变量。这里以 e

(environment)结尾的两个函数execle()和 execve()就可以在 envp[]中指定当前进程所使用的环境变量。 

表 3.3 对这 4 个函数中函数名和对应语法做一个小结,主要指出了函数名中每一位所表明的含义,希

望读者结合此表加以记忆。 



下面的示例利用函数 execle()将环境变量添加到新建的子进程中,这里的 env 是查看当前进程环境变
量的命令。
/* execle.c */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
/*命令参数列表,必须以 NULL 结尾*/
char *envp[]={"PATH=/tmp","USER=harry", NULL};

if (fork() == 0)
{
/*调用 execle()函数,注意这里也要指出 env 的完整路径*/
if (execle("/usr/bin/env", "env", NULL, envp) < 0)
{
printf("execle error\n");
}
}
}

程序的运行结果如下。
$ ./execle
PATH=/tmp
USER=harry


另外system()也会启动进程,它用来执行shell命令。其实system(const char*string)会调用fork产生子进程,由子进程来调用参数string。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: