管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别。
    有名管道叫named pipe或者FIFO(先进先出),可以用函数mkfifo()创建。

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

· 限制管道的大小。实际上,管道是一个固定大小的缓冲区。在Linux中,该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。

· 读取进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。
注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。

1. 管道的结构
在 Linux 中,管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。通过将两个 file 结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。

2.管道的读写
管道实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即管道读函数pipe_read()和管道写函数pipe_wrtie()。管道写函数通过将字节复制到 VFS 索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用了锁、等待队列和信号。

当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的 file 结构。file 结构中指定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作:

·内存中有足够的空间可容纳所有要写入的数据;

·内存没有被读程序锁定。

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

管道的读取过程和写入过程类似。但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,这依赖于文件或管道的打开模式。反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放。

因为管道的实现涉及很多文件的操作,因此,当读者学完有关文件系统的内容后来读pipe.c中的代码,你会觉得并不难理解。

Linux 管道的创建和使用都要简单一些,唯一的原因是它需要更少的参数。实现与 Windows 相同的管道创建目标,Linux 和 UNIX 使用下面的代码片段:

  pipe函数来创建 Linux 命名管道
int fd1[2];
if(pipe(fd1))

{ printf("pipe() FAILED: errno=%d",errno);

return 1;

}

  Linux 管道对阻塞之前一次写操作的大小有限制。专门为每个管道所使用的内核级缓冲区确切为 4096 字节。 除非阅读器清空管道,否则一次超过 4K 的写操作将被阻塞。实际上这算不上什么限制,因为读和写操作是在不同的线程中实现的。

  Linux 还支持命名管道。对这些数字的早期评论员建议我,为公平起见,应该比较 Linux 的命名管道和 Windows 的命名管道。我写了另一个在 Linux 上使用命名管道的程序。我发现对于 Linux 上命名的和未命名的管道,结果是没有区别。

  Linux 管道比 Windows 2000 命名管道快很多,而 Windows 2000 命名管道比 Windows XP 命名管道快得多。

例子:
#include<stdio.h>
#include<unistd.h>

int main()
{
int n,fd[2]; // 这里的fd是文件描述符的数组,用于创建管道做准备的
pid_t pid;
char line[100];
if(pipe(fd)<0) // 创建管道
printf("pipe create error\n");

if((pid=fork())<0) //利用fork()创建新进程
printf("fork error\n");

else if(pid>0){ //这里是父进程,先关闭管道的读出端,然后在管道的写端写入“hello world"
close(fd[0]);
write(fd[1],"hello word\n",11);
}
else{
close(fd[1]); //这里是子进程,先关闭管道的写入端,然后在管道的读出端读出数据
n= read(fd[0],line,100);
write(STDOUT_FILENO,line,n);
}
exit(0);
}

Linux文件类型之 管道相关推荐

  1. linux用pipe创建的文件类型,linux文件类型之 管道

    inux 管道管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别.有名管 ...

  2. Linux基本命令及Linux文件类型

    Linux文件类型 1.普通文件它最常使用的一类文件,其特点是不包含有文件系统的结构信息.通常用户所接触到的文件,如图形文件.数据文件.文档文件.声音文件等都属于这种文件.这种类型的文件按其内部结构又 ...

  3. Linux文件类型发布啦!

    在windows下面是通过文件的扩展名来区分文件类型的,但是在linux中却不是这儿样的.在linux中就没有所谓的文件扩展名,一个linux文件能不能被执行时取决于它的属性中是否有x,与文件名一点关 ...

  4. linux系统字符设备文件类型,Linux文件类型以及颜色标识

    1.Linux文件类型介绍 Linux系统不同于window系统,两者文件类型也有很大的差异.Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如f ...

  5. Linux文件类型有哪些?

    Linux文件类型: -:普通文件 d:目录文件(directory) l:链接文件(link) b:块设备文件 (binary) c:字符设备文件 (character) p:管道文件 (pipe) ...

  6. linux ls 中文乱码_每天一个linux命令:Linux文件类型与扩展名

    Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...

  7. 每天一个linux命令(目录文件操作):【转载】Linux文件类型与扩展名

    Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...

  8. Linux文件类型及颜色标识整理

    Linux文件类型及颜色标识整理 使用工具: ls命令 ls –l:以常格式显示文件及目录的详细信息 例如:-rw-r--r--  1 root root       0 10月 12 13:32 2 ...

  9. linux文件类型及用户相关命令

    Linux文件类型: 普通文件:-,file(内容格式) 目录文件:d 块设备:  b 字符设备:c 符号链接文件:l 套接字文件:s 命名管道文件:p 文件:属主.属组 属主:拥有者 属组:所属的组 ...

最新文章

  1. oracle 复制 mysql_MySQL与Oracle之间互相拷贝数据的Java程序
  2. BrupSuite渗透测试笔记(十一)
  3. 【 MATLAB】 Two-step WLS algorithm Simulation of TOA - Based Positioning
  4. git 将暂存区文件提交_Git知识
  5. Gradle 工具的源码研究
  6. Java / Spring:如何快速生成整个Swagger记录的CRUD REST API
  7. Ubuntu Sublime Text 3 搜狗拼音
  8. FW: How to use Hibernate Lazy Fetch and Eager Fetch Type – Spring Boot + MySQL
  9. C++_sizeof关键字_实型(也叫浮点型)---C++语言工作笔记011
  10. fckeditor异常总结---java.lang.ClassNotFoundException: org.devlib.schmidt.imageinfo.ImageInfo
  11. linux通信加密软件,5个Linux加密工具:VeraCrypt,CipherShed,CryFS,GnuPG,Encfs介绍
  12. Macbook 修改照片的大小
  13. 多项式输出 洛谷P1067(普及-)
  14. AddMvcCore,AddControllers,AddControllersWithViews,AddRazorPages的区别
  15. AI时代——人工智能技术图谱,它来啦(机器学习+深度学习学习路线)
  16. 一款App的开发成本是多少?
  17. 构建一个JPEG解码器(2):文件结构
  18. mac安装win7之后鼠标失灵_解决最新MAC(usb3.0)安装windows7鼠标不动造成无法安装都问题...
  19. 仿淘宝物流的跟踪图,不需要自定义时间轴
  20. 【题解】慈溪中学-8.14-T2

热门文章

  1. Hexo+buttterfly适合任意主题美化(悬挂动态修饰物)
  2. 2019一键清空朋友圈_批量清理朋友圈说说
  3. 搜狗输入法输入,字母全是大写且之间有间隔
  4. 持续集成Jenkins+Gitlab
  5. 时间花在哪,价值就在哪
  6. Word中英文导致空格间距过大如何解决?
  7. 【高等数学笔记】两类曲线积分、曲面积分的转化
  8. C# 集合-并发处理
  9. 教你u盘装系统不成功怎么办
  10. 几个好用Maven 镜像仓库地址