这是函数execlp的原型:
int execlp(const char *file, const char *arg, ...);
Run Code Online (Sandbox Code Playgroud)
手册页说,arg(按照惯例,"arg0" 的第一个参数应该指向与正在执行的文件相关联的文件名.)
然后我做了这些实验:
/*These three lines all produce the expected result:
. .. a.out main.c */
execlp("ls", "ls", "-a", 0);
execlp("ls", "arg0 is meaningless", "-a" , 0);
execlp("ls", "", "-a" , 0);
/*But this one does not work:
a.out main.c */
execlp("ls", "-a" , 0);
Run Code Online (Sandbox Code Playgroud)
所以问题是,arg0参数在任何情况下都有意义吗?为什么界面是这样设计的?
小智 9
主要功能签名是
int main(int argc, char ** argv);
Run Code Online (Sandbox Code Playgroud)
其中argv [0]是可执行文件的名称(在您的情况下为arg0),因此应用程序期望其命令行来自argv [1].
在某些情况下,单个二进制文件可以有多个名称(例如,busybox,有时使用具有不同名称的符号链接,指向单个二进制文件).在这种情况下,argv [0]用于确定使用哪个链接来调用二进制文件.
小智 6
程序可以argv[0]根据它们的调用方式使用不同的行为.例如,从xz-utils的args.c中看到这个片段:
const char *name = strrchr(argv[0], '/');
if (name == NULL)
name = argv[0];
else
++name;
// Look for full command names instead of substrings like
// "un", "cat", and "lz" to reduce possibility of false
// positives when the programs have been renamed.
if (strstr(name, "xzcat") != NULL) {
opt_mode = MODE_DECOMPRESS;
opt_stdout = true;
} else if (strstr(name, "unxz") != NULL) {
opt_mode = MODE_DECOMPRESS;
} else if (strstr(name, "lzcat") != NULL) {
opt_format = FORMAT_LZMA;
opt_mode = MODE_DECOMPRESS;
opt_stdout = true;
} else if (strstr(name, "unlzma") != NULL) {
opt_format = FORMAT_LZMA;
opt_mode = MODE_DECOMPRESS;
} else if (strstr(name, "lzma") != NULL) {
opt_format = FORMAT_LZMA;
}
Run Code Online (Sandbox Code Playgroud)
您可能会尝试execlp("ls", "not_ls", "--help", 0)看到差异.ls然后会被欺骗,以为它是这样的,not_ls并打印如下:
Usage: not_ls [OPTION]... [FILE]...
Run Code Online (Sandbox Code Playgroud)
你的最后一个电话
execlp("ls", "-a" , 0);
Run Code Online (Sandbox Code Playgroud)
没有足够的参数来像以前的那样工作。如果你改为调用
execlp("ls", "-a" , "-a", 0);
Run Code Online (Sandbox Code Playgroud)
它的工作方式应该与您的前 3 个调用相同,除非您的发行版中的 ls 有一些编码行为,如果其名称以“-”开头,则工作方式不同,但我怀疑它确实如此。
通常 ls 只是执行 set_program_name(argv[0]) ,这就是它使用 argv[0] 的全部目的。请参阅来源:http://git.savannah.gnu.org/gitweb/ ?p=coreutils.git;a=blob;f=src/ls.c;h=cd5996eb979f9e9319089e8c065b1276a1fbece8;hb=refs/heads/master 。该调用设置了名为program_name的变量,然后用它来打印用法
printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
Run Code Online (Sandbox Code Playgroud)
这就是为什么您会得到安德烈所示的不同帮助输出。
正如 Chris S 所说,某些程序的编码行为有所不同,具体取决于它们如何根据 argv[0] 进行调用。但 GNU ls 不是这些程序之一。坦率地说,我想知道为什么不,因为他们使用相同的 ls.c 代码来编译 ls 以及“dir”和“vdir”,但它们通过 ls-vdir.c 和 ls-dir.c 编译为不同的二进制文件。有一个标题,ls。h 有
#define LS_LS 1
/* This is for the 'dir' program. */
#define LS_MULTI_COL 2
/* This is for the 'vdir' program. */
#define LS_LONG_FORMAT 3
extern int ls_mode;
Run Code Online (Sandbox Code Playgroud)
然后查看 ls-vdir.c 例如。整个文件由以下部分组成
#include "ls.h"
int ls_mode = LS_LONG_FORMAT;
Run Code Online (Sandbox Code Playgroud)
最后回到 ls.c,现在顶部的评论如下
如果 ls_mode 为 LS_LONG_FORMAT,则无论输出设备的类型如何,都默认使用长格式。这是针对“vdir”程序的。
应该开始有意义了。
有些人甚至认为传送 3 个二进制文件(ls、dir 和 vdir)而不是一个是一个错误https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=16312但这显然是设计为最后一个https://bugs.archlinux.org/task/2767中的评论(引用自http://www.gnu.org/prep/standards/html_node/User-Interfaces.html)说
请不要使实用程序的行为取决于调用它的名称。有时用不同的名称链接到实用程序是很有用的,但这不应改变它的功能。
所以 GNU 不是 Unix ;-) 尽管他们可以通过 argv[0] 使 ls 改变其行为,但出于哲学原因他们选择不这样做(而是向您提供三个二进制文件)。显然,其他 Unix 程序员(例如 buysbox 的人)并不认同这种理念。
| 归档时间: |
|
| 查看次数: |
1630 次 |
| 最近记录: |