关于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

传递给execveargv用于构造即将启动的二进制文件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] 以了解它是否被称为 lspspwd,等等