管道容量及缓冲区的组成

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

(四)管道的大小

时间: 2024-07-29 09:45:48

管道容量及缓冲区的组成的相关文章

管道及其容量

1.管道 管道是一种最基本的IPC机制,由pipe函数创建: #include <unistd.h> int pipe(int filedes[2]); 调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端.所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);向这个文件

linux管道的容量和内部组织方式

1.管道容量  count=65536,即64KB #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<fcntl.h> #include<errno.h> #include<stdlib.h> #include<string.h> int main() { int _pipe[2]; if(pipe(_pipe)==-1) { print

进程间通信---管道

每个进程各自有着不同的用户地址空间,任何一个进程的全局变量在另一个进程中是看不到的,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2在从内核中把数据读走,内核提供的这种机制称为进程间通信. 进程间通信的本质:让不同的进程看到同一份系统资源. 进程通信方式:管道(pipe) pipe函数: #include <unistd.h> int pipe(int fd[2]); 调用pipe函数时在内核中开辟一块缓冲区(管道)用于通信,它有一个读端

JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码

一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化. ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的

Linux管道(匿名PIPE)

管道基本概念 管道是Unix中最古老的进程间通信的形式. 我们把从一个进程连接到另一个进程的一个数据流称为一个"管道" 如:ps aux | grep httpd | awk '{print $2}' 管道示意图 管道的本质 固定大小的内核缓冲区 管道限制 1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道; 2)匿名管道只能用于具有共同祖先的进程(如父进程与fork出的子进程)之间进行通信;[通常,一个管道由一个进程创建,然后该进程调用fork,此后父子进

linux学习——管道

这篇文章简单介绍一下操作系统中的管道,并主要解决以下两个问题: 1.管道的内部实现 2.管道的容量? 管道是操作系统中,不同进程之间进行通信的方式. 根据通信的进程之间的关系,管道分为匿名管道和非匿名管道 其中,匿名管道只能用于有"血缘关系"的进程之间进行通信,而命名管道则可以用于任意两进程的通信 此外,管道是单向的,所以2个管道就可以实现进程之间的双向通信 管道的实现原理: 我们知道,进程之间的数据是私有的,即使是父子进程,也是如此,所以,要想让2个进程共享某个数据,我们可以在指定的

Linux的进程间通信 - 管道

Linux的进程间通信 - 管道 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问问题和甄误反馈,共同进步. 微博ID:orroz 微信公众号:Linux系统技术 前言 管道是UNIX环境中历史最悠久的进程间通信方式.本文主要说明在Linux环境上如何使用管道.阅读本文可以帮你解决以下问题: 什么是管道和为什么要有管道? 管道怎么分类? 管道的实现是什么样的? 管道有多大? 管道的大小是不是可以调整?如何调整? 什

进程间通信—无名管道通信

进程间通信——Interprocess communication——IPC 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信. 不同进程间的通信本质:进程之间可看到一份公共资源:而提供这份资源的形式或者提供者不同,造成了通信方式不同. Linux下进程通信方式主要有以下几种: 1.管道---pipe 无

IPC通信之管道

管道 Linux管道(pipe)提供一种单向(半双工)的进程间通讯机制.管道有一个读端和一个写端.从写端写入的数据可以重读端读出来.函数pipe()创建一个管道,返回两个文件描述符,fd[0]是读端,f[1]是写端.如下图 管道的读写可以使用Linux标准IO操作接口进行,例如read.write等.从图1不难看出,数据一直缓存在内核中直到被读取出来. 单个进程的管道几乎没有任何用处.通常调用pipe的进程接着调用fork,这样就创建了从父进程到子进程的IPC通道.如下图 缺省情况下,管道工作在