管道
- 匿名管道
命名管道
匿名管道:
创建:命令
|
创建、函数int pipe(int pipefd[2]);
创建
pipe创建匿名管道:
父进程fork出子进程,父进程关闭读端、子进程关闭写端。如图,
注:0、1、2、3、4是文件描述符
管道特点:- 只能用于具有亲缘关系的进程间通信
- 管道提供流式服务
- 管道生命随进程,即进程结束,管道释放
一般情况下,内核对管道操作进行同步与互斥
管道读写规则:
没有数据可读
不指定O_NONBLOCK:read调用阻塞,即进程暂停执行,一直等到有数据来为止。
指定O_NONBLOCK:read调用返回-1,errno值为EAGAIN。当管道满的时候
不指定O_NONBLOCK:write调用阻塞,知道有进程读走数据
指定O_NONBLOCK:调用返回-1,errno值EAGAIN。如果写端文件描述符关闭,read返回为0;
- 如果读端文件描述符关闭,写端产生SIGPIPE信号 ,导致写端进程退出。
读端关闭时实现代码如下:
1 #include<unistd.h>
2 #include<string.h>
3 #include<stdlib.h>
4 #include<stdio.h>
5
6 int main()
7 {
8 int fd[2];
9 if(pipe(fd)<0)
10 {
11 perror("pipe");
12 exit(1);
13 }
14 pid_t pid = fork();
15 if(pid<0){perror("fork");exit(1);}
16 if(pid==0)
17 {
18 close(fd[1]);
19 int count = 0;
20 while(1){
21 char buf[1024] = {0};
22 int s = read(fd[0],buf,sizeof(buf)-1);
23 if(s>0)
24 {
25 count++;
26 buf[s] = '\0';
27 printf("child read # %s\n",buf);
28 fflush(stdout);
29 }
30 if(count>5){
31 printf("child exit\n");
32 break;
33 }
39 }
40 exit(0);
41 }else
42 {
43 close(fd[0]);
45 while(1){
46 char buf[1024] = {0};
47 sleep(1);
50 printf("parent write#");
51 fflush(stdout);
52 scanf("%s",buf);
53 write(fd[1],buf,strlen(buf));
62 exit(0);
63 }
结果如下:
写端关闭实现代码:
1 #include<unistd.h>
2 #include<string.h>
3 #include<stdlib.h>
4 #include<stdio.h>
5
6 int main()
7 {
8 int fd[2];
9 if(pipe(fd)<0)
10 {
11 perror("pipe");
12 exit(1);
13 }
14 pid_t pid = fork();
15 if(pid<0){perror("fork");exit(1);}
16 if(pid==0)
17 {
18 close(fd[1]);
19 while(1){
20 char buf[1024] = {0};
21 int s = read(fd[0],buf,sizeof(buf)-1);
22 if(s>0)
23 {
24 buf[s] = '\0';
25 printf("child read # %s\n",buf);
26 fflush(stdout);
27 }
28 else
29 {
30 printf("child exit\n");
31 break;
32 }
33 }
34 exit(0);
35 }else
36 {
37 close(fd[0]);
38 int count = 0;
39 while(1){
40 char buf[1024] = {0};
41 sleep(1);
42 if(count<5)
43 {
44 printf("parent write#");
44 printf("parent write#");
45 fflush(stdout);
46 scanf("%s",buf);
47 write(fd[1],buf,strlen(buf));
48 count++;
49 }else
50 {
51 printf("parent exit");
52 break;
53 }
54 }
55 }
56 exit(0);
57 }
命名管道:
匿名管道只能在具有亲缘关系的进程之间传递通信,命名管道可以实行根本不相关的进程通信。
创建:mkfifo命令、int mkfifo(const char *pathname, mode_t mode);
函数
匿名管道与命名管道之间唯一的区别是创建方式的不同,一旦这些工作完成后,具有相同的语义