管道随进程 匿名管道是存在于内存中的特殊文件 特点: 1.单向 2.有血缘关系的进程间通信 3.实现进程间同步 4.提供“流式服务” 匿名管道的实现: test.c #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> int main() { int _pipe[2]; int ret=pipe(_pipe); if(ret==-1) { printf("create pipe error!error code is:%d\n",errno); return 1; } pid_t id=fork(); if(id<0) //create fail { printf("fork error!\n"); return 2; } else if(id==0) //child { close(_pipe[0]); int i=0; char* _mesg_c=NULL; while(i<100) { _mesg_c="i am a child!"; write(_pipe[1],_mesg_c,strlen(_mesg_c)+1); sleep(1); i++; } } else //father { close(_pipe[1]); char _mesg[100]; int j=0; while(j<100) { memset(_mesg,'\0',sizeof(_mesg)); read(_pipe[0],_mesg,sizeof(_mesg)); printf("%s\n",_mesg); j++; } } return 0; } 使用管道要注意以下四种情况(假设都是阻塞 I/O操作,没有设置O_NONBLOCK标志) 1、所有指向写端的文件描述符都关闭了,而仍有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样 test1.c #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<sys/wait.h> int main() { int _pipe[2]; int ret=pipe(_pipe); if(ret==-1) { printf("create pipe error!error code is:%d\n",errno); return 1; } pid_t id=fork(); if(id<0) //create fail { printf("fork error!\n"); return 2; } else if(id==0) //child { close(_pipe[0]); int i=0; char* _mesg_c=NULL; while(i<10) { _mesg_c="i am a child!"; write(_pipe[1],_mesg_c,strlen(_mesg_c)+1); sleep(1); i++; } close(_pipe[1]); } else //father { close(_pipe[1]); char _mesg[100]; int j=0; while(j<100) { memset(_mesg,'\0',sizeof(_mesg)); int ret=read(_pipe[0],_mesg,sizeof(_mesg)); printf("%s:code is:%d\n",_mesg,ret); j++; } if(waitpid(id,NULL,0)<0) { return 3; } } return 0; } 结果: i am a child!:code is:14 (10行) :code is:0 (90行) Program exited normally. 2、如果有指向管道写端的文件描述符没关闭,而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。 test2.c: #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<sys/wait.h> int main() { int _pipe[2]; int ret=pipe(_pipe); if(ret==-1) { printf("create pipe error!error code is:%d\n",errno); return 1; } pid_t id=fork(); if(id<0) //create fail { printf("fork error!\n"); return 2; } else if(id==0) //child { close(_pipe[0]); int i=0; char* _mesg_c=NULL; while(i<20) { if(i<10) { _mesg_c="i am a child!"; write(_pipe[1],_mesg_c,strlen(_mesg_c)+1); } sleep(1); i++; } } else //father { close(_pipe[1]); char _mesg[100]; int j=0; while(j<20) { memset(_mesg,'\0',sizeof(_mesg)); int ret=read(_pipe[0],_mesg,sizeof(_mesg)); printf("%s:code is:%d\n",_mesg,ret); j++; } if(waitpid(id,NULL,0)<0) { return 3; } } return 0; } 结果: i am a child!:code is:14 (10行) :code is:0 (10行) Program exited normally. 3、如果所有指向管道读端的文件描述符都关闭了,这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。 test3.c: #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<sys/wait.h> int main() { int _pipe[2]; int ret=pipe(_pipe); if(ret==-1) { printf("create pipe error!error code is:%d\n",errno); return 1; } pid_t id=fork(); if(id<0) //create fail { printf("fork error!\n"); return 2; } else if(id==0) //child { close(_pipe[0]); int i=0; char* _mesg_c=NULL; while(i<20) { if(i<10) { _mesg_c="i am a child!"; write(_pipe[1],_mesg_c,strlen(_mesg_c)+1); } sleep(1); i++; } } else //father { close(_pipe[1]); char _mesg[100]; int j=0; while(j<3) { memset(_mesg,'\0',sizeof(_mesg)); int ret=read(_pipe[0],_mesg,sizeof(_mesg)); printf("%s:code is:%d\n",_mesg,ret); j++; } close(_pipe[0]); sleep(10); if(waitpid(id,NULL,0)<0) { return 3; } } return 0; } 结果: i am a child!:code is:14 i am a child!:code is:14 i am a child!:code is:14 Program exited normally. 4、如果有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么管道被写满时,再次write会阻塞,直到管道中有空位置了才写入数据并返回。 test4.c #include<stdio.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<sys/wait.h> int main() { int _pipe[2]; int ret=pipe(_pipe); if(ret==-1) { printf("create pipe error!error code is:%d\n",errno); return 1; } pid_t id=fork(); if(id<0) //create fail { printf("fork error!\n"); return 2; } else if(id==0) //child { close(_pipe[0]); int i=0; char* _mesg_c=NULL; while(i<20) { _mesg_c="i am a child!"; write(_pipe[1],_mesg_c,strlen(_mesg_c)+1); sleep(1); i++; } } else //father { close(_pipe[1]); char _mesg[100]; int j=0; while(j<20) { if(j<3) { memset(_mesg,'\0',sizeof(_mesg)); int ret=read(_pipe[0],_mesg,sizeof(_mesg)); printf("%s:code is:%d\n",_mesg,ret); } sleep(1); j++; } if(waitpid(id,NULL,0)<0) { return 3; } } return 0; } 结果: i am a child!:code is:14 i am a child!:code is:14 i am a child!:code is:14 Program exited normally.
本文出自 “追寻内心的声音” 博客,请务必保留此出处http://ljy789.blog.51cto.com/10697684/1763811