第十五章-进程间通信

一、(未命名)管道

半双工管道是最常用的IPC形式,两种局限性:
(1)半双工时,数据只能在一个方向上流动。
(2)只能在具有公共祖先的两进程间使用。如父进程创建管道,fork后,父子进程可以使用管道。
在shell中执行"cmd1 | cmd2"时,shell会创建两个进程,然后用管道将前一条命令的标准输出与后一条命令的标准输入想连接。

#include <unistd.h>
int pipe(int fd[2]);

由fd返回两个文件描述符,fd[0]为读端,fd[1]为写端。即fd[1]的输出是fd[0]的输入。
在这里插入图片描述
单个进程中的管道基本没用。通常,会先调用pipe,接着调用fork,从而创建从父进程到子进程的IPC通道:
在这里插入图片描述
fork后做什么取决于我们想要的数据流的方向。如,对于父进程到子进程的管道,可以父进程中关闭读端(fd[0]),子进程中关闭写端(fd[1])。

当管道一端关闭后,发生什么:
(1)当读(read)一个写端已被关闭的管道时,在所有数据被读取后,read返回0,表示文件结束。
(2)当写(write)一个读端已被关闭的管道,则产生信号SIGPIPE。如忽略该信号或捕捉信号并从处理程序返回,则write返回-1,errno设置为EPIPE。

二、协同进程

UNIX系统过滤程序从标准输入读取数据,向标准输出写数据。几个过滤程序通常在shell管道中线性连接。当一个过滤程序既产生某个过滤程序的输入,又读取该过滤程序的输出时,它就变成了协同进程(coprocess)
在这里插入图片描述

三、FIFO(命名管道)

未命名管道只能在两个有亲缘关系的进程间使用,而FIFO没有此限制。FIFO是一种文件类型。通过stat结构的st_mode成员的编码可以知道文件是否是FIFO类型,可以用S_ISFIFO宏对此进行测试。

创建FIFO类似于创建文件:

#include <sys/stat.h>
int mkfifo(const char* path, mode_t mode);
int mkfifoat(int fd, const char* path, mode_t mode);
//成功,返回0;出错,返回-1

四、消息队列

消息队列是消息的链接表,存储在内核中,由消息队列标识符标识。每个队列都有一个msqid_ds结构与其相关联。此结构定义了队列的当前状态:

struct msqid_ds{
	struct ipc_perm  msg_perm;
	msgqnum_t        msg_qnum;
	msglen_t         msg_qbytes;
	pid_t			 msg_lspid; //pid of last msgsnd()
	pid_t			 msg_lrpid; //pid of last msgrcv()
	time_t 			 msg_stime; //last msgsnd() time
	time_t 			 msg_rtime; //last magrcv() time
	time_t 			 msg_ctime; //last change time
	...
};

msgget用于创建一个新队列或打开一个现有队列:

#include <sys/msg.h>
int msgget(key_t key, int flag);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值