[转]关于exec系列函数的文件路径问题及延伸
原文地址: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); }
[注,此处APUE原书作者的代码不是这样的,请看]
1 #include "apue.h" 2 #include <sys/wait.h> 3 char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL }; 4 int 5 main(void) 6 { 7 pid_t pid; 8 if ((pid = fork()) < 0) { 9 err_sys("fork error"); 10 } else if (pid == 0) { /* specify pathname, specify environment */ 11 if (execle("/home/sar/bin/echoall", "echoall", "myarg1", 12 "MY ARG2", (char *)0, env_init) < 0) 13 err_sys("execle error"); 14 } 15 if (waitpid(pid, NULL, 0) < 0) 16 err_sys("wait error"); 17 if ((pid = fork()) < 0) { 18 err_sys("fork error"); 19 } else if (pid == 0) { /* specify filename, inherit environment */ 20 if (execlp("echoall", "echoall", "only 1 arg", (char *)0) < 0) 21 err_sys("execlp error"); 22 } 23 exit(0); 24 }
#include "apue.h" int main(int argc, char *argv[]) { int i; char **ptr; extern char **environ; for (i = 0; i < argc; i++) printf("argv[%d]: %s\n", i, argv[i]); for (ptr = environ; *ptr != 0; ptr++) printf("%s\n", *ptr); 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,所以程序能正确运行。
作者:红山玉龙
出处:http://www.cnblogs.com/yhLinux/
各位看官如果觉得文章对您有用的话,请猛击右下方大姆指给个推荐,让更多的朋友能够看到,以节约搜索解决方案的时间,用来做更有意义的事情o(∩_∩)o
分享知识是快乐的,也应是自由的。欢迎各位朋友转载,请您在转载时帖上本文原文链接,谢谢!
浙公网安备 33010602011771号