用
其实有六种以
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以
关于char *const的用法,有如下原文说明:
The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn. Together they describe a list of on
这些函数原型看起来很容易混,但只要掌握了规律就很好记。不带字母p(表示path)的exec
如果参数中包含/,则将其视为路径名。
否则视为不带路径的程序名,在PATH
带有字母l(表示list)的exec
对于以e(表示environment)结尾的exec函数,可以把一份新的环境变量表传给它,其他exec函数仍使用当前的环境变量表执行新程序。
char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execvp("ps", ps_argv);
事实上,只有execve是真正的系统调用,其它五个函数最终都调用execve,所以
一个完整的例子:
#include <unistd.h>#include <stdlib.h>int main(void){execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);perror("exec ps");exit(1);}
执行此程序则得到:
$ ./a.outPID PPID PGRP SESS TPGID COMMAND6614 6608 6614 6614 7199 bash7199 6614 7199 6614 7199 ps
由于exec函数只有错误返回值,只要返回了一定是出错了,所以不需要判断它的返回值,直接在后面调用error即可。注意在调用
调用exec后,原来打开的文件描述符仍然是打开的[37]。利用这一点可以实现I/O重定向。先看一个简单的例子,把标准输入转成大写然后打印到标准输出:
例 30.4. upper
/* upper.c */#include <ctype.h>#include <stdio.h>int main(void){int ch;while((ch = getchar()) != EOF) {putchar(toupper(ch));}return 0;}
运行结果如下:
$ ./upperhello THEREHELLO THERE(按Ctrl-D表示EOF)$
使用Shell重定向:
$ cat file.txtthis is the file, file.txt, it is all lower case.$ ./upper < file.txtTHIS IS THE FILE, FILE.TXT, IT IS ALL LOWER CASE.
如果希望把待转换的文件名放在命令行参数中,而不是借助于输入重定向,我们可以利用upper程序的现有功能,再写一个包装程序wrapper。
例 30.5. wrapper
/* wrapper.c */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>int main(int argc, char *argv[]){int fd;if (argc != 2) {fputs("usage: wrapper file\n", stderr);exit(1);}fd = open(argv[1], O_RDONLY);if(fd<0) {perror("open");exit(1);}dup2(fd, STDIN_FILENO);close(fd);execl("./upper", "upper", NULL);perror("exec ./upper");exit(1);}
$ ./wrapper file.txtTHIS IS THE FILE, FILE.TXT, IT IS ALL LOWER CASE.
联系客服