- 1、本文档共7页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Linux管道通信浅析.doc
Linux管道通信浅析
【摘 要】在Linux下,由于处于用户态的不同进程之间是彼此隔离的,它们必须通过某种机制来进行通信。Linux平台下提供了多种进程通信方式,如管道、信号量、消息队列等,本文主要研究了Linux环境中的管道通信的实现机制,探讨无名管道和有名管道的工作方式,及相应的创建和使用的方法。
【关键词】Linux、进程通信、管道
一、管道实现机制
我们把从一个进程连接到另一个进程的数据流称为 “管道”,这是最早的Linux进程间通信机制之一。在Linux中管道常作为一种特殊文件处理。实际上,管道是内核中一个固定大小的缓冲区,它按先进先出的方式进行数据传输,一个进程向管道中写的内容会被管道另一端的进程读出。每次写入的内容都添加在管道缓冲区的末尾,且从缓冲区的头部读出数据,读写的位置自动增加,并且从管道读数据是一次性操作,数据一旦被读,便从管道中被抛弃。在缓冲区写满时,则由相应的规则控制读写进程进入等待队列,当空的缓冲区有写入数据或满的缓冲区有数据读出时,就唤醒等待队列中的读写进程继续读写。
管道分无名管道和有名管道。无名管道没有文件名,也没有磁盘节点,仅作为一个内存对象存在,用完后便销毁。无名管道没有显式的打开过程,实际上它在创建时就自动打开了,故只能由有亲缘关系的两个进程间通信使用。而有名管道克服了无名管道没有名字的限制,可由任意两个或多个进程间通信使用,它的使用方法和普通文件类似,都遵循打开、读、写、关闭的过程,只是读写的内部实现和普通文件有所不同。
二、无名管道
(一)无名管道创建
int pipe(int fd[2])在Linux中可以通过系统调用建立管道。当一个管道建立时,会创建两个文件描述符fd [0]和fd [1],其中fd [0]固定用于读管道,fd[1]固定用于写管道,如图1所示,这样就构成了一个半双工通道。
由于管道用于不同进程间通信,而调用pipe()创建的管道两端处于一个进程中,这在实际应用中没有太大意义。因此,通常先是创建一个管道,再通过调用fork()函数创建子进程,该子进程会继承父进程所创建的管道,这时,父子进程就可以共享该管道。管道的文件描述符对应关系如图2所示。此时关系看似非常复杂,实际上却给不同进程之间的读写创造了很好的条件。父子进程分别拥有自己的读写通道,为了实现父子进程之间的读写,只需把无关的读端或写端文件描述符关闭即可。如在图3中将父进程的写端fd[1]和子进程的读端fd[0]关闭,此时,父子进程之间就建立起了一条“子进程写入父进程读取”的通道。反之,亦如此。
(二) 无名管道读写操作
创建完管道后,便可以调用I/O函数,如close、read、write等函数,对管道进行读写了,但注意与普通文件读写还有一定区别。
1.从无名管道中读取数据。如果管道写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
当管道写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数或返回请求的字节数。
2.向无名管道中写入数据。向管道中写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,则写操作将一直阻塞。
三、有名管道
有名管道建立在实际的磁盘介质上,有自己的名字,它以FIFO的文件形式存在于文件系统中。故即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信。
(一) 有名管道创建
int mkfifo(const char * pathname, mode_t mode)
该函数的第一个参数是路径名,即创建后FIFO的名字。若该参数是一个已经存在的路径名时,会返回EEXIST错误,故在调用mkfifo函数前最好先检查FIFO是否已经创建。
第二个参数与open()函数中的mode参数相同。如果程序在打开FIFO时指定了只读/只写方式,则该进程对于打开的FIFO就是一个读端/写端。如果指定的是读写方式,进程既是读端又是写端。
(二) 有名管道的打开
无名管道在创建时自动打开,但有名管道在使用时必须调用open()打开。因为无名管道有两个文件数据结构:对应的VFS索引节点及共享数据页,在进程每次运行时都会创建一次,而FIFO一旦创建便一直存在。
对管道使用open()时可能会引起阻塞。若同时用读写方式(O_RDWR)打开,则不会引起阻塞;若用只读方式(O_RDONLY)打开,则open()会阻塞一直到有写方打开管道, 除非指定了
文档评论(0)