管道通信:有名管道?无名管道?行业大牛通通教会你!

管道是一种最古老也是最基本的系统IPC形式,管道就像现实中的水管,水就像数据,它是消息传递的一种特殊方式,管道机制必须提供三方面的协调能力:互斥、同步和确定对方的存在。

在Linux中是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同;所有的Linux系统都提供此种通信机制。

管道有以下局限性:

1、它是半双工的,即数据一个管道上的数据只能在一个方向上流动,如果要实现双向通信,就必须在两个进程之间建立两个管道;

2、管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);

3、管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等。

4、管道只能在具有公共祖先的两个进程之间使用等等;

通常,进程会先调用pipe函数产生管道,接着调用fork()函数,fork函数会将父进程的相关数据结构继承到子进程中,这样就使子进程中的文件描述符表中的fd[0]和fd[1]指向父进程所指向的管道文件,这样就能实现两个进程之间的通信。

管道通信分为无名管道名管道,其中,无名管道:

int pipe(int filedes[2]);

返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。

必须在fork()中调用pipe(),否则子进程不会继承文件描述符。两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。

命名管道FIFO:

管道最大的劣势就是没有名字,只能用于有一个共同祖先进程的各个进程之间。FIFO代表先进先出,单它是一个单向数据流,也就是半双工,和无名管道不同的是:每个FIFO都有一个路径与之关联,从而允许无亲缘关系的进程访问。

int mkfifo(const char *pathname, mode_t mode);

这里pathname是路径名,mode是sys/stat.h里面定义的创建文件的权限.

命名管道具有很好的使用灵活性,表现在:

管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,当进程创建管道时,每次都需要提供两个文件描述符来操作管道。其中一个对管道进行写操作,另一个对管道进行读操作。对管道的读写与一般的IO系统函数一致,使用write()函数写入数据,使用read()读出数据。它是由内核管理的一个缓冲区,它的一端连接一个进程的输出,另一端连接一个进程的输入。管道的缓冲区不需要很大,它被设计为环形的数据结构,当两个进程都终止后,管道的生命周期也会被结束。

注:只有在管道的读端存在时,向管道中写入数据才有意义,具有亲缘关系通过进程间通信,用户自己创建管道,完成读写操作,管道和FIFO的数据是字节流,应用程序之间必须事先确定特定的传输"协议",同时,父子进程在运行时,它们的先后次序并不能保证。因此,为了保证父子进程已经关闭了相应的文件描述符,可在两个进程中调用sleep()函数达成。

你可能感兴趣的:(管道通信:有名管道?无名管道?行业大牛通通教会你!)