我已成功使用popen()从我的C程序中运行命令。据我了解,它在幕后使用了fork()exec()(或这些的变体)。这很好用:

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

...将如预期的那样打开一个新的xterm窗口。

现在,我正在尝试使用posix_spawn()达到相同的目的,我知道这可能对资源更友好,尤其是如果我们不打算与新的子进程进行通信时,尤其如此:
/* 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)按预期工作。这使我很难真正看到一种模式。

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

最佳答案

消息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);
}

关于c - 为什么posix_spawn()在popen()工作的地方失败?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48876134/

10-16 00:50