使用POPEN和PCLOSE时的问题

iq3niunx  于 2022-09-21  发布在  Unix
关注(0)|答案(2)|浏览(232)

我有一个使用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 errorn");
        return 1;
    }

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

该程序的输出为:

./test
Broken Pipe
36096,1,141

我的问题是:

1.为什么会有“坏了的管道”?
为什么退出状态码为141?我认为“ls*”执行成功,因此,退出状态应该为0。

smtd7mpg

smtd7mpg1#

  • 由于升起SIGPIPE信号,ls显示“断管”。
  • 引发SIGPIPE是因为ls试图输出到关闭的管道。
  • 管道关闭,因为您的程序在popen()之后立即调用pclose()

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

1.关闭popen()调用打开的流。
1.等待命令终止。
1.返回命令终止状态。

因为它关闭流,然后*等待命令终止,所以ls有时会在流关闭后尝试写入流,从而导致上述情况。

此外,正如KingsIndian指出的那样,SIGPIPE可能并不总是被提升。这是因为该命令实际上可以在主进程调用pclose()之前完成其工作。由于这种行为是不可预测的,我建议实现一些同步。您总是希望确切地知道您的程序始终处于什么状态。

顺便说一句,管道用于进程间通信。如果您的主进程只是打开和关闭管道,那么使用fork()exec()可能会更好。

hxzsmxv2

hxzsmxv22#

在关闭管道之前,它可以使用睡眠(),但我必须根据我的命令设置10秒(睡眠(10))。

相关问题