我已成功使用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告诉您xterm找不到DISPLAY环境变量.所有图形输出程序均使用此环境变量连接到屏幕.
由于环境为空,因此未找到变量(这是posix_spawnp函数调用中的最后一个NULL).看来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);
}