摘要:
1、进程间通信的简介;
2、pipe管道通信;
3、pipe管道通信的特点;
4、管道通信过程中会遇到的四种情况;
5、fifo管道通信;
6、对比fifo管道与pipe管道;
7、管道 |;
8、管道的缓冲区的容量大小;
1、进程间通信
简称:IPC(InterProcess Communication)
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到;
所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,
所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,
进程1把数据从用户空间拷到内核缓 冲区,
进程2再从内核缓冲区把数据读走,
内核提供的这种机制称为进程间通信。
下面是一个图形解释进程间通信的形象图:
2、管道通信(pipe)
管道是一种最基本的的IPC机制,是有pipe函数来提供的。
函数的原型是:
#include <unistd.h>//函数的头文件
int pipe(int pipefd[2]);//函数原型
pipe函数参数与函数返回值简介:
在调用pipe函数时在内核中开辟一块缓冲区(也可看成是文件)(称为管道)用于通信;
它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符;
filedes[0]指向管道的读端,filedes[1]指向管道的写端。
所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);
向这个文件读写数据其实是在读写内核缓冲区。pipe函数调用成功返回0,调用失败返回-1。
上面的就是这个函数的大致的使用方法:
但是开辟管道之后要怎么来实现两个进程之间的通信,下面是一些使用的方法:
1、父进程创建管道
2、父进程fork生出子进程
3、父进程关闭读端,子进程关闭写端
完成上面的操作之后 ,现在的进程就是 一个进程来读,一个进程来写;
代码实现:
pipe管道通信的特点:
1、管道是依靠文件系统的,所以管道 的生命周期是 随进程的;
2、进程之间的管道通信是单向的。只能有一个进程读,另一个进程写;要么反过来;
3、这种只能用于有血缘关系的进程(常用于是兄弟进程),因为他们需要有相同的文件描述符表;
4、进程间的通信是按照 数据流的方式来通信,一个进程写了多少,则此进程就读多少;
5、管道之间的读写是按照同步的方式来进行的;(写完之后再读)
使用管道过程中需要注意的四种问题:
1、如果指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。
代码验证:
代码中子进程来写,五次之后关闭写端 、、、、的输出结果:
2、如果有指向管道写端的文件描述符没关闭,而持有管道写端的 进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
代码验证:
代码中的子进程每次写完之后,都会等上100秒,父进程读完之后都会 阻塞等待 :
3、如果指向管道读端的文件描述符都关闭了,这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
代码验证:
代码中的父进程来读,五次之后关闭读端,父进程来接受自己成的退出信息
4、如果有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。
代码验证:
代码中的 父进程读完之后,等待100秒 ,,,结果:
3、管道通信(FIFO)
概念:
pipe管道,一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服。。
FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。值得注意的是,FIFO(first input first output)总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。
管道的创建:
创建命名管道的系统函数有两个:mknod和mkfifo。两个函数均定义在头文件sys/stat.h。
我们这里主要介绍的mkfifo
函数原型如下:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
函数原型的解析:
代码的验证函数:
进程client 写:
进程server 读:
命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似。
4、管道(pipe)、命名管道(fifo)对比
对 上面两个管道的相同点:
1、依赖文件系统,生命周期随进程;
2、都是单向通信的;
3、按照数据流的方式通信;
4、读写之间都是按照同步机制来访问的。
不同点:
1、管道只能应用于有血缘关系的进程,命名管道可应用于所有的进程
2、管道依赖于文件描述符表,不需要明确的创建文件,命名管道需要明确的创建fifo文件存于文件系统中。
5、管道 |
很多的人都知道 | 这个符号是一种管道 ,但是学了上面的知识 ,我们就要知道 ;
|这是一种匿名的管道,
为什么呢?
首先、它没有穿件新的管道文件;
再者、它通信的进程虽然不是父子进程,但是可以看成是兄弟进程。 同是shell创建的子进程。
5、管道缓冲区的大小
每一个管道的缓冲区都是有大小的;
我们可以使用命令
ulimit -a
来查看管道的容量:
我们在其来验证一下:
实现的结果:
pipe capacity = 65536;