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
- Linux中的管道pipe----管道的四种情况和特点
- Linux下的管道pipe----管道容量和实现机制
- Linux管道PIPE的原理和应用
- Linux中的pipe与named pipe(FIFO),即管道和命名管道
- Linux中的pipe与named pipe(FIFO),即管道和命名管道
- 管道使用的四种特殊情况!
- 匿名管道的四种特殊情况
- 管道的四种读写情况
- 匿名管道的四种情况
- Linux操作系统中的管道(pipe)使用方法
- linux--管道pipe
- Linux 管道(pipe)
- Linux pipe(管道)
- linux管道pipe
- linux管道(pipe)
- linux管道pipe详解
- 【linux】匿名管道pipe
- Linux 管道pipe
- 正则表达式基础知识
- SSLstrip 强制 HTTPS 流量降级
- pthread_attr_init () 线程属性函数使用
- 登陆出错后JSP提示
- leetcode Reverse Integer
- Linux中的管道pipe----管道的四种情况和特点
- Android网络框架-Volley(一) 工作原理分析
- Storyboard快速创建带有Navigation的Controller
- SparkSQL之JDBC
- Android网络框架-Volley(四) 使用get和post方法发送json请求
- linux 计划任务
- J2EE框架(Struts&Hibernate&Spring)的理解
- Web API入门一
- 利用MLS算法计算法向量,并统一法向。