这是函数execlp的原型:
int execlp(const char *file, const char *arg, ...);
手册页说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);
所以问题是,arg0参数在任何情况下都有意义吗?为什么界面是这样设计的?
答案 0 :(得分:9)
主要功能签名是
int main(int argc, char ** argv);
其中argv [0]是可执行文件的名称(在您的情况下为arg0),因此应用程序需要来自argv [1]的命令行。
在某些情况下,单个二进制文件可以有多个名称(例如,busybox,有时使用具有不同名称的符号链接,指向单个二进制文件)。在这种情况下 argv [0]用于确定用于调用二进制文件的链接。
答案 1 :(得分:6)
程序可以使用argv[0]
以不同的方式运行,具体取决于它们的调用方式。
例如,请参阅xgs-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;
}
答案 2 :(得分:6)
您可以尝试execlp("ls", "not_ls", "--help", 0)
来查看差异。然后,ls
会被欺骗,认为它是not_ls
,并打印出如下内容:
Usage: not_ls [OPTION]... [FILE]...
答案 3 :(得分:2)
是的,参数都是有意义的。
第一个参数确定调用哪个可执行文件,其余参数确定可执行文件将接收哪些参数,包括它认为它被调用的内容。
C程序通过argc
和argv
和
int main(int argc, char* argv[]);
这对多呼叫二进制文件特别有用,例如busybox,它们的行为会有所不同,具体取决于它们的调用方式。
答案 4 :(得分:2)
你的最后一次电话
execlp("ls", "-a" , 0);
没有足够的参数可以像以前那样工作。如果你改为打电话
execlp("ls", "-a" , "-a", 0);
它应该与你的前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);
这就是为什么你得到不同的帮助输出,正如安德烈所示。
正如Chris S所说,根据argv [0]的说法,某些程序的编码行为会有所不同。但是GNU ls不是那些程序之一。坦率地说,我想知道为什么不这样做,因为他们使用相同的ls.c代码来编译ls和#34; dir"和" vdir",但这些是通过ls-vdir.c和ls-dir.c编译为不同的二进制文件。有一个标题,ls。那个
#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;
然后以ls-vdir.c为例。整个文件由
组成#include "ls.h"
int ls_mode = LS_LONG_FORMAT;
最后回到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]改变它的行为,他们也选择不这样做是出于哲学原因(并且发送给你三个二进制文件)。显然,其他Unix程序员(例如购买者)并不赞同这种理念。