Linux中的管道pipe----管道的四种情况和特点
Linux中的管道pipe----管道的四种情况和特点
管道(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
2 #include
3 #include
4 #include
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
2 #include
3 #include
4 #include
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
2 #include
3 #include
4 #include
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 }
Linux中的管道pipe----管道的四种情况和特点相关教程