execv vs execvp,为什么只有其中之一需要确切的文件路径? [英] execv vs execvp, why just one of them require the exact file's path?

查看:64
本文介绍了execv vs execvp,为什么只有其中之一需要确切的文件路径?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在同一目录中有两个文件.

I have two files in the same directory.

directory/  
| a.c  
| b.c

a

#include <stdio.h>                         
#include <string.h>                        
#include <sys/types.h>                     
#include <unistd.h>                        

int main(int argc, char *argv[])           
{                                          
   pid_t pid;                              
   int status;                             
   int wret;                               

   if ((pid = fork()) < 0)                 
      printf("error");                     
   else if(pid == 0)                       
   {                                       
      printf("%s", argv[1]);               
      execv(argv[1], &argv[1]);            
   }                                       
   else                                    
   {  
      /* respawn */                          
      if ((wret = wait(&status)) != -1)    
      execv(argv[1], &argv[1]);            
   }                                       

   return 0;                               
}       

b.c只是一个打印"hello"的简单程序.

b.c is just a simple program that print "hello".

我想从命令行运行 ./ab ,以使 a 程序调用 exexXX 以执行 b 程序.

I want to run ./a b from the command line to make the a program call exexXX to execute the b program.

我不明白为什么我使用 execv 只能在命令行中编写 ./ab ,而不是如果我使用 execvp 我必须写 ./a ./b.

I don't understand why if I use execv I can write just ./a b in the command line, instead if I use execvp I have to write ./a ./b.

man exec 页面不清晰,因为它报告

The man exec page is not clear because it reports

这些函数的初始参数是文件的名称,将被执行."

"The initial argument for these functions is the name of a file that is to be executed."

谢谢

推荐答案

如果程序名称参数不包含斜杠,则 execvp()函数会在您列出的目录中查找要执行的程序PATH环境变量.如果您的PATH上没有.(当前目录),并且您不在路径中列出的目录之一中,则纯名称(例如 b )将会即使 b 在当前目录中也不会执行.如果名称包含斜杠,则可以是相对的( ./b )或绝对的(/home/someone/src/programs/b ),并将其解释为无需参考PATH环境变量即可执行的文件名.

If the program name argument contains no slashes, the execvp() function looks for the program to execute in the directories listed on your PATH environment variable. If you don't have . (the current directory) on your PATH and you aren't in one of the directories listed on your path, a plain name like b will not be executed, even if b is in the current directory. If the name contains a slash, it can be relative (./b) or absolute (/home/someone/src/programs/b) and it will be interpreted as a file name to be executed without consulting the PATH environment variable.

相反, execv()将程序名称参数中的普通 b 视为 ./b —文件中的名称当前目录并执行(如果存在),否则执行失败.

By contrast, execv() treats a plain b in the program name argument as ./b — the name of the file in the current directory and executes it if it is present, and fails if it is located somewhere else.

有一次,有一条评论问:

At one time, there was a comment that asked:

您是说如果您在.中具有可执行文件b,并且您执行 execv("b",b_args),它将被执行?

Are you saying if you have an executable b in . and you do execv("b", b_args), it will get executed?

在普通的Unix机器上,是的.

On a normal Unix box, yes.

代码 b.c :

#include <stdio.h>
int main(void)
{
    puts("Hello");
    return 0;
}

代码 a.c :

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    char *argv[] = { "b", 0 };
    execv(argv[0], argv);
    fprintf(stderr, "failed to execute '%s'\n", argv[0]);
    return 1;
}

运行这些:

$ (PATH=$(clnpath "$PATH" ".:$PWD"); echopath PATH; ./a)
/Users/jleffler/bin
/opt/informix/12.10.FC6/bin
/Users/jleffler/oss/bin
/Users/jleffler/oss/rcs/bin
/usr/local/mysql/bin
/opt/gcc/v7.3.0/bin
/Users/jleffler/perl/v5.24.0/bin
/usr/local/bin
/usr/bin
/bin
/opt/gnu/bin
/usr/sbin
/sbin
Hello
$

clnpath 脚本通过删除出现在其第二路径中的任何目录名称,来修改作为其第一个参数("$ PATH" )提供的字符串,就像参数(.:: $ PWD" )一样-这是我在需要时即时编辑PATH的方式. echopath 脚本回显 PATH 上的目录(或任何其他类似路径的变量,否则它将处理扩展类似路径的变量的结果,例如"$PATH" ),每行一个-输出显示./Users/jleffler/soq (这是我运行程序的地方)都没有子外壳中的 $ PATH . ./a 运行来自 ac 的代码(没有前面的 ./才能执行),而该代码又运行代码来自 bc ,它会生成 Hello .(如果某些系统无法正常运行,请进行识别.)

The clnpath script modifies the string provided as its first argument ("$PATH") by removing any occurrences of any of the directory names listed in its second path-like argument (".:$PWD") — it's how I edit my PATH on the fly when I need to. The echopath script echoes the directories on PATH (or any other path-like variable, or it will process the result of expanding a pathlike variable, such as "$PATH"), one per line — the output shows that neither . nor /Users/jleffler/soq (which is where I run the program) is on $PATH in the sub-shell. The ./a runs the code from a.c (it would not be executed without that ./ in front), which in turn runs the code from b.c, which produces the Hello. (If there is some system where this does not work, please identify it.)

我还可以安排 b.c 为:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    puts("Hello");
    const char *env = "PATH";
    char *val = getenv(env);
    if (val == 0)
        val = "<nothing>";
    printf("%s=%s\n", env, val);
    return 0;
}

这将直接从可执行文件中打印 $ PATH 的值(以验证是否未列出.或当前工作目录的值).

which would print the value of $PATH directly from the executable (to verify that neither . nor the value of the current working directory is listed).

这篇关于execv vs execvp,为什么只有其中之一需要确切的文件路径?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆