execv vs execvp,为什么只有其中之一需要确切的文件路径? [英] execv vs execvp, why just one of them require the exact file's path?
问题描述
我在同一目录中有两个文件.
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 doexecv("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屋!