Shr*_*har 114 command-line c arguments
典型的 Unix/Linux 程序接受命令行输入作为参数计数 ( int argc) 和参数向量 ( char *argv[])。的第一个元素argv是程序名称 - 后跟实际参数。
为什么程序名称作为参数传递给可执行文件?是否有使用自己名称的程序示例(可能是某种exec情况)?
cou*_*ode 131
首先,请注意这argv[0]不一定是程序名称。这是调用者argv[0]在execve系统调用中输入的内容(例如,请参阅Stack Overflow 上的这个问题)。( 的所有其他变体exec都不是系统调用,而是到 的接口execve。)
例如,假设以下内容(使用execl):
execl("/var/tmp/mybackdoor", "top", NULL);
Run Code Online (Sandbox Code Playgroud)
/var/tmp/mybackdoor是执行但argv[0]设置为 的内容top,这就是ps或(真实的)top将显示的内容。有关更多信息,请参阅U&L SE 上的此答案。
设置所有的这一边:花哨的文件系统的出现和以前一样/proc,argv[0]是一个过程,了解了自己的名字的唯一途径。那有什么用呢?
mur*_*uru 65
大量:
argv[0]shargv[0]-vi,view,evim,eview,ex,vimdiff,等。shutdown、reboot、 等的系统中, 是到systemctl的符号链接。dir*_*rkt 37
从历史上看,argv它只是一个指向命令行“单词”的指针数组,因此从第一个“单词”开始是有意义的,它恰好是程序的名称。
并且有相当多的程序根据用于调用它们的名称而表现出不同的行为,因此您可以创建指向它们的不同链接并获得不同的“命令”。我能想到的最极端的例子是busybox,它就像几十个不同的“命令”,具体取决于它的调用方式。
编辑:根据要求提供 Unix 第一版的参考
例如,可以从它的主要功能中cc看到argc并且argv已经使用了。该外壳拷贝参数传递给parbuf里面的newarg循环的一部分,而在处理方式相同参数的命令本身。(当然,稍后它只执行第一个参数,即命令的名称)。好像execv那时候没有亲戚。
rud*_*ier 23
用例:
您可以使用程序名称来更改程序行为。
例如,您可以创建一些指向实际二进制文件的符号链接。
使用这种技术的一个著名例子是 busybox 项目,它只安装一个二进制文件和许多符号链接。(ls、cp、mv 等)。他们这样做是为了节省存储空间,因为他们的目标是小型嵌入式设备。
这也在setarchutil-linux 中使用:
$ ls -l /usr/bin/ | grep setarch
lrwxrwxrwx 1 root root 7 2015-11-05 02:15 i386 -> setarch
lrwxrwxrwx 1 root root 7 2015-11-05 02:15 linux32 -> setarch
lrwxrwxrwx 1 root root 7 2015-11-05 02:15 linux64 -> setarch
-rwxr-xr-x 1 root root 14680 2015-10-22 16:54 setarch
lrwxrwxrwx 1 root root 7 2015-11-05 02:15 x86_64 -> setarch
Run Code Online (Sandbox Code Playgroud)
他们在这里使用这种技术基本上是为了避免许多重复的源文件或只是为了保持源代码的可读性。
另一个用例是需要在运行时加载一些模块或数据的程序。拥有程序路径使您能够从相对于程序位置的路径加载模块。
此外,许多程序会打印错误消息,包括程序名称。
为什么:
man 3p execve):argv 是传递给新程序的参数字符串数组。按照惯例,这些字符串中的第一个应该包含与正在执行的文件相关联的文件名。
如果argc的值大于零,则argv[0]指向的字符串代表程序名;如果宿主环境中的程序名称不可用,则 argv[0][0] 应为空字符。
注意 C 标准说的是“程序名”而不是“文件名”。
mar*_*elm 23
除了根据调用方式改变其行为的程序之外,我发现argv[0]打印程序的用法很有用,如下所示:
printf("Usage: %s [arguments]\n", argv[0]);
Run Code Online (Sandbox Code Playgroud)
这会导致使用消息始终使用调用它的名称。如果程序被重命名,它的使用信息也会随之改变。它甚至包括调用它的路径名:
# 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]
Run Code Online (Sandbox Code Playgroud)
这是一个很好的接触,特别是对于可能无处不在的小型专用工具/脚本。
这在 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.
Run Code Online (Sandbox Code Playgroud)
一个执行程序键入:
program_name0 arg1 arg2 arg3 ...。
所以shell应该已经划分了token,第一个token已经是程序名了。顺便说一句,因此在程序端和外壳上有相同的索引。
我认为这只是一个方便的技巧(在最开始时),并且正如您在其他答案中看到的那样,它也非常方便,因此延续了这一传统并将其设置为 API。
基本上, argv 包含程序名称,以便您可以编写类似 的错误消息prgm: file: No such file or directory,这将使用以下内容实现:
fprintf( stderr, "%s: %s: No such file or directory\n", argv[0], argv[1] );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25697 次 |
| 最近记录: |