关于exec系列函数的文件路径问题及延伸

转载来至于:

http://blog.csdn.net/abcdef0966/article/details/5725541






  1. 源代码:  
  2. /********************************************************* 
  3. prog8-8.c 
  4. APUE第二版 P191 程序清单8-8 exec函数实例 
  5.  
  6. ************************************************************/  
  7. #include <stdlib.h>  
  8. #include <stdio.h>  
  9. #include <unistd.h>  
  10. #include <sys/wait.h>  
  11. #include <errno.h>  
  12.   
  13. char *env_init[] = { "USER=unknown""PATH=/tmp", NULL};  
  14.   
  15. int main(void)  
  16. {  
  17.     pid_t pid;  
  18.   
  19.     if ( (pid = fork()) < 0)  
  20.     {  
  21.         printf("fork error.");  
  22.         exit(1);  
  23.     }  
  24.     else if (pid == 0)  
  25.     {  
  26.         //调用prog8-9.c生成的可执行程序echoall,该可执行程序在/home/user01/apue_exercise下  
  27.         //调用此execle相当于在echoall目录下执行./echoall myarg1 "MY ARG2"  
  28.         if (execle("~/apue_exercise/echoall""echoall""myarg1", /  
  29.                "MY ARG2", (char*)0, env_init) < 0)  
  30.         {  
  31.             printf("%s/n", strerror(errno));  
  32.             exit(1);  
  33.         }  
  34.     }  
  35.   
  36.     if (waitpid(pid, NULL, 0) < 0)  
  37.     {  
  38.         printf("wait error./n");  
  39.         exit(1);  
  40.     }  
  41.   
  42.     if ((pid = fork()) < 0)  
  43.     {  
  44.         printf("fork error./n");  
  45.         exit(1);  
  46.     }  
  47.     else if (pid == 0)  
  48.     {  
  49.          if (execlp("echoall""echoall""only 1 arg", (char *)0) < 0)  
  50.          {  
  51.              printf("%s/n", strerror(errno));  
  52.              exit(1);  
  53.          }  
  54.     }  
  55.   
  56.     exit(0);  
  57. }  
  

 

  1. /**************************************************** 
  2.  
  3. prog8-9.c 
  4.  
  5. APUE第二版 P192 
  6.  
  7. 程序清单8-9 回送所有命令行参数和所有环境字符串 
  8.  
  9.   
  10.  
  11.   
  12.  
  13. ******************************************************/  
  14.   
  15. #include <stdlib.h>  
  16.   
  17. #include <stdio.h>  
  18.   
  19.    
  20.   
  21. int main(int argc, char *argv[])  
  22.   
  23. {  
  24.   
  25.     int i;  
  26.   
  27.    
  28.   
  29.     for (i = 0; i < argc; i++)  
  30.   
  31.     {  
  32.   
  33.         printf("argv[%d]: %s/n", i, *argv++);  
  34.   
  35.     }  
  36.   
  37.    
  38.   
  39.     exit(0);  
  40.   
  41. }  
  

问题:

首先,执行 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,所以程序能正确运行。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值