系统编程之posix有名信号量
1. posix有名信号量用到了线程库 pthread ,所以在编译时是需加上-lpthread
2. 创建的有名信号量在 /run/shm 或者/dev/shm文件夹中
如何操作posix有名信号量?
1.创建信号量
功能 创建、打开一个 POSIX 有名信号量
- 头文件
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h> - 函数原型
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);
参数 | Value |
---|---|
name | 信号量的名字,必须以正斜杠 ”/” 开头 |
oflag | 创建模式如下: |
O_CREATE | 如果该名字对应的信号量不存在,则创建 |
O_EXCL | 如果该名字对应的信号量已存在,则报错 |
mode | 八进制读写权限,比如 0666 |
value | 初始值 |
如果信号量已存在,参数三与参数四直接无效
-
返回值
成功 信号量的地址
失败 SEM_FAILED
备注 跟 open( )类似,当 oflag 中包含 O_CREATE 时,该函数必须提供后两个参数
2.对信号量进行PV操作
功能 对 POSIX 有名信号量进行 P、V 操作
- 头文件
#include <semaphore.h> - 函数原型
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem)
- 参数
sem 信号量指针 - 返回值
成功 0
失败 -1
3.对信号量进行关闭操作
- 头文件
#include <semaphore.h> - 函数原型
int sem_close(sem_t *sem); ---->关闭信号量
int sem_unlink(const char *name); ---->删除信号量
参数 | Value |
---|---|
sem | 信号量指针 |
name | 信号量名字 |
- 返回值
成功 0
失败 -1
系统编程之消息队列
使用ipcs -q查看系统消息队列
如何使用消息队列?
1.创建键值 ftok()
2.创建消息队列
功能 获取消息队列的 ID
-
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> -
函数原型
int msgget(key_t key, int msgflg);
参数 | Value |
---|---|
key | 消息队列的键值 |
msgflg | |
IPC_CREAT | 如果 key 对应的 MSG 不存在,则创建该对象 |
IPC_EXCL | 如果该 key 对应的 MSG 已经存在,则报错 |
mode | MSG 的访问权限(八进制,如 0644) |
- 返回值
成功 该消息队列的 ID
失败 -1
备注 如果 key 指定为为 IPC_PRIVATE,则会自动产生一个随机未用的新键值
3.发送、接收消息
- 头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> - 函数原型
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp,size_t msgsz, long msgtyp, int msgflg);
参数 | Value |
---|---|
msqid | 发送、接收消息的消息队列 ID |
msgp | 要发送的数据、要接收的数据的存储区域指针 |
msgsz | 要发送的数据、要接收的数据的大小 |
msgtyp | 这是 msgrcv 独有的参数,代表要接收的消息的标识 |
msgflg | |
IPC_NOWAIT | 非阻塞读出、写入消息 接受模式,一般写0 |
MSG_EXCEPT | 读取标识不等于 msgtyp 的第一个消息 |
MSG_NOERROR | 消息尺寸比 msgsz 大时,截断消息而不报错 |
- 返回值
成功
msgsnd( ) 0
msgrcv( ) 真正读取的字节数
失败 -1
发送消息时,消息必须被组织成以下形式:
struct msgbuf
{
long mtype; // 消息的标识
char mtext[1]; // 消息的正文
};
4.设置或者获取消息队列的相关属性
-
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> -
函数原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数 | Value |
---|---|
msqid | 消息队列 ID |
cmd | |
IPC_STAT | 获取该 MSG 的信息,储存在结构体 msqid_ds 中 |
IPC_SET | 设置该 MSG 的信息,储存在结构体 msqid_ds |
IPC_RMID | 立即删除该 MSG,并且唤醒所有阻塞在该 MSG 上的进程,同时忽略第三个参数 |
IPC_INFO | 获得关于当前系统中 MSG 的限制值信息 |
MSG_INFO | 获得关于当前系统中 MSG 的相关资源消耗信息 |
MSG_STAT | 同 IPC_STAT,但 msgid 为该消息队列在内核中记录所有消息队列信息的数组的下标,因此通过迭代所有的下标可以获得系统中所有消息队列的相关信息 |
buf | 相关信息结构体缓冲区 |
- 返回值
成功 | Value |
---|---|
IPC_STAT | 0 |
IPC_SET | 0 |
IPC_RMID | 0 |
IPC_INFO | 内核中记录所有消息队列信息的数组的下标最大值 |
MSG_INFO | |
MSG_STAT | 返回消息队列的 ID |
失败 | -1 |
1.IPC_STAT 获得的属性信息被存放在以下结构体中:
struct msqid_ds
{
struct ipc_perm msg_perm; /* 权限相关信息 */
time_t msg_stime; /* 最后一次发送消息的时间 */
time_t msg_rtime; /* 最后一次接收消息的时间 */
time_t msg_ctime; /* 最后一次状态变更的时间 */
unsigned long __msg_cbytes; /* 当前消息队列中的数据尺寸 */
msgqnum_t msg_qnum; /* 当前消息队列中的消息个数 */
msglen_t msg_qbytes; /* 消息队列的最大数据尺寸 */
pid_t msg_lspid; /* 最后一个发送消息的进程 PID */
pid_t msg_lrpid; /* 最后一个接收消息的进程 PID */
};
其中,权限相关的信息用如下结构体来表示:
struct ipc_perm
{
key_t __key; /* 当前消息队列的键值 key */
uid_t uid; /* 当前消息队列所有者的有效 UID */
gid_t gid; /* 当前消息队列所有者的有效 GID */
uid_t cuid; /* 当前消息队列创建者的有效 UID */
gid_t cgid; /* 当前消息队列创建者的有效 GID */
unsigned short mode; /* 消息队列的读写权限 */
unsigned short __seq; /* 序列号 */
};
2.当使用 IPC_INFO 时,需要定义一个如下结构体来获取系统关于消息队列的限制值信息,并且将这个结构体指针强制类型转化为第三个参数的类型。
struct msginfo
{
int msgpool; /* 系统消息总尺寸(千字节为单位)最大值 */
int msgmap; /* 系统消息个数最大值 */
int msgmax; /* 系统单个消息尺寸最大值 */
int msgmnb; /* 写入消息队列字节数最大值 */
int msgmni; /* 系统消息队列个数最大值 */
int msgssz; /* 消息段尺寸 */
unsigned short int msgseg; /* 分配给消息队列的数据段的最大值 */
};