第4章 管道和FIFO
4.1 概述
管道是最初的UNIX IPC形式。尽管对许多操作系统很有用,但因为它没有名字,从而智能由有亲缘关系的进程使用。
4.2 一个简单的客户——服务器例子
图中,客户从标准输入(stdin)读进一个路径名,并把它写入IPC通道。服务器从该IPC通道读出这个路径名,并尝试打开文件来读。如果服务器能打开该文件,它就读出其中的内容,并写入IPC通道,以作为对客户的响应;否则,它就响应一个出错的消息。
4.3 管道
所有样式的UNIX都提供管道。它由pipe函数创建,提供一个单项的数据流。
创建管道 fork,为子进程waitpid
从标准输入读进路径名,从管道复制到标准输出,从管道读出路径名,打开文件处理错误,把文件复制到管道。
4.4 全双工管道
例如SVR4的pipe函数以及许多内核都提供的socketpair函数
4.5 popen和pclose函数
popen函数,它创建一个管道并启动另一个进程,该进程要么从该管道读出标准输入,要么从该管道写入标准输出。
4.6 FIFO
FIFO由mkfifo函数创建
其中,pathname 是一个普通的UNIX路径名,它是该FIFO的名字
mode参数指定文件权限位,类似于open的第二个函数
4.6.1 例子
创建两个FIFO
调用fork(调用fork后,子进程调用我们的sever函数,父进程调用我们的client函数)
这个FIFO例子比起之前的管道例子变动如下:
创建并打开一个管道只需调用pipe
管道在所有进程都关闭后自动消失
4.6.2 无亲缘关系的客户和服务器
4.7 管道和FIFO的额外属性
一个描述符能以两种方式设置成非阻塞
①调用open时可指定O_NONBLOCK标志
②如果一个描述符已经打开,那么可以调用fcnt1以启动O_NONBLOCK标志
4.8 单个服务器多个客户
创建众所周知的FIFO,打开来读,打开来写。
读出客户请求
分析客户请求
打开客户请求的文件,将它发送到客户的FIFO
创建FIFO
构建客户请求行
打开 服务器的FIFO,写入请求
读出来自服务器的文件内容 或出错消息
4.8.1 FIFO write的原子性
4.8.2 FIFO和NFS的关系
FIFO是一种只能在单台主机上使用的IPC形式
4.9 对比迭代服务器和并发服务器
UNIX下的并发服务器称为每个客户一个子进程服务器,每当一个客户请求到达时,这种服务器就让主进程调用fork派生出一个子进程。
4.10 字节流和消息
4.11 管道和FIFO限制
4.12 小结
第5章 Posix消息队列
5.1 概述
消息队列可认为是一个消息链表。消息队列具有随内核的连续性。
5.2 mq_open、mq_close和mq_unlink函数
mq_open创建一个新的消息队列或者打开一个已存在的消息队列
已打开的消息队列是由mq_close关闭的
unlink是删除一个文件的机制
因为消息队列有内核的连续性,即没有消息打开消息队列,消息也一直存在,直到调用mq_unlink并让它引用计数达到0以删除该队列为止。
5.3 mq_getattr和mq_setattr函数
每个消息队列有四个属性,mq_getattr返回所有这些属性,mq_setattr则设置其中某个属性。
5.4 mq_send和mq_receive函数
这两个函数分别用于往一个队列中放置一个消息和从一个队列中取走一个消息。
5.5 消息队列限制
mq_mqxmsg 队列中最大消息数
mq_msgsize 给定消息的最大字节数
MQ_OPEN_MAX 一个进程能够同时拥有打开着消息队列的最大数目
MQ_PRIO_MAX 任意消息的最大优先级值增加1
5.6 mq_notify 函数
如果给定msgrcv指定非阻塞标志(IPC_NOWAIT),那么尽管不阻塞了,但必须持续调用该函数以确定何时有一个消息到达。我们说这称为轮询,是对cpu时间的浪费。我们需要一种方法,让系统告诉我们何时一个消息放到了先前为空的某个队列中。
5.7 Posix实时信号
5.8 使用内存映射I/O实现posix消息队列
5.9 小结
第6章 System V 消息队列
6.8 复用消息
与一个消息队列的每个消息相关联的类型字段提供了两个特征
6.11 小结