每个进程都有不同的用户地址空间,任何一个进程的全局变量在 另一个进程中都看不到,所以进程之间要交换数据必须 通过内核,在内核中开辟一块缓冲区,把进程1的数据从用户空间考到内核区,进程2再从内核区把数据考走,内核提供的这种机制叫做进程间通信
(一)管道的外部实现
当我们定义一个管道时,这个管道是由内核管理的一个缓冲区,可以抽象为现实生活中的线路;管道的一端链接一个进程的输出 ,这个进程 会向管道中放入信息;管道的另一端链接一个进程的输出,这个进程取出被放入的信息。当管道被放满时尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也会消失 。从原理上讲管道利用fork机制建立从而让两个进程可以连接到一个 管道上。
从本质上讲管道也是一种文件,但和文件有所不同的是管道可以克服使用文件通信的两个问题:
(1)限制管道的大小,实际上管道是一个固定大小的缓冲区,在Linux中该缓冲区的大小为1也,即4K字节,它不能像文件那样不加检验的增长。使用单个固定缓冲区也会带来问题,比如在写管道是可能变满,随后对管道的write()调用将默认的阻塞。
(2)读取进程可能工作的比写进程快。
(二)管道内部实现机制
管道是一种基本的IPC机制,由pipe函数创建
#include<unsistd.h>
int pipe(int filedes[2])
调用pipe函数时在内核中开辟一块缓冲区,它有一个读短和一个写端,然后通过filedes[1]指向管道的写端,所以管道在 用户程序看来就像一个打开文件,通过read(filedes[0])或者write(filedes[1])向这个文件读写数据其实是在读写内核缓冲区。pipe调用成功返回0,失败返回-1
1.父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端
2.父进程调用fork函数创建子进程,那么子进程也有两个文件描述符指向同一个管道
3.父进程关闭管道的读端,子进程关闭管道的写端,父进程可以往管道里写,子进程可以从管道里读,管道使用环形队列实现的,数据从写端流入读端流出,这样子实现了进程间的通信
(三 )管道缓冲区的组成
匿名管道(pipe)
(1)只能用于有血缘关系的进程间通信
(2)生命周期随进程
(3)提供数据间通信方式 ,面向字节流
(4)管道内部实现的进程同步机制
(5)单向数据通信
使用管道需要注意一下四种特殊情况
(1)如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数为 0)而任然有进程从管道读端读数据,那么管道中剩下的数据都被读取以后,再次read会返回0,就像读到文件末尾一样
(2)如果有指向管道写端的文件描述符没关闭 (管道写端的文件描述符大于0)而持有管道写端的进程也没有向管道中写入数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取以后,再次read会阻塞,直到管道中有数据可读了 才会读取数据并返回
(3)如果所有指向管道读端的文件描述符都关闭了(管道中的引用计数等于0)这时有进程向管道写端write,那么该进程会收到信号SIGPIPE通常会导致进程异常终止
(4)如果指向管道读端的文件描述符没有关闭(管道读端的引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道写满时再次write会阻塞,直到管道中有了空位置才写入数据并返回
命名管道(FIFO)
1.概念 :
管道的一个不足之处是没有名字,因此只能用于亲缘关系的进程间通信,FIFO不同于管道之处在于它提供 一个路径名与之关联,以FIFO的形式存储于文件系统;命名管道是一个设备文件,因此即使进程与创建FIFO的进程间不存在亲缘关系,只要可以访问该路径,就能通过FIFO相互通信
2.命名管道的创建与读写
Linux下有两种方式创建命名管道,一是shell下交互的建立命名管道,二是程序中使用系统函数建立命名管道。shell可用mknod ,mkfifo命令,下面使用mknod namedpipe
创建命名管道的系统函数有两个:mknod mkfifo两个函数均定义在头文件sys/stst.h
函数原型如下:
#include<sys/types.h>
#include<sys/stst.h>
int mknod(const char* path,mode_t mod,dev_t dev);
int mkfifo(const char* path,mode_t mode);
函数mknod参数中
path:为创建的命名管道全路径名;
mod:创建的命名管道模式,指明其存取权限;
dev:为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会 用到;
这两个函数调用成功返回0失败都返回-1
命名管道创建后就可以使用了,命名管道和管道的使用方法基本相同,使用命名管道时必须将其打开open(),因为命名管道存在与一个硬盘上的文件,而管道是存在与内存上的特殊文件
(四)管道的大小