匿名管道的四种特殊情况
2016-06-17 18:37
337 查看
管道随进程 匿名管道是存在于内存中的特殊文件 特点: 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
相关文章推荐
- 环形队列的实现原理
- Linux中进程正常退出return和exit()的区别
- 浅谈文件描述符与文件指针
- 浅谈inode
- Swift中的闭包(Closure) 浅析
- 小工具: 听例句背单词
- printf()的返回值
- 实现动态顺序表
- 有一个字符数组的内容为:"student a am i",请你将数组的内容改为"i am a student".
- 判断回文数、回文字符串(从左边读和从右边读一样)
- 使用可变参数列表实现print("s\tc\n","bit-tech",'w');
- 使用可变参数列表实现任意个数求平均值
- hibernate.cfg.xml配置
- 编写程序实现strlen()函数,strcmp(),strcpy(),strcat()的功能
- util 将bean 独立出来 写法
- 编写一个程序统计输入字符串中: 各个数字、空白字符、以及其他所有字符出现的次数
- 实现一个函数int my_atoi(char s[]),可以将一个字符串转换为对应的整数
- 一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。请找出这个数字。(使用位运算)
- 不使用(a+b)/2这种方式,求两个数的平均值(保证不会溢出)
- 两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?(异或的用法)