一.管道是进程间通信的一种重要手段,在linux中没有使用专门的数据结构,而是借助了文件系统的file结构和VFS索引节点inode。通过两个file结构指向同一个临时的VFS索引节点,而这个索引节点又指向一个物理页面实现的。如下图所示:
管道的实现的源代码在fs/pipe.c中,其中pipe_read()和pipe_write()是管道的读写函数。管道写函数通过将字节复制到VFS索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用了锁、等待队列和信号。
二.匿名管道(pipe)
常用于父子进程,也用于有血缘关系的进程间的通信。举例:父进程与子进程之间的通信。
因为匿名管道提供的进程通信是单向的,所以去掉上图中子的读(写),去掉父的写(读)。就可以实现子写父读(子读父写)。
代码实现子写父读:1 #include
2 #include
3 #include
4 #include
5 #include
6
7 int main()
8 {
9 //1.创建管道
10 int pipe_fd[2]={-1,-1};
11 if(pipe(pipe_fd)<0)
12 {
13 perror("pipe");
14 exit(1);
15
16 }
17 // printf("0-> %d,1-> %d",pipe_fd[0],pipe_fd[1]);检查读写
18 //2.创建进程
19 pid_t pid=fork();
20 if(pid<0)
21 {
22 perror("fork");
23 exit(2);
24
25 }
26 else if(pid==0)
27 {
28 //子进程
29 close(pipe_fd[0]);
30 int count=10;
31 char buf[]="hello bit";
32 while(count)
33 {
34 write(pipe_fd[1],buf, strlen(buf));
35 count--;
36 sleep(1);
37 }
38 close(pipe_fd[1]);
39 }
40 else
41 {
//父进程
42 close(pipe_fd[1]);
43 char buf[1024];
44 while(1)
45 {
46 memset(buf,'\0',sizeof(buf)-1);
47 ssize_t size=read(pipe_fd[0],buf,sizeof(buf)-1);
48 if(size>0)
49 {
50 buf[size]='\0';
51 printf("%s\n",buf);
52
53 }
54 }
55 }
56 close(pipe_fd[0]);
57 return 0;
58 }
1,7 Top
程序执行结果:
父进程读取到子写的10条信息。
使用匿名管道注意的状况(假设都是阻塞I/O)
1.管道引用计数
定义一个count,来决定读多少写多少
2.写端不关闭,并且不写,读端读完,继续等待,此时阻塞
3.读端关闭,写端在写,那么写进程收到信号SIGPIPE,通常导致进程异常中止。
4.读端没有关闭,但不读数据,写端一直在写,直到写满,再次阻塞或为空再写。
匿名管道的特点总结:
1.进程之间的通信是单向的
2.用于父子进程和有血缘关系的进程
3.提供的是流式服务
4.管道内部处理了数据写齐备然后才能读的机制
5.生命周期随进程。
三.命名管道(name pipe 或 FIFO)
命名管道是在shell交互地建立的,可以解决不同进程之间的进程问题。
代码:client:发消息的
#include
int main()
{
umask(0);
//创建命名管道
if(mkfifo("./.tmp",S_IFIFO|0666)<0)
{
perror("mkfifo");
exit(1);
}
int fd=open("./.tmp",O_WRONLY);//写方式打开
if(fd<0)
{
perror("open");
exit(2);
}
char buf[1024];
while(1)
{
memset(buf,'\0',sizeof(buf));
fflush(stdout);
ssize_t size=read(0,buf,sizeof(buf));//从标准入上读
buf[size]='\0';
write(fd,buf,sizeof(buf));
}
close(fd);
return 0;
}
server:接消息的
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 int main()
9 {
10
11 int fd=open("./.tmp",O_RDONLY);
12 if(fd<0)
13 {
14 perror("open");
15 exit(2);
16 }
17 char buf[1024];
18 while(1)
19 {
20 ssize_t size=read(fd,buf,sizeof(buf));
21 if(size>0)
22 {
23 buf[size-1]='\0';
24 printf("client say %s\n",buf);
25 }
26 else
27 {
28 printf("client quit or error\n") ;
29 break;
30
31 }
32
33
34 }
35 close(fd);
36 return 0;
37 }
运行结果:
client:
server: