Linux中的管道pipe----管道的四种情况和特点

来源:互联网 发布:微交易系统源码下载 编辑:程序博客网 时间:2024/06/08 17:45
管道(pipe)----是用来支持两个或多个进程间进行进程间通信(IPC)
进程间通信(IPC)----每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到。所以进程之间要交换数据必须通过内核。
                     不同进程看到的公共资源是由操作系统(OS)提供的。
管道(pipe)函数原型为: int pipe(int pipefd[2]) pipefd[2]为输出型参数,是一个数组,存放打开的两个文件描述符。
                         一般情况下,文件描述符0、1、2为标准输入输出错误,pipefd[0]打开文件描述符3,pipefd[1]
                         打开文件描述符4。0、1下标分别对应管道的读端和写端
管道的特点:
(1)管道适用于单向通信,防止用户误操作;
(2)管道目前只用于具有血缘关系的进程,常用于父子进程;
(3)管道的生命周期是:随进程,管道是文件,在进程退出时文件销毁,管道也销毁;
(4)管道是基于字节流的通信方式;
(5)管道内部已经实现了同步,具有数据一致性;
下面是在Linux下的一个管道程序,我们创建一个进程,让子进程写,父进程读。父子进程同时有读端和写端,所以需要各自关闭一端。
  1 #include<stdio.h>  2 #include<unistd.h>  3 #include<string.h>  4 #include<stdlib.h>  5 int main()  6 {  7     int fds[2];  8     if(pipe(fds)<0)  9     { 10         perror("pipe"); 11         return 1; 12     } 13     printf("fds0:%d,fds1:%d\n",fds[0],fds[1]); 14  15     pid_t id=fork(); 16     if(id==0) 17     { 18         close(fds[0]);         //子进程关闭读端 19         const char* child="hello father,i am child!"; 20         int i=0; 21         while(i<10)           //只写入10次数据 22         { 23             sleep(1); 24             printf("child run...!,%d\n",i); 25             write(fds[1],child,strlen(child)); 26             i++; 27         } 28         exit(0); 29     } 30     else 31     { 32         close(fds[1]);          //父进程关闭写端 33         char buf[1024]; 34         while(1) 35         { 36             ssize_t s=read(fds[0],buf,sizeof(buf)-1);         //读成功后进行打印 37             if(s>0) 38                 { 39                     buf[s]=0; 40                     printf("father recv:%s\n",buf); 41                 } 42         } 43         pid_t ret=waitpid(id,NULL,0); 44         if(ret>0) 45         { 46             printf("waitpid success!\n"); 47         } 48     } 49 }

管道有四种情况:

1、读方不关闭读端,但是不读,写方一直在写----子进程会一直写,直到写满缓冲区

  1 #include<stdio.h>  2 #include<unistd.h>  3 #include<string.h>  4 #include<stdlib.h>  5 int main()  6 {  7     int fds[2];  8     if(pipe(fds)<0)  9     { 10         perror("pipe"); 11         return 1; 12     } 13     printf("fds0:%d,fds1:%d\n",fds[0],fds[1]); 14  15     pid_t id=fork(); 16     if(id==0) 17     { 18         close(fds[0]); 19         const char* child="hello father,i am child!"; 20         int i=0; 21         while(1)           //子进程一直写 22 //      while(i<10) 23         { 24 //          sleep(1); 25             printf("child run...!,%d\n",i); 26             write(fds[1],child,strlen(child)); 27             i++; 28         } 29         exit(0); 30     } 31     else 32     { 33         close(fds[1]); 34         char buf[1024]; 35         sleep(100000);            //父进程不读,进行睡眠 36         while(1) 37         { 38             ssize_t s=read(fds[0],buf,sizeof(buf)-1); 39             if(s>0) 40                 { 41                     buf[s]=0; 42                     printf("father recv:%s\n",buf); 43                 } 44         } 45         pid_t ret=waitpid(id,NULL,0); 46         if(ret>0) 47         { 48             printf("waitpid success!\n"); 49         } 50     } 51 }

2、读方一直读,写方不写,没有关闭写端----父进程一直在等待子进程写入

  1 #include<stdio.h>  2 #include<unistd.h>  3 #include<string.h>  4 #include<stdlib.h>  5 int main()  6 {  7     int fds[2];  8     if(pipe(fds)<0)  9     { 10         perror("pipe"); 11         return 1; 12     } 13     printf("fds0:%d,fds1:%d\n",fds[0],fds[1]); 14  15     pid_t id=fork(); 16     if(id==0) 17     { 18         close(fds[0]); 19         const char* child="hello father,i am child!"; 20         int i=0; 21         sleep(10000);              //写方不写 22         while(1) 23 //      while(i<10) 24         { 25 //          sleep(1); 26             printf("child run...!,%d\n",i); 27             write(fds[1],child,strlen(child)); 28             i++; 29         } 30         exit(0); 31     } 32     else 33     { 34         close(fds[1]); 35         char buf[1024]; 36         while(1) 37         { 38             ssize_t s=read(fds[0],buf,sizeof(buf)-1); 39             if(s>0) 40                 { 41                     buf[s]=0; 42                     printf("father recv:%s\n",buf); 43                 } 44         } 45         pid_t ret=waitpid(id,NULL,0); 46         if(ret>0) 47         { 48             printf("waitpid success!\n"); 49         } 50     } 51 }

3、写方写了一些不写了,关闭了写端,读方读完剩余的数据后,read返回0,就像读到了文件结尾一样

 16     if(id==0) 17     { 18         close(fds[0]); 19         const char* child="hello father,i am child!"; 20         int i=0; 21 //      sleep(10000); 22         while(1) 23         { 24             sleep(1); 25             printf("child run...!,%d\n",i); 26             write(fds[1],child,strlen(child)); 27             i++; 28             if(i>5)          //写方写入5次之后关闭写端 29             { 30                 close(fds[1]); 31                 break; 32             } 33         } 34         exit(0);
 35     }
 36     else
 37     {//father->read
 38         close(fds[1]);
 39         char buf[1024];
 40         int count=0;
 41         while(1)
 42         {
 43             ssize_t s=read(fds[0],buf,sizeof(buf)-1);
 44             if(s>0)
 45                 {
 46                     buf[s]=0;
 47                     printf("father recv:%s\n",buf);
 48                 }
 49             if(s==0) //读失败
 50             {
 51                 printf("no write,code:%d\n",s);
 52             }
 53         }
 54         int status=0; 55         pid_t ret=waitpid(id,&status,0); 56         if(ret>0) 57         { 58             printf("waitpid success!,sig:%d,exitCode:%d\n",status&0xff,(status>>8)&0xff); 59         } 60     } 61 }

4、写方一直在写,读方读了一些后直接退出,关闭读端----读方只读了一些后退出,waitpid收到异常信号13

 36     else 37     {//father->read 38         close(fds[1]); 39         char buf[1024]; 40         int count=0; 41         while(1) 42         { 43             ssize_t s=read(fds[0],buf,sizeof(buf)-1); 44             if(s>0) 45                 { 46                     buf[s]=0; 47                     printf("father recv:%s\n",buf); 48                 } 49             count++; 50             if(count>5)         //读方读了五次数据后关闭读端,直接退出 51             { 52                 close(fds[0]); 53                 break; 54             } 55         }
 56         int status=0;
 57         pid_t ret=waitpid(id,&status,0);
 58         if(ret>0)
 59         {
 60             printf("waitpid success!,sig:%d,exitCode:%d\n",status&0xff,(status>>8)&0xff);
 61         }
 62     }
 63 }

                                             
0 0
原创粉丝点击