使用popen和pclose时的问题

时间:2013-03-22 06:23:12

标签: c shell unix

我有一个使用popenpclose的程序:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
int main(void)
{
    FILE *fp = NULL;
    int ret_val = 0;

    fp = popen("ls *", "r");
    if (NULL == fp)
    {
        printf("popen error\n");
        return 1;
    }

    ret_val = pclose(fp);
    if (-1 == ret_val)
    {
        printf("pclose error\n");
        return 1;
    }
    else
    {
        printf("%d,%d,%d\n",ret_val, WIFEXITED(ret_val), WEXITSTATUS(ret_val));
    }
    return 0;
}

该计划的输出是:

./test
Broken Pipe
36096,1,141

我的问题是:

  1. 为什么会出现“破管”?
  2. 为什么退出状态码为141?我认为“ls *”已经执行了 成功,因此,退出状态应为0。

1 个答案:

答案 0 :(得分:6)

  • “断管”由ls显示,因为SIGPIPE信号是 提高。
  • 引发了SIGPIPE,因为ls正在尝试输出到已关闭的管道。
  • 管道已关闭,因为您的程序会在pclose()。{/ li>之后立即拨打popen()

阅读the documentation可以进一步理解pclose的这种行为。基本上,pclose将:

  1. 关闭popen()来电打开的信息流。
  2. 等待命令终止。
  3. 返回命令的终止状态。
  4. 由于它关闭了流然后等待命令终止,ls有时会在关闭之后尝试写入流因此导致提到的场景。

    另外,正如kingsindian所指出的那样,SIGPIPE可能永远不会被提升。这是因为在主进程调用pclose() 之前,命令实际上可以完成的工作。由于这种行为是不可预测的,我建议实现一些同步。您始终希望完全您的计划始终处于什么状态。

    作为旁注,管道是用于进程间通信的。如果您的主要流程只是打开并关闭了管道,那么最好使用fork()exec()