lienhua34
2014-10-07
在文档“进程控制三部曲”中,我们提到 fork 函数创建子进程之后,通常都会调用 exec 函数来执行一个新程序。调用 exec 函数之后,该进程就将执行的程序替换为新的程序,而新的程序则从 main 函数开始执行。
UNIX 提供了 6 种不同的 exec 函数供我们使用。它们的原型如下所示,
#include <unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */);
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */);
int execvp(cosnt char *filename, char *const argv[]);
6个函数的返回值:若出错则返回-1,若成功则没有返回值
可能很多人会觉得这六个函数太难记了。但是,我们仔细观察会发现,这六个函数的命名是有一些规律的。
• 含有 l 和 v 的 exec 函数的参数表传递方式是不同的。
• 含有 e 结尾的 exec 函数会传递一个环境变量列表。
• 含有 p 结尾的 exec 函数取的是新程序的文件名作为参数,而其他exec 函数取的是新程序的路径。
exec 函数给新程序传递参数表方式的不同可以通过 exec 函数名称来体现。含有 l(l 表示 list)的 exec 函数(execl、execle 和 execlp)将新程序的参数表以列表的方式传递,要求每个命令行参数作为一个单独的参数,最后空指针结尾。含有 v(v 表示 vector)的 exec 函数(execv、execve 和execvp)将新程序的参数表构造成一个数组进行传递。下面我们来看一个例子,我们有一个程序 echoargs.c,其输出所有的命令行参数。
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) { printf("arg%d: %s\n", i, argv[i]); } exit(0); }
编译该程序,生成 echoargs 文件,
lienhua34:demo$ gcc -o echoargs echoargs.c
然后在我们的 execdemo.c 中分别以两种不同参数表传递方式来调用execl 和 execv 函数,
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/wait.h> char echoargsPath[] = "/home/lienhua34/program/c/apue/ch08/demo/echoargs"; char *myargs[] = {"echoargs", "This", "is", "a", "demo" }; int main(void) { pid_t pid; if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { printf("Transmits arguments by vector\n"); if (execv(echoargsPath, myargs) < 0) { printf("execv error: %s\n", strerror(errno)); exit(-1); } } wait(NULL); if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { printf("Transmits arguments by list\n"); if (execl(echoargsPath, myargs[0], myargs[1], myargs[2], myargs[3], "another", myargs[4], (char *)0) < 0) { printf("execv error: %s\n", strerror(errno)); exit(-1); } } wait(NULL); exit(0); }