使用execv启动程序并传递参数而不提高argc

时间:2019-01-16 21:25:42

标签: c arguments fork exec argc

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

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

        puts(argv[3]);
        return 0;
    }

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

这是我到目前为止所拥有的:

    int main()
    {
        pid_t pid = fork();

        if(pid == 0)
        {
            char *argv[] = { "filepath", "placeholder",
                             "placeholder, "Hello World!" };
            execv("filepath", argv);
            exit(0);
        }
        else
        {
            waitpid(pid, 0, 0);
        }

        return 0;
    }

这将在Linux上运行。

我尝试了mbj的原始建议,以在arguments数组中传递0,可惜这没有用。但是,如果我将0作为第一个参数,则argc变为0,但是当尝试打印参数时,我得到了输出“ LC_MEASUREMENT = de_DE.UTF-8”。谷歌搜索并没有真正帮助我。

我在这里全神贯注,因此不胜感激。

1 个答案:

答案 0 :(得分:2)

好吧,经过我自己的尝试,我现在想通了。

由于将以NULL0)开头的数组传递给execv会导致程序打印出LC_MEASUREMENT=de_DE.UTF-8,因此我意识到它必须表示{{1 }}是指进程 environment 中的一个元素(LC_MEASUREMENT是用于在Linux中配置语言环境设置的环境变量之一)。

使用argv[3]

的解决方案

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

要访问当前环境,我们需要在execv外部声明environ变量:

main

然后在调用external char **environ; int main() { ... 之前执行此操作:

execv

使用 char *argv[] = { NULL }; environ[2] = "Hello world!"; execv("filepath", argv); 的简单解决方案

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

execve

如上面的代码片段所示,无论我们使用哪种方法, char *argv[] = { NULL }; char *envp[] = { "foo", "bar", "Hello World!", NULL }; execve("filepath", argv, envp); 都必须位于环境的索引"Hello World!"处。

工作原理

之所以起作用,是因为有一个标准,用于在执行程序时如何在进程内存中布置命令行参数和环境:char指针的环境数组位于命令行参数数组之后。

由于这些数组以NULL条目终止,因此看起来像这样:

2

我希望ASCII技术可以帮助您理解为什么在执行这样的程序时+---------+---------------------------------------+ | Args | Environment | +---------+---------+---------+---------+---------+ | NULL | envp[0] | envp[1] | envp[2] | NULL | +---------+---------+---------+---------+---------+ ^ ^ ^ | | | argv[0] argv[1] ... argv[3] argv[3]的含义相同。