进程间通信
管道
- 父子进程之间不共享数据段和堆栈段,通过管道进行通信
- 管道是两个进程之间进行单项通信的机制,是一种半双工管道
- 管道只能用于具有亲缘关系的进程(父子进程和兄弟进程)
- 管道没有名字
- 管道的缓冲区大小受限制
- 管道传输的是无格式的字节流
- 两端进程向管道读写数据是通过创建管道时系统设置的文件描述符进行的,管道本质上也是一种文件
- 写数据每次都添加到管道缓冲区的末尾,读数据是从缓冲区的头部读出数据的
- 管道由函数
int pipe(int fd[2]);
函数创建,依赖头文件#include <unistd.h>
- 有名管道已FIFO的文件形式存在于文件系统中,即使访问该路径的进程不存在亲缘关系也可以通过FIFO相互通信
- 实现两个不相关进程之间的通信
- 该管道可以通过路径名指出,在文件系统中是可见的
- FIFO严格的遵守先进先出原则,从管道头部读出数据,将写操作的数据添加到末尾
1
2
3
4
5
6#include <sys/sypes.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
//pathname是路径名也就是创建后FIFO的名字,mode和open()函数中的mode参数
//如果路径已经存在则返回EEXIST错误
消息队列
- 用于运行于同一条机器上的进程间通信,在一个系统内核中用来保存消息的队列,在系统内核中以消息链表的形式出现的
创建消息队列或取得已经存在的消息队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27int msgget(key_t key, int msgflg);
//key是端口号,也可以通过ftok函数生成
//msgflg如果等于IPC_CREAT,如果没有该队列,则创建一个并返回一个标识符,如果已经存在则返回原标识符
//msgflg等于IPC_EXCL,如果没有该队列返回-1,如果已经存在返回0
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
//从队列中取用消息
//msqid是消息队列的标识码
//msgp是指向消息缓冲区的指针
//msgsz是消息的大小
//msgstp是从消息队列中读取的消息形态,如果值为0表示消息队列中的所有消息都会被读取
//msgflg用来指明核心程序在队列没有数据的情况下应该采取的行动
struct msgstru{
long mtype;
char mtext[512];
};
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//将数据放到消息队列中
int msgctl(int msgqid, int cmd, struct msqid_ds *buf);
//设置消息队列的属性
//对msgqid表示的消息队列执行cmd操作
//IPC_STAT来获取消息队列的msqid_ds数据结构,并保存到buf指定的地址空间
//IPC_SET设置消息队列的属性,要设置的属性存储在buf中
//IPC_RMID从内核中删除msqid标识的消息队列消息队列和有名管道有相似之处,也有优势:
- 消息队列可以用于独立发送和接收进程而存在,消除同步有名管道打开和关闭可能产生的困难
- 可以同时通过发送信息来避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法
- 接收程序可以通过消息类型有选择的接收数据
共享内存
1 | #include <sys/shm.h> |
信号量
1 | #include <sys/types.h> |
ipcs命令
ipcs -a
列出本用户相关的ipcs参数ipcs -q
列出进程中的消息队列ipcs -s
用于列出所有的信号量ipcs -m
用于列出所有共享内存信息ipcs -l
用于列出系统的险恶ipcs -t
列出最后的访问时间ipcs -u
列出当前的使用情况