使用popen和pclose时的问题

Nan*_*iao 4 c unix shell

我有一个使用popen和的程序pclose:

#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;
}
Run Code Online (Sandbox Code Playgroud)

该计划的输出是:

./test
Broken Pipe
36096,1,141
Run Code Online (Sandbox Code Playgroud)

我的问题是:

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

Ani*_*amy 6

  • 显示"断管"是ls因为SIGPIPE信号被提升.
  • 提出SIGPIPE是因为ls尝试输出到已关闭的管道.
  • 管道被关闭,因为你的程序会立即调用pclose()你之后popen().

pclose阅读文档可以进一步理解这种行为.基本上,pclose将:

  1. 关闭popen()通话打开的流.
  2. 等待命令终止.
  3. 返回命令的终止状态.

由于它关闭流然后等待命令终止,ls有时可能会在关闭尝试写入流,从而导致上述情况.

另外,正如kingsindian所指出的那样,SIGPIPE可能永远不会被提升.这是因为命令实际上可以在主进程调用之前完成其工作pclose().由于这种行为是不可预测的,我建议实现一些同步.你总是想知道究竟是什么说明你的程序在任何时候.

另外,管道是用于进程间通信的.如果您的主要流程只是打开和关闭管道,您可能最好使用fork()exec().