为什么我们必须在exec函数中两次传递文件名?


12

我读 8 章的Stevens撰写的《 UNIX环境中的高级编程》。我阅读并理解了exec函数的全部六个。

我注意到的一件事是,在所有exec函数中:

  • 第一个参数是文件名/路径名(取决于exec函数)。
  • 第二个参数是我们输入的argv [0] main(),它是文件名本身。

因此,这里我们必须在函数中两次传递文件名。

是否有任何原因(例如我们无法从第一个参数的路径名中获取文件名)?

Answers:


15

因此,这里我们必须在函数中两次传递文件名。

通过观察将其中之一用作argv[0]值,它们与您注意到的完全不同。这不必与可执行文件的基本名称相同。许多/大多数事物都忽略了它,您可以在其中放置任何内容。

第一个是可执行文件的实际路径,显然有必要。表面上,第二个作为用于调用它的名称传递给该进程,但是,例如:

execl("/bin/ls", "banana", "-l", NULL);

会正常工作,假定/bin/ls是正确的路径。

但是,某些应用程序确实使用argv[0]。通常,这些链接中包含一个或多个符号链接$PATH;这在压缩实用程序中很常见(有时它们使用Shell包装器代替)。如果已xz安装,则stat $(which xzcat)表明它是的链接xz,并man xzcatman xz解释“ xzcat等效于xz --decompress --stdout”的解释相同。xz知道如何调用它的方法是通过检查argv[0],使它们等效:

execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);

5
嗯,所以这可以解释busybox您如何将其定义为正确的名称?
terdon

4
@terdon正是busybox的单个二进制文件满足了许多不同命令的方式。
2015年

7
这意味着如果/bin/ls是busybox,它将不知道如何执行banana
Riking

6

您不必两次传递文件名。

第一个是实际执行的文件。

第二个参数是argv[0]流程的名称,即流程应将其视为什么。例如,如果您ls从外壳程序运行,则第一个参数是/bin/ls,第二个参数是just ls

您可以执行某个文件,然后通过第二个参数将其调用。程序可以检查其名称,并根据名称进行不同的处理。这也可以通过硬链接(或符号链接)来完成,但是这种方式提供了更大的灵活性。


实际上,链接是相同的方法,因为它设置argv[0]为链接名称。
goldilocks 2015年

在最后一段中,“您可以执行某个文件,并通过第二个参数调用其他文件;该程序可以检查其名称,并根据名称表现不同”。您能详细说明一下还是给我一些阅读资料,我对这种环境是陌生的。
munjal007'3

goldilocks答案的最后一部分对此进行了解释。
Wurtel

1

要点是argv[0]可以设置为任何值(包括NULL)。按照约定argv[0]将设置为可执行文件的启动路径(由shell进程执行时execve())。

如果./foodir/bar是指向同一可执行文件的两个不同链接(硬链接或符号链接),则使用两个路径从shell启动程序将分别设置argv[0]./foodir/bar

argv[0]可以NULL忽略的事实常常被忽略。例如,以下代码可能会崩溃NULL argv[0](尽管glibc打印类似<null>的内容argv[0]):

if (argc != 3) {
    fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
    exit(EXIT_FAILURE);
}

Linux上的一种替代方法是/proc/self/exe用于这种情况。


您如何将argv [0]设置为./foo和dir / bar
munjal007,2015年

@ munjal007很抱歉,如果我不清楚。我的意思是两次运行该程序:一次./foo和一次dir/barargv[0]在这两种情况下会有所不同(在每种情况下,它都将与您使用的路径相同)。
Ulfalizer'3

@ munjal007当然,假设您从外壳程序运行它。关键是您自己编程argv[0]时可以设置为任何内容exec*()。将外壳程序设置argv[0]为用于启动程序的路径是一种惯例(并且明智的做法是在您exec*()编写程序时执行此操作,因为许多程序会检查argv[0]并希望它保留路径)。
Ulfalizer'3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.