我正在 Linux 上用 C 编写一个程序,其中包含一个模块 允许在远程机器上执行 shell 命令。这 实际执行命令的最简单方法当然是 只需使用 system() 函数,或使用 popen 然后抓取 输出。但是,由于与当前不相关的其他设计要求,我选择使用更底层的方法 问题。
基本上,我设置了管道和分支,然后调用 execl。这一切 工作完美,除了一个恼人的异常。它不起作用 如果要执行的 shell 命令是守护进程,则正确。在那里面 案例,它只是挂起。我不知道为什么。我的理解是 当守护进程启动时,它通常会 fork ,然后父进程退出。由于我的应用程序有一个通往父级的开放管道,因此调用 当 parent 退出时, to read() 应该失败。但反而 应用程序挂起。
下面是一些重现问题的基本代码:
int main(int argc, char** argv)
{
// Create a pipe and fork
//
int fd[2];
int p = pipe(fd);
pid_t pid = fork();<p></p>
<pre><code> if (pid > 0)
{
// Read from the pipe and output the result
//
close(fd[1]);
char buf[1024] = { 0 };
read(fd[0], buf, sizeof(buf));
printf("%s\n", buf);
// Wait for child to terminate
int status;
wait(&status);
}
else if (pid == 0)
{
// Redirect stdout and stderr to the pipe and execute the shell
// command
//
dup2(fd[1], STDOUT_FILENO);
dup2(fd[1], STDERR_FILENO);
close(fd[0]);
execl("/bin/sh", "sh", "-c", argv[1], 0);
}
</code></pre>
<p>}
</p>
如果您将代码与普通的 shell 命令一起使用,则该代码可以正常工作。但是如果 你尝试运行一个守护进程,它只是挂起而不是返回到 应有的提示。
最佳答案
最可能的解决方案是在 execl() 之上添加 close(fd[1]);
。
您的程序挂起的原因是 read() 函数等待守护进程向其 stdout/stderr 写入内容。如果守护进程(包括程序的子进程,以及子进程的派生子进程保留其 stdout/stderr)不写任何东西,并且至少有一个进程保持管道的可写端打开,读( )永远不会回来。但是那个进程是什么,它使管道的可写端保持打开状态?它很可能是您程序的子进程的子进程,即长期运行的守护进程。虽然它可能在守护进程时调用了 close(0);
和 close(1);
,但很可能它没有调用 close(fd[1] );
,所以管道的可写端仍然是打开的。
关于c - 使用 execl 执行守护进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/800712/