使用 execv 启动程序并在不提高 argc 的情况下传递参数

Luc*_*caW 2 c arguments fork argc

我在课堂上得到了这个代码:

    int main(int argc, char **argv)
    {
        if(argc)
        {
            return 1;
        }

        puts(argv[3]);
        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

现在,我应该编写第二个程序来执行它并使其打印“Hello World!”。所以我必须找到一种方法来传递参数(我假设使用 execv)同时让 argc 保持在 0。

这是我到目前为止:

    int main(int argc, char **argv)
    {
        if(argc)
        {
            return 1;
        }

        puts(argv[3]);
        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

这将在 Linux 上运行。

我尝试了 mbj 最初的建议,在参数数组中传递一个 0,但遗憾的是没有奏效。但是,如果我将 0 作为第一个参数,argc 将变为 0,但是当我尝试打印参数时会得到输出“LC_MEASUREMENT=de_DE.UTF-8”。谷歌搜索这也没有真正帮助我。

我在这里完全不知所措,所以任何帮助表示赞赏。

mbj*_*mbj 5

好的,经过我自己的一些实验,我现在想通了。

由于传递以NULL( 0)开头的数组会execv导致程序打印出来LC_MEASUREMENT=de_DE.UTF-8,我意识到它一定意味着指的argv[3]是进程环境中的一个元素(LC_MEASUREMENT 是用于在 Linux 中配置语言环境设置的环境变量之一)。

解决方案 execv

由于execv会将当前环境复制到新程序中,因此我们只需要修改环境并将字符串"Hello World!"放在正确的位置,然后再调用execv. 事实证明,打印的字符串是环境的索引 2 指向的字符串。

要访问当前环境,我们需要在environ之外声明变量main

external char **environ;

int main() 
{
    ...
Run Code Online (Sandbox Code Playgroud)

然后在调用之前执行此操作execv

        char *argv[] = { NULL };
        environ[2] = "Hello world!";
        execv("filepath", argv);
Run Code Online (Sandbox Code Playgroud)

更简单的解决方案 execve

我们可以使用该函数,而不是external char **environ在调用之前声明和修改当前环境,它让我们传入一个新的字符串数组作为程序的环境:execvexecve

        char *argv[] = { NULL };
        char *envp[] = { "foo", "bar", "Hello World!", NULL };
        execve("filepath", argv, envp);
Run Code Online (Sandbox Code Playgroud)

如上面的代码片段所示,无论我们使用哪种方法,都"Hello World!"需要2位于环境的索引处。

这个怎么运作

这样做的原因是,当程序执行时,命令行参数和环境在进程内存中的布局有一个标准:字符指针的环境数组放在命令行参数数组之后。

由于这些数组以 NULL 条目终止,因此它将如下所示:

+---------+---------------------------------------+ 
| Args    | Environment                           |
+---------+---------+---------+---------+---------+
|  NULL   | envp[0] | envp[1] | envp[2] |  NULL   | 
+---------+---------+---------+---------+---------+
    ^         ^                   ^                     
    |         |                   |
 argv[0]    argv[1]     ...     argv[3]
Run Code Online (Sandbox Code Playgroud)

我希望 ASCII 艺术可以帮助您理解为什么argv[3]environ[2]我们执行这样的程序时的含义相同。

  • 谢谢,这个解决方案有效!也感谢您的出色解释,使其非常容易理解。 (2认同)