我有一个程序,通过popen()系统调用使用'/ usr / bin / lpstat'计算'Printer Queues Total'值。
{
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()系统调用中挂起的原因,它将帮助我修改程序以满足我的要求。
感谢您花时间阅读这篇文章和您的努力。
答案 0 :(得分:0)
人们期望并不总是有现实基础: - )
您运行的命令在完成之前实际上不会生成任何输出。这就是为什么它似乎挂在popen
而不是fscanf
。
有两个可能的原因立即让人想起。
首先是它以这种方式实现,popen
在传送第一行之前完全捕获输出。根据我对UNIX的了解,这似乎不太可能,但我无法确定。
远更多可能是管道的影响。我注意到的一件事是,一些过滤器(如grep
)批量生产线以提高效率。所以,虽然popen
本身可能会立即喷出它的线(好吧,直到它到达延迟位),grep
保持线直到它得到一个足够大的块的事实可能会造成延误。
事实上,几乎可以肯定的是,直通wc,在从lpstat
收到所有行之前,它无法生成任何输出(你无法弄清楚有多少行直到所有线路都已收到)。因此,即使popen
只是等待第一个字符可用,这似乎就是挂起的地方。
通过简单地删除pipe-through-grep-and-wc位并查看发生的情况来测试它是一件简单的事情。
我想提出的另一点。你的printf
语句后面没有换行符,即使它们有,也有些情况下输出可能仍然是完全缓冲的(因此在程序退出或填充缓冲区之前你可能看不到任何内容) )。
我首先将它们更改为以下形式:
printf ("message here\n"); fflush (stdout); fsync (fileno (stdout));
确保在继续之前完全刷新 。我讨厌这是对缓冲问题的简单误解: - )
答案 1 :(得分:0)
当lpstat尝试从远程打印机检索信息时,听起来好像popen可能正在挂起。这个特殊问题有a fair amount of discussion。看一下那个帖子,特别是那个链接的那个。