码迷,mamicode.com
首页 > 其他好文 > 详细

管道容量及缓冲区的组成

时间:2016-07-14 07:17:11      阅读:384      评论:0      收藏:0      [点我收藏+]

标签:管道容量及缓冲区的组成

       每个进程都有不同的用户地址空间,任何一个进程的全局变量在 另一个进程中都看不到,所以进程之间要交换数据必须 通过内核,在内核中开辟一块缓冲区,把进程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(),因为命名管道存在与一个硬盘上的文件,而管道是存在与内存上的特殊文件


(四)管道的大小 

技术分享

技术分享


技术分享


技术分享




管道容量及缓冲区的组成

标签:管道容量及缓冲区的组成

原文地址:http://10808695.blog.51cto.com/10798695/1826221

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!