broken pipe java这是为什么

linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF - 推酷
linux系统编程之管道(二):管道读写规则和Pipe Capacity、PIPE_BUF
当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
示例程序如下:
&C++ Code&
/*************************************************************************
&&&&&&File&Name:&process_.c
&&&&&&Author:&Simba
&&&&&&Mail:&
&&&&&&Created&Time:&Sat&23&Feb&:02&PM&CST
&************************************************************************/
&sys/types.h&
&sys/stat.h&
&unistd.h&
&stdlib.h&
&string.h&
&signal.h&
&ERR_EXIT(m)&\
&&&&&&&&perror(m);&\
&&&&&&&&exit(EXIT_FAILURE);&\
&(pipe(pipefd)&==&-
&&&&&&&&ERR_EXIT(
&pipe&error&
&&&&pid_t&
&&&&pid&=&fork();
&(pid&==&-
&&&&&&&&ERR_EXIT(
&fork&error&
&&&&&&&&sleep(
&&&&&&&&close(pipefd[
&&&&&&&&write(pipefd[
&&&&&&&&close(pipefd[
&&&&&&&&exit(EXIT_SUCCESS);
&&&&close(pipefd[
&flags&=&fcntl(pipefd[
],&F_GETFL);
&&&&fcntl(pipefd[
],&F_SETFL,&flags&|&O_NONBLOCK);&
//enable&fd的O_NONBLOCK
&ret&=&read(pipefd[
//默认是disable&fd的O_NONBLOCK
&(ret&==&-
//&父进程不会阻塞,出错返回
&&&&&&&&ERR_EXIT(
&read&error&
&&&&printf(
&buf=%s\n&
特意在子进程中sleep了3s,让父进程先被调度运行,而且读端文件描述符标志设置为非阻塞,即立刻出错返回,如下。
simba@ubuntu:~/Documents/code/linux_programming/APUE/pipe$ ./pipe_block&
read error: Resource temporarily unavailable
二、当管道满的时候
O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
管道是一块内存缓冲区,可以写个小程序测试一下管道的容量
Pipe Capacity
&C++ Code&
/*************************************************************************
&&&&&&File&Name:&process_.c
&&&&&&Author:&Simba
&&&&&&Mail:&
&&&&&&Created&Time:&Sat&23&Feb&:02&PM&CST
&************************************************************************/
&sys/types.h&
&sys/stat.h&
&unistd.h&
&stdlib.h&
&string.h&
&signal.h&
&ERR_EXIT(m)&\
&&&&&&&&perror(m);&\
&&&&&&&&exit(EXIT_FAILURE);&\
&(pipe(pipefd)&==&-
&&&&&&&&ERR_EXIT(
&pipe&error&
&flags&=&fcntl(pipefd[
],&F_GETFL);
&&&&fcntl(pipefd[
],&F_SETFL,&flags&|&O_NONBLOCK);&
//&设置为非阻塞
&&&&&&&&ret&=&write(pipefd[
&(ret&==&-
&&&&&&&&&&&&printf(
&err=%s\n&
,&strerror(errno));
&&&&&&&&&&&&
&&&&&&&&count++;
&&&&printf(
&count=%d\n&
,&count);&
//管道容量
程序中将写端文件描述符标志设置为非阻塞,当管道被写满时不会等待其他进程读取数据,而是直接返回-1并置errno,输出如下:
simba@ubuntu:~/Documents/code/linux_programming/APUE/pipe$ ./pipe_capacity&
err=Resource temporarily unavailable
count=65536
打印了错误码,可以看到管道的容量是64kB,man 7 pipe中也有提到在2.6.11内核以前是4096,现在是65536。
三、如果所有管道读端对应的文件描述符被关闭(管道读端的引用计数等于0),则write操作会产生SIGPIPE信号,默认终止当前进程
示例代码如下:
&C++ Code&
/*************************************************************************
&&&&&&File&Name:&process_.c
&&&&&&Author:&Simba
&&&&&&Mail:&
&&&&&&Created&Time:&Sat&23&Feb&:02&PM&CST
&************************************************************************/
&sys/types.h&
&sys/stat.h&
&unistd.h&
&stdlib.h&
&string.h&
&signal.h&
&ERR_EXIT(m)&\
&&&&&&&&perror(m);&\
&&&&&&&&exit(EXIT_FAILURE);&\
&&&&printf(
&recv&sig=%d\n&
&&&&signal(SIGPIPE,&handler);
&(pipe(pipefd)&==&-
&&&&&&&&ERR_EXIT(
&pipe&error&
&&&&pid_t&
&&&&pid&=&fork();
&(pid&==&-
&&&&&&&&ERR_EXIT(
&fork&error&
&&&&&&&&close(pipefd[
&&&&&&&&exit(EXIT_SUCCESS);
&&&&close(pipefd[
&&&&sleep(
&ret&=&write(pipefd[
&(ret&==&-
&&&&&&&&printf(
&err=%s\n&
,&strerror(errno));
输出测试:
simba@ubuntu:~/Documents/code/linux_programming/APUE/pipe$ ./close_fd_read&
recv sig=13
err=Broken pipe
父进程睡眠1s确保所有读端文件描述符都已经关闭,如果没有安装SIGPIPE信号的处理函数,则默认终止当前进程,即write函数不会返回,现在write错误返回-1,并置errno=EPIPE,对应的出错信息是Broken pipe。
四、如果所有管道写端对应的文件描述符被关闭(管道写端的引用计数等于0),那么管道中剩余的数据都被读取后,再次read会返回0
示例程序如下:
&C++ Code&
/*************************************************************************
&&&&&&File&Name:&process_.c
&&&&&&Author:&Simba
&&&&&&Mail:&
&&&&&&Created&Time:&Sat&23&Feb&:02&PM&CST
&************************************************************************/
&sys/types.h&
&sys/stat.h&
&unistd.h&
&stdlib.h&
&string.h&
&signal.h&
&ERR_EXIT(m)&\
&&&&&&&&perror(m);&\
&&&&&&&&exit(EXIT_FAILURE);&\
&&&&printf(
&recv&sig=%d\n&
&&&&signal(SIGPIPE,&handler);
&(pipe(pipefd)&==&-
&&&&&&&&ERR_EXIT(
&pipe&error&
&&&&pid_t&
&&&&pid&=&fork();
&(pid&==&-
&&&&&&&&ERR_EXIT(
&fork&error&
&&&&&&&&close(pipefd[
&&&&&&&&exit(EXIT_SUCCESS);
&&&&close(pipefd[
&&&&sleep(
&ret&=&read(pipefd[
&&&&printf(
&ret&=&%d\n&
输出测试如下:
simba@ubuntu:~/Documents/code/linux_programming/APUE/pipe$ ./close_fd_write&
同样地父进程睡眠1s确保所有的写端文件描述符都已经关闭,read返回0。
五、当要写入的数据量不大于PIPE_BUF时,linux将保证
写入的原子性
;当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
On &Linux,&
is 4096 bytes。
&The precise semantics depend on whether the file descriptor is nonblocking (O_NONBLOCK),&whether there are multiple writers to the pipe, and on n, the number of bytes to be written。即由文件描述符的标志,是否有多个进程向管道写入以及写入的字节数所决定准确的语义,总共分4种情况,具体可man一下。
下面的程序演示
&C++ Code&
/*************************************************************************
&&&&&&File&Name:&process_.c
&&&&&&Author:&Simba
&&&&&&Mail:&
&&&&&&Created&Time:&Sat&23&Feb&:02&PM&CST
&************************************************************************/
&sys/types.h&
&sys/stat.h&
&unistd.h&
&stdlib.h&
&string.h&
&signal.h&
&ERR_EXIT(m)&\
&&&&&&&&perror(m);&\
&&&&&&&&exit(EXIT_FAILURE);&\
&TEST_SIZE&
<span style="color:#ff
/*&默认O_NONBLOCK&disabled&,这里验证&size&&&PIPE_BUF(4K)的情况&*/
&a[TEST_SIZE];
&b[TEST_SIZE];
&&&&memset(a,&
&&&&memset(b,&
&ret&=&pipe(pipefd);
&(ret&==&-
&&&&&&&&ERR_EXIT(
&pipe&error&
&pid&=&fork();
&&&&&&&&close(pipefd[
&&&&&&&&ret&=&write(pipefd[
//&全部写完才返回
&&&&&&&&printf(
&apid=%d&write&%d&bytes&to&pipe\n&
,&getpid(),&ret);
&&&&&&&&exit(
&&&&pid&=&fork();
&&&&&&&&close(pipefd[
&&&&&&&&ret&=&write(pipefd[
&&&&&&&&printf(
&bpid=%d&write&%d&bytes&to&pipe\n&
,&getpid(),&ret);
&&&&&&&&exit(
&&&&close(pipefd[
&&&&sleep(
&fd&=&open(
&test.txt&
,&O_WRONLY&|&O_CREAT&|&O_TRUNC,&
<span style="color:#ff
<span style="color:#ff
&&&&&&&&ret&=&read(pipefd[
//当管道被写入数据,就已经可以开始读了,每次读取4k
//&管道写端全部关闭,即读到了结尾
&&&&&&&&&&&&
&&&&&&&&printf(
&n=%02d&pid=%d&read&%d&bytes&from&pipe&buf[4095]=%c\n&
&&&&&&&&&&&&&&&n++,&getpid(),&ret,&buf[
<span style="color:#ff
&&&&&&&&write(fd,&buf,&ret);
输出测试如下:
simba@ubuntu:~/Documents/code/linux_programming/APUE/pipe$ ./pipe_buf&
n=01 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=02 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=03 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=04 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=05 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=06 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=07 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=08 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=09 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=10 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=11 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=12 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=13 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=14 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=15 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=16 pid=7137 read 4096 bytes from pipe buf[4095]=B
n=17 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=18 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=19 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=20 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=21 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=22 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=23 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=24 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=25 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=26 pid=7137 read 4096 bytes from pipe buf[4095]=A
apid=7138 write 69632 bytes to pipe
n=27 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=28 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=29 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=30 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=31 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=32 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=33 pid=7137 read 4096 bytes from pipe buf[4095]=A
n=34 pid=7137 read 4096 bytes from pipe buf[4095]=B
bpid=7139 write 69632 bytes to pipe
分析一下:现在的情况是有两个子进程在对管道进行阻塞写入各68k,即每个子进程完全写入68k才返回,而父进程对管道进行阻塞读取,每次读取4k,打印每4k中的最后一个字符。需要注意的是是边写边读,因为前面说过管道的容量只有64k,当管道被写满时子进程就阻塞等待父进程读取后再写入。由上面输出可以看出B进程先写入64k的B,然后A进程写入68k的A之后B进程接着写完最后4K的B,然后write返回。由A进程write完毕输出的提示可知此时A进程已经写完成了,但父进程还没读取A完毕,当两个子进程全部写完退出时关闭写端文件描述符,则父进程read就会返回0,退出while循环。可以得出结论:当多个进程对管道进行写入,且一次性写入数据量大于PIPE_BUF时,则不能保证写入的原子性,即可能数据是
着的。man 手册的解释如下:
& & & &O_NONBLOCK disabled, n & PIPE_BUF
&The write is nonatomic: the data given to write(2) may be interleaved with write(2) &the&write(2) blocks until n bytes have been written.
注意我们这里设定了size=68k,则写端不能设置成非阻塞,因为PIPE_BUF只有64k,不能一次性写入68k,故只能返回-1,且一个字符也不写入,读端也不能设置为非阻塞,因为有可能此时管道还没被写入数据或者不够一次性read的数据量的时候去读,则直接返回-1,不会阻塞等待足够数据量后进行读取。总之测试4种不同情形下的情况也应设置不同的条件。
管道的前4种读写规则具有普遍意义,Tcp socket 也具有管道的这些特性。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致Linux pipe_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Linux pipe
上传于||暂无简介
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
你可能喜欢PIPE 私人股权投资已上市公司股份
中英名称  英文全称:Private Investment in Public Equity
  中文全称:
已上市公司股份PIPE的特点  这种融资方式非常受欢迎,相对于二次发行等传统的融资手段,PIPE的融资成本和融资效率要相对高一些。在PIPE发行中监管机构的审查更少一些,而且也不需要昂贵的路演,这使得获得资本的成本和时间都大大降低。PIPE比较适合一些快速成长为中型企业的上市公司,他们没有时间和精力应付传统股权融资的复杂程序。
pipe 函数 (C语言)
  pipe我们用中文叫做管道。
  以下讲解均是基于Linux为环境:函数简介  所需头文件 #include
  函数原型 int pipe(int fd[2])
  函数传入值 fd[2]:管道的两个
,之后就是可以直接操作这两个文件描述符
  返回值 成功 0 失败 -1什么是管道  管道是Linux 支持的最初Unix IPC形式之一,具有以下特点:
  管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 只能用于
进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道
的末尾,并且每次都是从缓冲区的头部读出数据。管道的创建  #include
  int pipe(int fd[2])
  该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现
进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。管道的读写规则  管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的
函数都可以用于管道,如close、read、write等等。从管道中读取数据  如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0; 当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。注:(PIPE_BUF在include/linux/
中定义,不同的
可能会有所不同。Posix.1要求PIPE_BUF至少为512字节,red hat 7.2中为4096)。
  关于管道的读规则验证:
  /**************
  * readtest.c *
  **************/
  #include
  #include
  #include
  main()
  int pipe_fd[2];
  char r_buf[100];
  char w_buf[4];
  char* p_
  int r_
  memset(r_buf,0,sizeof(r_buf));
  memset(w_buf,0,sizeof(r_buf));
  p_wbuf=w_
  if(pipe(pipe_fd)&0)
  printf(&pipe create error &);
  return -1;
  if((pid=fork())==0)
  printf(& &);
  close(pipe_fd[1]);
  sleep⑶;//确保子进程关闭写端
  r_num=read(pipe_fd[0],r_buf,100);
  printf(&read num is %d the data read from the pipe is %d &,r_num,atoi(r_buf));
  close(pipe_fd[0]);
  exit();
  else if(pid&0)
  close(pipe_fd[0]);//read
  strcpy(w_buf,&111&);
  if(write(pipe_fd[1],w_buf,4)!=-1)
  printf(&parent write over &);
  close(pipe_fd[1]);//write
  printf(&parent close fd[1] over &);
  sleep⑽;
  /**************************************************
  * 程序输出结果:
  * parent write over
  * parent close fd[1] over
  * read num is 4 the data read from the pipe is 111
  * 附加结论:
  * 管道写端关闭后,写入的数据将一直存在,直到读出为止.
  ****************************************************/
  向管道中写入数据:
  向管道中写入数据时,linux将不保证写入的原子性,管道
一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
  注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,
可以处理该信号,也可以忽略(默认动作则是应用程序终止)。
  对管道的写规则的验证1:写端对读端存在的依赖性
  #include
  #include
  main()
  int pipe_fd[2];
  char r_buf[4];
  char* w_
  memset(r_buf,0,sizeof(r_buf));
  if(pipe(pipe_fd)&0)
  printf(&pipe create error &);
  return -1;
  if((pid=fork())==0)
  close(pipe_fd[0]);
  close(pipe_fd[1]);
  sleep⑽;
  exit();
  else if(pid&0)
  sleep⑴; //等待子进程完成关闭读端的操作
  close(pipe_fd[0]);//write
  w_buf=&111&;
  if((writenum=write(pipe_fd[1],w_buf,4))==-1)
  printf(&write to pipe error &);
  printf(&the bytes write to pipe is %d &,writenum);
  close(pipe_fd[1]);
  则输出结果为:Broken pipe,原因就是该管道以及它的所有fork()产物的读端都已经被关闭。如果在
中保留读端,即在写完pipe后,再关闭父进程的读端,也会正常写入pipe,读者可自己验证一下该结论。因此,在向管道写入数据时,至少应该存在某一个进程,其中管道读端没有被关闭,否则就会出现上述错误(管道断裂,进程收到了SIGPIPE信号,默认动作是进程终止)
  对管道的写规则的验证2:linux不保证写管道的原子性验证
  #include
  #include
  #include
  main(int argc,char**argv)
  int pipe_fd[2];
  char r_buf[4096];
  char w_buf[4096*2];
  memset(r_buf,0,sizeof(r_buf));
  if(pipe(pipe_fd)&0)
  printf(&pipe create error &);
  return -1;
  if((pid=fork())==0)
  close(pipe_fd[1]);
  while⑴
  sleep⑴;
  rnum=read(pipe_fd[0],r_buf,1000);
  printf(&child: readnum is %d &,rnum);
  close(pipe_fd[0]);
  exit();
  else if(pid&0)
  close(pipe_fd[0]);//write
  memset(r_buf,0,sizeof(r_buf));
  if((writenum=write(pipe_fd[1],w_buf,1024))==-1)
  printf(&write to pipe error &);
  printf(&the bytes write to pipe is %d &,writenum);
  writenum=write(pipe_fd[1],w_buf,4096);
  close(pipe_fd[1]);
  输出结果:
  the bytes write to pipe is 1000
  the bytes write to pipe 4096
  child: readnum is 1000 //注意,此行输出说明了写入的非原子性
  child: readnum is pipe 1000
  child: readnum is pipe 1000
  child: readnum is pipe 1000
  child: readnum is pipe 1000
  child: readnum is pipe 120 //注意,此行输出说明了写入的非原子性
  child: readnum is pipe 0
  child: readnum is pipe 0
  ......
  结论:
  写入数目小于4096时写入是非原子的!
  如果把父进程中的两次写入字节数都改为5000,则很容易得出下面结论:
  写入管道的数据量大于4096字节时,缓冲区的空闲空间将被写入数据(补齐),直到写完所有数据为止,如果没有进程读数据,则一直阻塞。管道应用实例  
实例一:用于
  管道可用于输入输出重定向,它将一个命令的输出直接定向到另一个命令的输入。比如,当在某个shell程序(Bourne shell或C shell等)键入who│wc -l后,相应shell程序将创建who以及wc两个进程和这两个进程间的管道。考虑下面的命令行:
  $kill -l 运行结果见 附一。
  $kill -l | grep SIGRTMIN 运行结果如下:
  30) SIGPWR 31) SIGSYS 32) SIGRTMIN 33) SIGRTMIN+1
  34) SIGRTMIN+2 35) SIGRTMIN+3 36) SIGRTMIN+4 37) SIGRTMIN+5
  38) SIGRTMIN+6 39) SIGRTMIN+7 40) SIGRTMIN+8 41) SIGRTMIN+9
  42) SIGRTMIN+10 43) SIGRTMIN+11 44) SIGRTMIN+12 45) SIGRTMIN+13
  46) SIGRTMIN+14 47) SIGRTMIN+15 48) SIGRTMAX-15 49) SIGRTMAX-14
实例二:用于具有亲缘关系的
  下面例子给出了管道的具体应用,
通过管道发送一些命令给子进程,子进程解析命令,并根据命令作相应处理。
  #include
  #include
  main()
  int pipe_fd[2];
  char r_buf[4];
  char** w_buf[256];
  int childexit=0;
  memset(r_buf,0,sizeof(r_buf));
  if(pipe(pipe_fd)&0)
  printf(&pipe create error &);
  return -1;
  if((pid=fork())==0)
  //子进程:解析从管道中获取的命令,并作相应的处理
  printf(& &);
  close(pipe_fd[1]);
  sleep⑵;
  while(!childexit)
  read(pipe_fd[0],r_buf,4);
  cmd=atoi(r_buf);
  if(cmd==0)
  printf(&child: receive command from parent over now child process exit &);
  childexit=1;
  else if(handle_cmd(cmd)!=0)
  sleep⑴;
  close(pipe_fd[0]);
  exit();
  else if(pid&0)
  //parent: send commands to child
  close(pipe_fd[0]);
  w_buf[0]=&003&;
  w_buf[1]=&005&;
  w_buf[2]=&777&;
  w_buf[3]=&000&;
  for(i=0;i&4;i++)
  write(pipe_fd[1],w_buf[i],4);
  close(pipe_fd[1]);
  //下面是子进程的命令处理函数(特定于应用):
  int handle_cmd(int cmd)
  if((cmd&0)||(cmd&256))
  //suppose child only support 256 commands
  printf(&child: invalid command &);
  return -1;
  printf(&child: the cmd from parent is %d &,cmd);
  return 0;
PIPE什么意思
  ⒈管,导管,输送管[C]
  They are laying pipes under the road.
  他们正在铺设路下面的管子。
  ⒉烟斗[C]
  His father is a pipe-smoker.
  他父亲是抽烟斗的。
  ⒊管乐器;笛[C]
  He is playing a tune on his pipe.
  他在用笛子吹奏一支曲子。
  ⒋笛声;鸟鸣声;尖锐的声音[U]
  ⒌管状器官;呼吸器官[C]
  ⒍(液量单位)最大桶[C],大酒桶
  ⒎【口】容易干的事
  ⒈用管道输送[H][(+into/to)]
  Water was piped into the village two years ago.
  两年前水由管子通到了村里。
  ⒉(用尖声)说话,唱歌;尖声鸣叫
  The woman piped her disapproval.
  那妇人尖声嚷叫不赞成。
  ⒊用管乐器吹奏
  I'll pipe your favorite song.
  我来吹奏那支你喜欢听的歌。
  ⒋为...铺设管道
  Our neighborhood will be piped for gas.
  我们这个地区将要铺设煤气管。
  ⒌为(衣服)滚边;为(糕饼)浇饰花边
  ⒈吹奏管乐
  ⒉尖声叫嚷,尖声鸣叫
  Wind was piping in the woods.
  风在林中呼啸。
  同义词
  同义词 参见
  artery
  aqueduct
  funnel
  outlet
  名复: pipes
  动变: piping管道的局限性  管道的主要局限性正体现在它的特点上:
  只支持单向
; 只能用于具有亲缘关系的进程之间; 没有名字; 管道的
是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);
  管道所传送的是无格式
,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;Linux管道的实现机制  在Linux中,管道是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为:
  限制管道的大小。实际上,管道是一个固定大小的
。在Linux中,该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。
  读取进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。
注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。1. 管道的结构  在 Linux 中,管道的实现并没有使用专门的
,而是借助了文件系统的file结构和VFS的
inode。通过将两个 file 结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。如图 7.1所示。
  图7.1 管道结构示意图
  图7.1中有两个file 数据结构,但它们
操作例程地址是不同的,其中一个是向管道中写入数据的例程地址,而另一个是从管道中读出数据的例程地址。这样,
仍然是通常的文件操作,而
却利用这种
抽象机制实现了管道这一特殊操作。2.管道的读写  管道实现的
在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即管道读函数pipe_read()和管道写函数pipe_wrtie()。管道写函数通过将字节复制到 VFS
而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。当然,
必须利用一定的机制同步对管道的访问,为此,内核使用了锁、
  当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的
,可找到该文件的 file 结构。file 结构中指定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作:
  内存中有足够的空间可容纳所有要写入的数据;
  内存没有被读程序锁定。
  如果同时满足上述条件,写入函数首先锁定内存,然后从写进程的
中复制数据到内存。否则,写入进程就休眠在 VFS 索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。写入进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写入数据,或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接收到信号。当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤醒。
  管道的读取过程和写入过程类似。但是,进程可以在没有数据或内存被锁定时立即返回
,而不是阻塞该进程,这依赖于文件或管道的打开模式。反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。当所有的进程完成了
之后,管道的索引节点被丢弃,而共享数据页也被释放。
  因为管道的实现涉及很多文件的操作,因此,当读者学完有关文件系统的内容后来读pipe.c中的代码,你会觉得并不难理解。
万方数据期刊论文
材料科学技术学报(英文版)
万方数据期刊论文
中国有色金属学会会刊(英文版)
万方数据期刊论文
为本词条添加和相关影像
互动百科的词条(含所附图片)系由网友上传,如果涉嫌侵权,请与客服联系,我们将按照法律之相关规定及时进行处理。未经许可,禁止商业网站等复制、抓取本站内容;合理使用者,请注明来源于。
登录后使用互动百科的服务,将会得到个性化的提示和帮助,还有机会和专业认证智愿者沟通。
您也可以使用以下网站账号登录:
此词条还可添加&
编辑次数:6次
参与编辑人数:6位
最近更新时间: 14:54:54
贡献光荣榜
扫描二维码用手机浏览词条
保存二维码可印刷到宣传品
扫描二维码用手机浏览词条
保存二维码可印刷到宣传品}

我要回帖

更多关于 ssh broken pipe 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信