为什么posix_spawn()在popen()工作的地方失败?

时间:2018-02-20 00:18:25

标签: c linux popen spawn

我成功使用popen()从我的C程序中运行命令。据我了解,它使用幕后的fork()exec()(或其变体)。这非常有效:

FILE *fd = popen("xterm", "r");
pclose(fd);

...将按预期启动一个新的xterm窗口。

现在我试图用posix_spawn()来实现同样的目标,我理解这可能更加资源友好,特别是如果我们不打算与新的子进程进行通信:< / p>

/* p.we_wordv contains the argv, index 0 holds the actual command */
pid_t pid;
posix_spawnp(&pid, p.we_wordv[0], NULL, NULL, p.we_wordv, NULL);

...但是,对于命令xterm,在父输出上产生以下内容:

xterm: Xt error: Can't open display:
xterm: DISPLAY is not set

尝试启动其他进程将产生其他错误消息,无提示失败,或者在某些情况下(如ls)按预期工作。这使我实际看到一个模式有点困难。

你能否指出是什么导致第二种方法的行为与第一种方法不同?

1 个答案:

答案 0 :(得分:3)

消息DISPLAY is not set告诉您xterm找不到DISPLAY 环境变量。所有图形输出程序都使用此环境变量连接到您的屏幕。

它没有找到变量,因为环境是空的(它是NULL函数调用中的最后一个posix_spawnp。似乎popen重用当前流程的环境,因此它没有这个问题。

您可能希望传递手动创建的环境,仅包含所需的内容,或者只是传递您的进程所具有的任何环境。后者更灵活(xterm将从您的进程继承各种配置设置,从shell继承它们)但可能存在安全风险。

要访问流程环境,请使用environ全局变量或更改main函数以接收其他参数:

int main(int argc, char *argv[], char *envp[])
{
    ...
    posix_spawnp(&pid, p.we_wordv[0], NULL, NULL, p.we_wordv, envp);
}