linux进程间通信:匿名管道和命名管道

来源:互联网 发布:手机实时监控软件 编辑:程序博客网 时间:2024/05/29 05:06

进程间通信的本质是让不同的进程看到一份公共的资源
这里写图片描述
上图中,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制成为进程间通信。

(一)匿名管道
管道是一种最基本的IPC(进程间通信)机制,由pipe函数创建

#include<unistd.h>int pipe(int filedes)

filedes参数传给用户两个文件描述符,filedes[0]指向文件的读端,filedes[1]指向文件的写端(就像0是标准输入,1是标注输出一样)。所以管道在用户程序看起来就像是一个打开的文件。函数调用成功返回0,失败返回-1。

管道实现进程间通信的方式如下:
这里写图片描述
具体步骤为:(1)父进程调用pipe开辟管道,得到两个文件描述符指向文件的两端
(2)父进程调用fork创建子进程,子进程也产生两个文件描述符指向文件的两端。
(3)由于管道只能实现单向通信,因此需要父子进程需要关闭适当的读写端。父进程关闭读端,子进程关闭写端,就像上图中看到的,父进程可以往管道里写,子进程可以从管道里读,管道使用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。

匿名管道:不能在系统的文件管理中找到相应管道所在的文件
匿名管道的特点:
(1)只能实现单向通信
(2)只能用于具有血缘关系的进程之间进行通信,通常用于父子进程。
(3)不会读到错误和乱码,因为管道自带同步机制
(4)管道在进行通信的时候,对外界提供的服务是面向字节流的
(5)管道是依赖于文件系统的,他的生命周期随进程,(即进程退出,则管道消失)

创建管道的代码如下:
这里写图片描述
这里写图片描述

1, 如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍然有 进程 从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像 读到文件末尾一样。即:写端关闭,读端一直读,读端读到文件尾信号退出。

这里写图片描述
(红色区域为代码修改部分)

2, 如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管道写 端的 进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数 据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
即:如果读者读完,则读者阻塞等待(写端是没有关闭,但是没有写东西)

3, 如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时有进 程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
即:所有读端关闭,写端一直写,写端被操作系统终止(SIGPIPE);
这里写图片描述
结果如下:
这里写图片描述
写端异常终止

4, 如果有指向管道读端的文件描述符没关闭(管道读端的引用计数大于0),而持有管道读 端的 进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时 再 次write会阻塞,直到管道中有空位置了才写入数据并返回。
即:如果写者写满,则写者阻塞等待(读端是没有关闭的, 但是没有读东西)。
这里写图片描述

(二)命名管道
匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。值得注意的是,FIFO(first input first output)总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。
创建命名管道用mkfifo函数

#include<sys/types.h>#include<sys/stat.h>int mkfifo(const char* pathname,mode_t mode)

命名管道创建后就可以使用了,命名管道和管道的使用方法基本是相同的。只是使用命 名管道时,必须先调用open()将其打开。因为命名管道是一个存在于硬盘上的文件,而管道是存在于内存中的特殊文件。需要注意的是,调用open()打开命名管道的进程可能会阻塞。但如果同时用读写方式 (O_RDWR)打开,则一定不会导致阻塞;如果以只读方式(O_RDONLY)打开,则调 用open()函数的进程将会被阻塞直到有写方打开管道;同样以写方式(O_WRONLY)打开 也会阻塞直到有读方式打开管道。

读端代码:
这里写图片描述

写端代码:
这里写图片描述

这里写图片描述

匿名管道和命名管道最大的区别就在于,匿名管道是用于有血缘关系的进程间通信,父子进程有相同的文件描述符来读取同一段缓冲区。命名管道可以用于毫无关系的进程间,是通过设定一个全局路径,使得两个进程都可以看到,用这个路径名来标识一个IPC通道。管道的缺点:管道是有容量限制的,且只能实现单向通信。

阅读全文
1 0
原创粉丝点击