我成功使用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
)按预期工作。这使我实际看到一个模式有点困难。
你能否指出是什么导致第二种方法的行为与第一种方法不同?
答案 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);
}