标签:匿名管道
通信:因为进程有强大独立性,当想把自己数据交给另一个进程,需要通信。
通信本质:让不同进程看到相同资源。
匿名管道:管道:通过某种机制传递资源(数据),匿名管道只适用于有血缘关系的进程,一般用于父,子进程通信。
a.创建管道
b.创建子进程
c.父,子进程关闭自己不需要的文件描述符
注意:匿名管道提供单向通信,父读子写或父写子读,若要实现双向通信,可再创建一个管道。
#include<stdio.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<stdlib.h> int main() { int _pipefd[2]={-1,-1}; int ret=pipe(_pipefd); if(ret==-1) { perror("pipe"); return 2; } pid_t id=fork(); if(id<0) { perror("fork"); return 2; } else if(id==0) { close(_pipefd[0]); char buf[]="hello world"; int count=5; while(count--) { write(_pipefd[1],buf,strlen(buf)); sleep(1); } } else { close(_pipefd[1]); char buf[1024]={0}; int count=5; while(count--) { memset(buf,‘\0‘,sizeof(buf)); ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1); buf[_size]=‘\0‘; printf("buf:%s\n",buf); } } return 0; }
使用管道需注意以下四种情况:
1.如果所有指向管道写端的文件描述符都关闭了,仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。
1 #include<stdio.h> 2 #include<string.h> 3 #include<unistd.h> 4 #include<sys/types.h> 5 #include<stdlib.h> 6 int main() 7 { 8 int _pipefd[2]={-1,-1}; 9 int ret=pipe(_pipefd); 10 if(ret==-1) 11 { 12 perror("pipe"); 13 return 2; 14 } 15 16 pid_t id=fork(); 17 if(id<0) 18 { 19 perror("fork"); 20 return 2; 21 } 22 else if(id==0) 23 { 24 close(_pipefd[0]); 25 char buf[]="hello world"; 26 int count=5; 27 int i=0; 28 while(count--) 29 { 30 if(i==3) 31 { 32 printf("I want sleep\n"); 33 break; 34 } 35 write(_pipefd[1],buf,strlen(buf)); 36 sleep(1); 37 i++; 38 } 39 close(_pipefd[0]); 40 } 41 else 42 { 43 close(_pipefd[1]); 44 char buf[1024]={0}; 45 int count=5; 46 while(count--) 47 { 48 memset(buf,‘\0‘,sizeof(buf)); 49 ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1); 50 if(_size>0) 51 { 52 // buf[_size]=‘\0‘; 53 printf("buf:%s\n",buf); 54 } 55 } 56 } 57 //printf("%d ,%d \n",_pipefd[0],_pipefd[1]); 58 return 0; 59 }
2.如果有指向管道写端的文件描述符没关闭,持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
//修改子进程代码为 else if(id==0) 23 { 24 close(_pipefd[0]); 25 char buf[]="hello world"; 26 int count=5; 27 int i=0; 28 while(count--) 29 { 30 if(i==3) 31 { 32 sleep(10); 33 //printf("I want sleep\n"); 34 // break; 35 } 36 write(_pipefd[1],buf,strlen(buf)); 37 sleep(1); 38 i++; 39 } 40 // close(_pipefd[0]); 41 }
3.如果所有指向管道读端的文件描述符都关闭了,这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
//修改父进程中代码为: else 44 { 45 close(_pipefd[1]); 46 char buf[1024]={0}; 47 int count=5; 48 while(count--) 49 { 50 if(count==3) 51 close(_pipefd[0]); 52 memset(buf,‘\0‘,sizeof(buf)); 53 ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1); 54 if(_size>0) 55 { 56 // buf[_size]=‘\0‘; 57 printf("buf:%s\n",buf); 58 } 59 } 60 int status=0; 61 pid_t _pid=waitpid(id,&status,0); 62 printf("waitpid: %d,return status:%d\n",id,status&0xff); 63}
4.如果有指向管道读端的文件描述符没关闭,持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。
//修改父进程中代码为: else 44 { 45 close(_pipefd[1]); 46 char buf[1024]={0}; 47 int count=5; 48 while(count--) 49 {} 50 int status=0; 51 pid_t _pid=waitpid(id,&status,0); 52 printf("waitpid: %d,return status:%d\n",id,status&0xff); 53}
本文出自 “小止” 博客,请务必保留此出处http://10541556.blog.51cto.com/10531556/1762101
标签:匿名管道
原文地址:http://10541556.blog.51cto.com/10531556/1762101