为什么 argv 包含程序名称?

为什么 argv 包含程序名称?

典型的 Unix/Linux 程序接受命令行输入作为参数计数 ( int argc) 和参数向量 ( char *argv[])。第一个元素argv是程序名称 - 后面是实际参数。

为什么程序名称作为参数传递给可执行文件?是否有任何程序使用自己的名称的示例(也许是某种exec情况)?

答案1

首先,请注意这argv[0]不一定是程序名称。这是调用者argv[0]在系统调用中放入的内容execve(例如,参见Stack Overflow 上的这个问题)。 ( 的所有其他变体exec都不是系统调用,而是 的接口execve。)

例如,假设以下情况(使用execl):

execl("/var/tmp/mybackdoor", "top", NULL);

/var/tmp/mybackdoor是执行但argv[0]设置为 的内容top,这就是psor (真实的)top将显示的内容。看这个答案有关更多信息,请访问 U&L SE。

抛开所有这些不谈:在诸如 之类的奇特文件系统出现之前/procargv[0]是进程了解自己名称的唯一方法。那有什么好处呢?

  • 一些程序根据调用它们的名称(通常通过符号或硬链接,例如BusyBox 的实用程序;该问题的其他答案中提供了更多示例)。
  • 此外,通过 syslog 记录的服务、守护进程和其他程序通常会将其名称添加到日志条目中;如果没有这个,事件跟踪将变得几乎不可行。

答案2

充足:

  • Bash 运行在POSIX模式什么argv[0]时候sh。当argv[0]以 开头时,它作为登录 shell 运行-
  • vi当以、viewevimeviewexvimdiff等方式运行时,Vim 的行为有所不同。
  • Busybox,正如已经提到的。
  • 在以 systemd 作为 init 的系统中,shutdownreboot等是符号链接到systemctl
  • 等等。

答案3

从历史上看,argv它只是指向命令行“单词”的指针数组,因此从第一个“单词”开始是有意义的,它恰好是程序的名称。

并且有相当多的程序根据用于调用它们的名称而表现不同,因此您只需创建指向它们的不同链接并获取不同的“命令”。我能想到的最极端的例子是忙碌盒, 哪个其行为类似于几十个不同的“命令”,具体取决于它的调用方式

编辑: Unix 第一版的参考资料,根据要求

例如可以从主要的cc该功能argcargv已被使用。这将参数复制到循环部分的parbuf内部newarg,同时以与参数相同的方式处理命令本身。 (当然,稍后它只执行第一个参数,即命令的名称)。看来execv那时亲戚还不存在。

答案4

除了程序根据调用方式改变其行为之外,我发现argv[0]打印程序的使用很有用,如下所示:

printf("Usage: %s [arguments]\n", argv[0]);

这会导致使用消息始终使用调用它的名称。如果程序被重命名,其使用信息也会随之改变。它甚至包括调用它的路径名:

# cat foo.c 
#include <stdio.h>
int main(int argc, char **argv) { printf("Usage: %s [arguments]\n", argv[0]); }
# gcc -Wall -o foo foo.c
# mv foo /usr/bin 
# cd /usr/bin 
# ln -s foo bar
# foo
Usage: foo [arguments]
# bar
Usage: bar [arguments]
# ./foo
Usage: ./foo [arguments]
# /usr/bin/foo
Usage: /usr/bin/foo [arguments]

这是一个很好的接触,特别是对于可能遍布各处的小型专用工具/脚本而言。

这在 GNU 工具中似乎也是常见的做法,ls例如:

% ls --qq
ls: unrecognized option '--qq'
Try 'ls --help' for more information.
% /bin/ls --qq
/bin/ls: unrecognized option '--qq'
Try '/bin/ls --help' for more information.

相关内容