IO进程 day08
11. 进程间的通信机制
11.6. 信号灯集
概念
信号灯,又叫信号量,是不同进程或同一个进程的不同线程间的同步机制
System V信号灯集是一个或者多个信号灯的集合。其中每一个都是单独的信号灯,Posix信号灯是单个的计数信号灯
通过信号灯可以同步共享内存的同步
步骤
- 创建key——ftok
- 创建或打开信号灯集——semget
- 初始化信号灯集——semctl
- PV操作——semop
- 删除信号灯——semctl
semget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
功能:创建信号灯集
参数:
key_t key
key值
int nsems
信号灯集里的信号灯的数目
int semflg
信号灯集的访问权限,一般为IPC_CREAT | IPC_EXCL | 0666
返回值:成功返回信号灯集ID,失败返回EOF
semctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl ( int semid, int semnum,int cmd,…/*union semun arg*/);
功能:操作信号灯集
参数:
int semid
信号灯集ID
int semnum
要操作的信号灯的编号
int cmd
对信号灯的操作
宏名 | 操作 |
---|---|
GETVAL | 获得信号灯的值 |
IPC_RMID | 从系统中删除信号灯集 |
SETVAL | 设置信号灯的值 |
union semun arg
信号灯的共用体,需要自己定义,只有在第三个参数为SETVAL
时,才需要输入该参数
返回值:
成功返回0,当第三个参数为GETVAL
时,返回值是信号灯的值
失败返回EOF;
注意
共用体如下
union semun
{
int val; // 信号灯的初值
// struct semid_ds *buf;
// unsigned short *array;
// struct seminfo *__buf;
}
semop
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop ( int semid, struct sembuf *opsptr, size_t nops);
功能:对信号灯集中的信号量进行申请和释放
参数:
int semid
信号灯集ID
struct sembuf *opsptr
操作方式,需要&结构体
size_t nops
需要操作的信号灯个数:1个
返回值:成功返回0,失败返回EOF
注意
操作的结构体如下
struct sembuf
{
short sem_num; // 需要操作的信号灯编号
short sem_op; // 对信号灯的操作,+1释放V,-1申请P
short sem_flg; // 0:阻塞
}
初始化和操作信号灯函数封装
void seminit (int semid, int num, int val)
{
union semun sem;
sem.val = val;
semctl(semid, num, SETVAL, sem);
}
void sem_op (int semid, int op, int num)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
semop(semid, &buf, 1);
}
命令
ipcs -s #查看信号灯集
ipcrm -s [semid] #删除信号灯集
11.7. 消息队列
特点
- 消息队列就是一个消息列表
- 消息队列可以实现消息的添加,读取等操作
- 消息队列按照类型来收发消息
- 消息队列在Linux系统中有大小限制
类别 | 大小限制 |
---|---|
消息队列个数 | 16个 |
消息队列总容量 | 16k |
每个消息的内容 | 8k |
步骤
- 创建key——ftok
- 创建或打开消息队列——msgget
- 添加消息——msgsnd
- 读取消息——msgrcv
- 删除消息队列——msgctl
msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int flag);
功能:创建消息队列
参数:
key_t key
key值
int flag
访问权限,一般为IPC_CREAT | IPC_EXCL | 0666
返回值:成功返回msgid,失败返回EOF
msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t size, int flag);
功能:添加消息
参数:
int msqid
消息队列的ID
const void *msgp
指向消息的指针
size_t size
发送消息正文的字节数
int flag
IPC_NOWAIT
消息没有发送完成函数也会立即返回
0
:直到发送完成函数才返回
返回值:成功返回0,失败返回EOF
注意
- 消息的结构如下,需要自行定义
struct msgbuf
{
long mtype; //消息类型
char mtext; // 消息正文,正文的类型不限
}
- 变量
mtype
必须是long
类型的,而且必须在第一个,且大于0 - 参数:
size_t size
是正文的大小,不算mtype
直接用结构体大小-mtype
的大小
msgrcv
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag);
功能:读取消息
参数:
int msqid
消息队列的ID
void *msgp
指向消息的指针
size_t size
发送消息正文的字节数
long msgtype
接收消息队列中类型为msgtype
的消息
int flag
IPC_NOWAIT
没有消息立即返回ENOMSG
0
:没有消息就一直阻塞
返回值:成功返回收到的消息的长度,失败返回EOF
msgctl
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
功能:删除消息队列
参数:
int msgqid
消息队列的ID
int cmd
写入IPC_RMID
:从系统中删除消息队列
struct msqid_ds *buf
消息队列缓冲区,一般为NULL
返回值:成功返回0,失败返回EOF
命令
ipcs -q #查看创建的消息队列
ipcrm -q [msqid] #删除消息队列