0

我有一个程序通过 popen() 系统调用使用“/usr/bin/lpstat”计算“打印机队列总计”值。

{
    int                     n=0;
    FILE                    *fp=NULL;

    printf("Before popen()");
    fp = popen("/usr/bin/lpstat -o | grep '^[^ ]*-[0-9]*[ \t]' | wc -l", "r");
    printf("After popen()");

    if (fp == NULL)
    {
            printf("Failed to start lpstat - %s", strerror(errno));
            return -1;
    }

    printf("Before fscanf");
    fscanf(fp, "%d", &n);
    printf("After fscanf");

    printf("Before pclose()");
    pclose(fp);
    printf("After pclose()");

    printf("Value=%d",n);
    printf("=== END ===");
    return 0;
}

注意:在命令行中,“/usr/bin/lpstat”命令暂停了一段时间,因为网络中有许多打印机可用。

这里的问题是,执行挂在 popen() 系统调用上,而我希望它挂在 fscanf() 上,它从文件流 fp 读取输出。

如果有人能告诉我 popen() 系统调用挂起的原因,它将帮助我修改程序以满足我的要求。

感谢您花时间阅读这篇文章和您的努力。

4

2 回答 2

0

听起来 popen 可能正在挂起,而 lpstat 尝试从远程打印机检索信息。关于这个特定问题有相当多的讨论。看看那个线程,尤其是那些与之相关的线程。

于 2011-04-26T11:59:15.297 回答
0

人们的期望并不总是有现实依据:-)

您正在运行的命令在完成之前实际上不会生成任何输出。这就是为什么它似乎挂在popen而不是fscanf.

有两个可能的原因立即浮现在脑海中。

首先是它以这种方式实现,popen在交付第一行之前完整捕获输出。根据我对 UNIX 的了解,这似乎不太可能,但我不能确定。

更有可能是管道的影响我注意到的一件事是一些过滤器(如grep)为了提高效率而分批生产。因此,虽然popen它本身可能会立即喷出它的线路(嗯,直到它到达延迟位),但grep坚持线路直到它获得足够大的块的事实可能会导致延迟。

事实上,几乎可以肯定是 pipe-through-wc,它在收到所有行之前无法生成任何输出(在收到所有行之前,lpstat您无法计算出有多少行)。因此,即使popen只是等待第一个字符可用,这似乎也是问题所在。

通过简单地删除 pipe-through-grep-and-wc 位并查看会发生什么来测试它是一件简单的事情。


我想提出另一点。您的printf语句后面没有换行符,即使有,在某些情况下输出可能仍被完全缓冲(因此在该程序退出或缓冲区填满之前您可能看不到任何内容)。

我首先将它们更改为以下形式:

printf ("message here\n"); fflush (stdout); fsync (fileno (stdout));

以确保在继续之前将它们完全冲洗干净。我讨厌这是对缓冲问题的简单误解:-)

于 2011-04-26T11:56:48.883 回答