C语言 NOTE34

系统编程之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; /* 分配给消息队列的数据段的最大值 */
};
发布了52 篇原创文章 · 获赞 2 · 访问量 1992

猜你喜欢

转载自blog.csdn.net/weixin_42191545/article/details/104196757