转载来至于:
http://blog.csdn.net/abcdef0966/article/details/5725541
- 源代码:
- /*********************************************************
- prog8-8.c
- APUE第二版 P191 程序清单8-8 exec函数实例
- ************************************************************/
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <errno.h>
- char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL};
- int main(void)
- {
- pid_t pid;
- if ( (pid = fork()) < 0)
- {
- printf("fork error.");
- exit(1);
- }
- else if (pid == 0)
- {
- //调用prog8-9.c生成的可执行程序echoall,该可执行程序在/home/user01/apue_exercise下
- //调用此execle相当于在echoall目录下执行./echoall myarg1 "MY ARG2"
- if (execle("~/apue_exercise/echoall", "echoall", "myarg1", /
- "MY ARG2", (char*)0, env_init) < 0)
- {
- printf("%s/n", strerror(errno));
- exit(1);
- }
- }
- if (waitpid(pid, NULL, 0) < 0)
- {
- printf("wait error./n");
- exit(1);
- }
- if ((pid = fork()) < 0)
- {
- printf("fork error./n");
- exit(1);
- }
- else if (pid == 0)
- {
- if (execlp("echoall", "echoall", "only 1 arg", (char *)0) < 0)
- {
- printf("%s/n", strerror(errno));
- exit(1);
- }
- }
- exit(0);
- }
- /****************************************************
- prog8-9.c
- APUE第二版 P192
- 程序清单8-9 回送所有命令行参数和所有环境字符串
- ******************************************************/
- #include <stdlib.h>
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- int i;
- for (i = 0; i < argc; i++)
- {
- printf("argv[%d]: %s/n", i, *argv++);
- }
- exit(0);
- }
问题:
首先,执行 gcc -o echoall prog8-9.c
这样,echoall就在prog8-9.c的目录/home/user01/apue_exercise下。
然后执行gcc prog8-8.c
./a.out
发现在exec处报错:No such file or directory
No such file or directory
两次调用exec函数都找不到可执行文件!!
解决方法:
其一、
发现APUE 第二版P188页8.10exec函数一节写到:
(execlp execvp)当指定filename作为参数时:
如果filename中包含/,则将其视为路径名。
否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件。
于是查看当前的PATH环境变量echo $PATH, 很明显,echoall所在的目录不在PATH环境变量中,只好在执行程序前先手动将当前目录(即/home/user01/apue_exercise加上。
$export PATH=$PATH:$PWD
这样,再执行./a.out
$./a.out
输出结果:
No such file or directory
argv[0]: echoall
argv[1]: only 1 arg
说明execlp的调用执行正确了。那第一次调用execle为什么会出错呢?
其二、
if (execle("~/apue_exercise/echoall", "echoall", "myarg1", /
"MY ARG2", (char*)0, env_init) < 0)
试着将这句代码中引用的路径改为:
/home/user01/apue_exercise/echoll,
即
if (execle("/home/user01/apue_exercise/echoall ", "echoall", "myarg1", /
"MY ARG2", (char*)0, env_init) < 0)
再次执行:
$export PATH=$PATH:$PWD
$./a.out
输出结果:
argv[0]: echoall
argv[1]: myarg1
argv[2]: MY ARG2
argv[0]: echoall
argv[1]: only 1 arg
执行正确!
那么,为什么不能在此处使用~呢?
原因是由于~只是shell对$home的引用,在系统函数中是不会对此进行相同的扩展的。
系统函数如何解释路径呢?
$man path_resolution
可得到相关的信息。大致意思如下:
某些unix/linux系统调用有文件名参数。文件名(或路径名)按下列方式解析:
如果路径名以/开头,则从当前进程的root目录开始查找路径。此所谓绝对路径。
如果路径名不以/开头,则从该进程的当前工作目录开始查找。此所谓相对路径。
一般情况下,每个目录都有一个”. “和 “..”, 用于表示当前目录和父目录。这也是能被正确解析的。
据此来看,系统调用并不能解析~。
试验:
因为echoall在当前工作目录下,
所以将
if (execle("/home/user01/apue_exercise/echoall ", "echoall", "myarg1", /
"MY ARG2", (char*)0, env_init) < 0)
改为
if (execle("echoall ", "echoall", "myarg1", "MY ARG2", (char*)0, env_init) < 0)
或者
if (execle("./echoall ", "echoall", "myarg1", /
"MY ARG2", (char*)0, env_init) < 0)
两个路径都能被正确解析,并且能够在进程的当前目录中找到echoall,所以程序能正确运行。