博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 管道
阅读量:6610 次
发布时间:2019-06-24

本文共 1291 字,大约阅读时间需要 4 分钟。

hot3.png

在Linux中,管道是一种使用非常频繁的通信机制。

从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为:限制管道的大小。

实际上,管道是一个固定大小的缓冲区。

Linux中, 该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。

使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生 时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。

读取进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。

当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。

注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。

在 Linux 中管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。

通过将两个 file 结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。

管道实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即管道读函数pipe_read()和管道写函数 pipe_wrtie()。

管道写函数通过将字节复制到 VFS 索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。

当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用 了锁、等待队列和信号。

当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的 file 结构。file 结构中指定了用来进行写操作的函数地址,内核调用该函数完成写操作。

写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,

才能进行实际的内存复制工作:内存中有足够的空间可容纳所有要写入的数据;内存没有被读程序锁定。

如果同时满足上述条件,写入函数首先锁定内存,然后从写进程的地址空间中复制数据到内存。否则,写入进程就休眠在 VFS 索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。写入进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写 入数据,或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接收到信号。

当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤 醒。

管道的读取过程和写入过程类似。

但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,这依赖于文件或管道打开模式

反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。

当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放。

转载于:https://my.oschina.net/darionyaphet/blog/318923

你可能感兴趣的文章
php 图形用户界面GUI 开发
查看>>
正则表达式详解
查看>>
linux文件与目录之权限对比
查看>>
LeetCode问题5
查看>>
AIX系列------ISO挂载
查看>>
如何打开被管理员禁止的注册表编辑器
查看>>
java根据经纬度计算距离
查看>>
MYSQL简单主从复制原理及实现
查看>>
U-Mail邮件服务器安全高效为政府信息化奠定基石
查看>>
sqlplus登陆方式说明
查看>>
窝里斗,只给微软看笑话
查看>>
递归函数打印斐波那契数列
查看>>
Too many open files 问题的解决
查看>>
CF976D. Degree Set
查看>>
I2C总线介绍及AT24C02驱动编写 笔记
查看>>
我的友情链接
查看>>
Nginx 在window server 2008R2上装有IIS启动不了
查看>>
C# 无法解析程序集
查看>>
利用expect实现交互登录
查看>>
Oracle服务器上Swap的配置
查看>>