unix中使用PIPE_BUF的popen和write/read系统调用解释

unix中使用PIPE_BUF的popen和write/read系统调用解释,unix,linux-kernel,popen,system-calls,limits,Unix,Linux Kernel,Popen,System Calls,Limits,在linux中,limits.h中定义的常量“PIPE\u BUF”是如何工作的。当我在系统调用读取(int-fd,void*buf,size\u t count)中将其用作计数时,,系统是否调用读取,每次返回一个字节,并等待它到达文件末尾? 下面的代码接受两个命令“last”和“sort”,并进行两次popen调用。 比如~$foo最后一次排序 在下面的代码中,我不理解如果读取只返回一次所有可用字节,为什么需要while循环。 还有,对popen的写入如何理解所有的输入已经被接收,现在是pop

在linux中,limits.h中定义的常量“PIPE\u BUF”是如何工作的。当我在系统调用读取(int-fd,void*buf,size\u t count)中将其用作计数时,,系统是否调用读取,每次返回一个字节,并等待它到达文件末尾? 下面的代码接受两个命令“last”和“sort”,并进行两次popen调用。 比如~$foo最后一次排序 在下面的代码中,我不理解如果读取只返回一次所有可用字节,为什么需要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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
文件*fin,*fout;
字符缓冲区[PIPE_BUF];
int n;
如果(argc<3)
{
printf(“需要两个参数。\n”);
出口(1);
}
fin=popen(argv[1],“r”);
fout=popen(argv[2],“w”);
福鲁斯(福特);
而((n=read(fileno(fin)、buffer、PIPE_BUF))>0)
{
写入(文件号(fout),缓冲区,n);
}
pclose(fin);
pclose(fout);
返回0;
}

根据linux源代码,没有迹象表明
read()
系统调用一次读取1个字节。这将是非常愚蠢的,所以我从未想过托瓦尔兹会接受这一点

回答你的问题:


read()
函数用一些数据填充缓冲区,要读取超出缓冲区容量的数据,您需要一直调用它,直到您读取了所需的所有数据。这就是为什么要使用循环。如果有一个与您正在读取的文件一样大的缓冲区,则效率不高。

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

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

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