轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaominglinux管道-应用编程-专题讲座writtenby王保明linux管道基本概念1管道基本概念及操作管道基本概念管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”比如:eg:ls|wc-lps–uwbm01|grep“aa”管道的本质====》固定大小的内核缓冲区管道限制管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。匿名管道pipe包含头文件unistd.h功能:创建一无名管道原型intpipe(intfd[2]);参数fd:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端返回值:成功返回0,失败返回错误代码管道创建后示意图轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming2管道和文件描述符在一起管道命令的编程实现:ls|wc–w文件描述符的深入理解#includeunistd.h#includesys/stat.h#includesys/wait.h#includesys/types.h#includefcntl.h#includestdlib.h#includestdio.h#includeerrno.h#includestring.h#includesignal.h#defineERR_EXIT(m)\do\{\perror(m);\exit(EXIT_FAILURE);\}while(0)intmain21(void){intpipefd[2];pid_tpid;if(pipe(pipefd)==-1){printf(pipe()err..\n);return-1;}pid=fork();if(pid==-1){printf(forkerr..\n);return-1;管道基本编程示例轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaoming}if(pid==0){close(pipefd[0]);//复制文件描述符pipefd[1],给标准输出,言外之意:execlp的ls命令输出到管道中dup2(pipefd[1],STDOUT_FILENO);close(pipefd[1]);execlp(ls,ls,NULL);//如果替换新的进程印象失败,则会执行下面一句话sprintf(stderr,executethecmdlserr..\n);exit(0);}elseif(pid0){intlen=0;charbuf[100]={0};close(pipefd[1]);//复制文件描述符pipefd[0],给标准输入,言外之意:execlp的wc命令从管道中读dup2(pipefd[0],STDIN_FILENO);close(pipefd[0]);//len=read(pipefd[0],buf,100);execlp(wc,wc,-w,NULL);printf(len:%d,buf:%s\n,len,buf);//close(pipefd[0]);}wait(NULL);printf(parent..quit\n);return0;}intmain(intargc,char*argv[]){close(0);//关闭表示输入open(makefile,O_RDONLY);//makefile文件变成标准输入close(1);//关闭标准输出open(makefile2,O_WRONLY|O_CREAT|O_TRUNC,0644);//maifle2变成标准输出轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingexeclp(cat,cat,NULL);//替换进程印象后,执行cat命令//cat命名从标准输入中按行读,紧接着写到标准输出return0;}2管道的读写规则管道读写规则研究(重点)当没有数据可读时O_NONBLOCKdisable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。O_NONBLOCKenable:read调用返回-1,errno值为EAGAIN。当管道满的时候O_NONBLOCKdisable:write调用阻塞,直到有进程读走数据O_NONBLOCKenable:调用返回-1,errno值为EAGAIN当管道不停的被写,写满的时候O_NONBLOCKdisable:write调用阻塞O_NONBLOCKenable:调用返回-1,errno值为EAGAIN如果所有管道写端对应的文件描述符被关闭,则read返回0如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。测试管道读(阻塞、非阻塞)测试管道两端读、写均关闭测试管道容量编程实践manfctlFiledescriptorflagsThefollowingcommandsmanipulatetheflagsassociatedwithafiledescriptor.Currently,onlyonesuchflagisdefined:FD_CLOEXEC,theclose-on-execflag.IftheFD_CLOEXECbitis0,thefiledescriptorwillremainopenacrossanexecve(2),otherwiseitwillbeclosed.F_GETFDReadthefiledescriptorflags.F_SETFD轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingSetthefiledescriptorflagstothevaluespecifiedbyarg.FilestatusflagsEachopenfiledescriptionhascertainassociatedstatusflags,initializedbyopen(2)andpossiblymodifiedbyfcntl(2).Duplicatedfiledescriptors(madewithdup(),fcntl(F_DUPFD),fork(),etc.)refertothesameopenfiledescription,andthussharethesamefilestatusflags.Thefilestatusflagsandtheirsemanticsaredescribedinopen(2).F_GETFLReadthefilestatusflags.F_SETFLSetthefilestatusflagstothevaluespecifiedbyarg.Fileaccessmode(O_RDONLY,O_WRONLY,O_RDWR)andfilecreationflags(i.e.,O_CREAT,O_EXCL,O_NOCTTY,O_TRUNC)inargareignored.OnLinuxthiscommandcanonlychangetheO_APPEND,O_ASYNC,O_DIRECT,O_NOATIME,andO_NONBLOCKflags.容量查询man-6pipePipeCapacityApipehasalimitedcapacity.Ifthepipeisfull,thenawrite(2)willblockorfail,dependingonwhethertheO_NONBLOCKflagisset(seebelow).Differentimplementationshavedifferentlimitsforthepipecapacity.Applicationsshouldnotrelyonaparticularcapacity:anapplicationshouldbedesignedsothatareadingprocessconsumesdataassoonasitisavailable,sothatawritingprocessdoesnotremainblocked.InLinuxversionsbefore2.6.11,thecapacityofapipewasthesameasthesystempagesize(e.g.,4096bytesonx86).SinceLinux2.6.11,thepipecapacityis65536bytes.读写规则man-6pipeIfallfiledescriptorsreferringtothewriteendofapipehavebeenclosed,thenanattempttoread(2)fromthepipewillseeend-of-file(read(2)willreturn0).Ifallfiledescriptorsreferring轻松入门实战应用从项目开发角度为你搭建完整的知识体系wangbaomingtothereadendofapipehavebeenclosed,thenawrite(2)willcauseaSIGPIPEsignaltobegeneratedforthecallingprocess.Ifthecallingprocessisignoringthissignal,thenwrite(2)failswiththeerrorEPIPE.Anapplicationthatusespipe(2)andfork(2)shouldusesuitableclose(2)callstocloseunnecessaryduplicatefiledescriptors;thisensuresthatend-of-fileandSIGPIPE/EPIPEaredeliveredwhenappropriate.Itisnotpossibletoapplylseek(2)toapipe.#includelinux/limits.hPIPE_BUF[root@localhost~]#find/-namelimits.h/usr/include/linux/limits.h[root@localhost~]#find/-namelimits.h|cat[root@localhost~]#find/-namelimits.h|sed-n1p[root@localhost~]#cat/usr/include/linux/limits.h#ifndef_LINUX_LIMITS_H#define_LINUX_LIMITS_H#defineNR_OPEN1024#defineNGROUPS_MAX65536/*supplementalgroupIDsareavailable*/#defineARG_MAX131072/*#bytesofargs+environforexec()*/#defineCHILD_MAX999/*nolimit:-)*/#defineOPEN_MAX256/*#openfilesaprocessmayhave*/#defineLINK_MAX127/*#linksafilemayhave*/#defineMAX_CANON255/*sizeofthecanonicalinputqueue*/#defineMAX_INPUT255/*sizeofthetype-aheadbuffer*/#defineNAME_MAX255/*#charsinafilename*/#definePATH_MAX4096/*#ch