在unix中使用PIPE_BUF进行popen和写/读系统调用解释

时间:2013-08-02 01:30:04

标签: unix linux-kernel popen system-calls limits

limits.h 中定义的常量“PIPE_BUF”在linux中是如何工作的。当我在系统调用中使用“count” “read(int fd,void * buf,size_t count);”时,系统会调用 “read”,一次返回一个字节并等待它到达文件末尾? 下面的代码采用两个命令“last”和“sort”并进行两次popen调用。 喜欢〜$ foo最后一种 在下面的代码中,我不明白为什么如果read只返回所有可用字节,那么while循环是必要的。 而且,对popen的写入如何理解所有输入都已被接收,现在是popen执行程序的时候了。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>

int main (int argc, char* argv[])
{
  FILE *fin, *fout;
  char buffer[PIPE_BUF];
  int n;

  if (argc < 3)
    {
      printf("Need two parameters.\n");
      exit(1);
    }

  fin=popen(argv[1], "r");
  fout=popen(argv[2],"w");

  fflush(fout);

  while ((n=read(fileno(fin), buffer, PIPE_BUF)) > 0)
    {
      write(fileno(fout), buffer, n);
    }

  pclose(fin);
  pclose(fout);

  return 0;
}

2 个答案:

答案 0 :(得分:1)

popen立即执行程序,并创建一个连接到该程序输入/输出的管道。 所有程序同时运行。

read调用等待一些数据(至少一个字节)可用,然后返回所有可用的数据并放入缓冲区。 如果管道另一端的程序写了多个字节,你也可以读取多个字节。

您需要一个循环,因为其他程序可能会在以后写入更多数据。 只有当管道的写入端关闭时,read才会返回零。

答案 1 :(得分:0)

根据linux-source,没有迹象表明read()系统调用一次只能读取1个字节。这将是非常愚蠢的,所以我永远不会认为Torvalds会接受这一点。

回答你的问题:

read()函数用一些数据填充缓冲区。要读取比缓冲区更多的数据,您需要继续调用它直到您已经阅读了所需的所有内容。这就是你要使用循环的原因。拥有与您正在阅读的文件一样大的缓冲区效率不高。