关于execve参数的困惑
Confusion about execve parameters
我的教授编写了一个程序,它使用 execve()
打印工作目录 (pwd
),但我不理解参数。
pid_t pid = fork();
if(pid <0)
perror(NULL);
else if(pid == 0)
{
char*argv[] = {"pwd",NULL};
execve("/bin/pwd",argv,NULL);
perror(NULL);
}
else
printf("Im the parent!");
return 0;
}
"/bin/pwd"
给出将要执行的可执行文件的路径。
这意味着它将调用 pwd
函数,不是吗?
那为什么我需要参数 pwd
?
如果没有那个参数,程序不能运行吗?
来自 execve 手册页:http://man7.org/linux/man-pages/man2/execve.2.html
argv is an array of argument strings passed to the new program. By
convention, the first of these strings (i.e., argv[0]) should contain
the filename associated with the file being executed. envp is an
array of strings, conventionally of the form key=value, which are
passed as environment to the new program. The argv and envp arrays
must each include a null pointer at the end of the array.
因此,argv
被视为用于执行新程序的命令行参数。
因为默认情况下,对于使用参数调用的 linux 二进制文件,这些参数通过 argc
/argv
访问,其中 argv[0]
包含程序名称。
我认为这是为了保持行为奇偶校验以匹配默认情况(使用参数调用程序)。
来源:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/exec.c#l1376
传递给execve
的argv
用于构造即将启动的二进制文件argv
。
execve man page 对此有一些提及。重点是我的。
By convention, the first of these strings should contain the filename associated with the file being executed.
也就是说,第一个 argv
并不是必须的文件名。事实上,可以通过将 argv[0]
更改为示例代码中的任何字符串来测试这一点,结果仍然是正确的。
所以这真的只是一个惯例。许多程序将使用 argv[0]
并期望它是文件名。但是很多程序也不关心 argv[0]
(比如 pwd
)。所以 argv[0]
是否真的需要设置为文件名取决于正在执行的程序。话虽如此,明智的做法是始终遵循惯例,以很好地满足几乎每个人长期以来的期望。
按照惯例,传递给程序的第一个参数是可执行文件的文件名。但是,不一定非得如此。
以下面的程序为例:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("number of arguments: %d\n", argc);
printf("program name: %s\n", argv[0]);
for (i=1; i<argc; i++) {
printf("arg %d: %s\n", argv[i]);
}
return 0;
}
如果你 运行 这个程序来自另一个这样的:
char*argv[] = {"myprog", "A", "B", NULL};
execve("/home/dbush/myprog",argv,NULL);
以上将输出:
number of arguments: 3
program name: myprog
arg 1: A
arg 2: B
但你也可以运行像这样
char*argv[] = {"myotherprog", "A", "B", NULL};
execve("/home/dbush/myprog",argv,NULL);
它会输出:
number of arguments: 3
program name: myotherprog
arg 1: A
arg 2: B
您可以使用 argv[0]
的值来了解您的程序是如何被调用的,并可能在此基础上公开不同的功能。
流行的 busybox 工具就是这样做的。单个可执行文件 link 具有不同的文件名。根据哪个 link 用户使用 运行 可执行文件,它可以读取 argv[0]
以了解它是否被称为 ls
、ps
、pwd
,等等
我的教授编写了一个程序,它使用 execve()
打印工作目录 (pwd
),但我不理解参数。
pid_t pid = fork();
if(pid <0)
perror(NULL);
else if(pid == 0)
{
char*argv[] = {"pwd",NULL};
execve("/bin/pwd",argv,NULL);
perror(NULL);
}
else
printf("Im the parent!");
return 0;
}
"/bin/pwd"
给出将要执行的可执行文件的路径。
这意味着它将调用 pwd
函数,不是吗?
那为什么我需要参数 pwd
?
如果没有那个参数,程序不能运行吗?
来自 execve 手册页:http://man7.org/linux/man-pages/man2/execve.2.html
argv is an array of argument strings passed to the new program. By
convention, the first of these strings (i.e., argv[0]) should contain
the filename associated with the file being executed. envp is an
array of strings, conventionally of the form key=value, which are
passed as environment to the new program. The argv and envp arrays
must each include a null pointer at the end of the array.
因此,argv
被视为用于执行新程序的命令行参数。
因为默认情况下,对于使用参数调用的 linux 二进制文件,这些参数通过 argc
/argv
访问,其中 argv[0]
包含程序名称。
我认为这是为了保持行为奇偶校验以匹配默认情况(使用参数调用程序)。
来源: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/exec.c#l1376
传递给execve
的argv
用于构造即将启动的二进制文件argv
。
execve man page 对此有一些提及。重点是我的。
By convention, the first of these strings should contain the filename associated with the file being executed.
也就是说,第一个 argv
并不是必须的文件名。事实上,可以通过将 argv[0]
更改为示例代码中的任何字符串来测试这一点,结果仍然是正确的。
所以这真的只是一个惯例。许多程序将使用 argv[0]
并期望它是文件名。但是很多程序也不关心 argv[0]
(比如 pwd
)。所以 argv[0]
是否真的需要设置为文件名取决于正在执行的程序。话虽如此,明智的做法是始终遵循惯例,以很好地满足几乎每个人长期以来的期望。
按照惯例,传递给程序的第一个参数是可执行文件的文件名。但是,不一定非得如此。
以下面的程序为例:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("number of arguments: %d\n", argc);
printf("program name: %s\n", argv[0]);
for (i=1; i<argc; i++) {
printf("arg %d: %s\n", argv[i]);
}
return 0;
}
如果你 运行 这个程序来自另一个这样的:
char*argv[] = {"myprog", "A", "B", NULL};
execve("/home/dbush/myprog",argv,NULL);
以上将输出:
number of arguments: 3
program name: myprog
arg 1: A
arg 2: B
但你也可以运行像这样
char*argv[] = {"myotherprog", "A", "B", NULL};
execve("/home/dbush/myprog",argv,NULL);
它会输出:
number of arguments: 3
program name: myotherprog
arg 1: A
arg 2: B
您可以使用 argv[0]
的值来了解您的程序是如何被调用的,并可能在此基础上公开不同的功能。
流行的 busybox 工具就是这样做的。单个可执行文件 link 具有不同的文件名。根据哪个 link 用户使用 运行 可执行文件,它可以读取 argv[0]
以了解它是否被称为 ls
、ps
、pwd
,等等