Linux exec函数:arg0参数用于什么?

时间:2014-07-10 13:38:16

标签: c++ c linux unix

这是函数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参数在任何情况下都有意义吗?为什么界面是这样设计的?

5 个答案:

答案 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程序通过argcargv

接收除第一个参数之外的所有参数
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程序员(例如购买者)并不赞同这种理念。