为什么 posix_spawn() 在 popen() 工作的地方失败?
Why does posix_spawn() fail where popen() works?
我在我的 C 程序中成功地使用了 popen()
到 运行 命令。据我了解,它在幕后使用 fork()
和 exec()
(或它们的变体)。这非常有效:
FILE *fd = popen("xterm", "r");
pclose(fd);
... 将按预期调出一个新的 xterm window。
现在我正在尝试使用 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
环境变量 。所有 graphical-output 程序都使用此环境变量连接到您的屏幕。
它没有找到变量,因为环境是空的(这是您 posix_spawnp
函数调用中的最后一个 NULL
)。好像popen
复用了当前进程的环境,所以没有这个问题。
您可能想要传递一个 manually-created 环境,只包含需要的东西,或者只传递您的进程拥有的任何环境。后者更灵活(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 程序中成功地使用了 popen()
到 运行 命令。据我了解,它在幕后使用 fork()
和 exec()
(或它们的变体)。这非常有效:
FILE *fd = popen("xterm", "r");
pclose(fd);
... 将按预期调出一个新的 xterm window。
现在我正在尝试使用 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
环境变量 。所有 graphical-output 程序都使用此环境变量连接到您的屏幕。
它没有找到变量,因为环境是空的(这是您 posix_spawnp
函数调用中的最后一个 NULL
)。好像popen
复用了当前进程的环境,所以没有这个问题。
您可能想要传递一个 manually-created 环境,只包含需要的东西,或者只传递您的进程拥有的任何环境。后者更灵活(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);
}