朋友们、伙计们,我们又见面了,本期来给大家带来消息队列和信号量相关代码和知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!
C 语 言 专 栏:C语言:从入门到精通
数据结构专栏:数据结构
个 人 主 页 :stackY、
C + + 专 栏 :C++
Linux 专 栏 :Linux
目录
1. 消息队列(简单认识)
- 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
- 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
- 特性方面
- 消息队列生命周期随内核
读写方写入的数据都会按照数据块的方式链入队列中,那么读写方如何正确的读取或者写入自己的数据块呢?
每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值,读写方可以根据数据块的类型来进行分辨:
系统中不止有一个消息队列,可能会存在多个消息队列,所以操作系统也要把消息队列管理起来;先描述,再组织,所以消息队列 = 队列内容 + 队列属性
2.1 接口认识
① 创建队列
- msgget接口:
- 参数:
key值依旧使用ftok函数进行获取;
权限位:
IPC_CREAT:shm不存在就创建,存在就回去并返回;
IPC_EXCL:不单独使用,配合IPC_CREAT | IPC_EXCL使用,表示msg不存在就创建,存在就出错返回,保证了创建的消息队列都是全新的。
- 返回值:
成功返回一个非负整数,即该消息队列的标识码;失败返回-1
命令行输入 ipcs -q:查看消息队列;
命令行输入 ipcrm -q msgid:删除指定的消息队列
② 发送消息
- msgend接口:
- 参数:
msqid:向指定的消息队列中发送(由msgget接口的返回值获取)
msgp、msgsz:所要发送的内存及长度
msgflg:标志位
IPC_NOWAIT表示队列满不等待,返回EAGAIN错误;
0表示以阻塞的方式发送。
- 返回值:
成功返回0,失败返回-1
③ 接收消息
- msgrcv接口:
- 参数:
msqid:从指定的消息队列中接收信息
msgp、msgsz:接收缓冲区
msgtyp:指定类型
msgflg:标志位
若消息队列中没有消息,msgflag=IPC_NOWAIT,那么会返回EAGAIN
若消息队列中没有消息,msgflag=0,那么消息队列中的消息会阻塞
- 返回值:
成功返回实际放到接收缓冲区里去的字符个数;
失败,返回-1
④ 控制队列
- msgctl接口:
- 参数:
msqid:由msgget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)IPC_STAT:把msqid_as结构中的数据设置为共享内存的当前关联值
IPC_SET:在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值
IPC_RMID:删除消息队列
buf:指向一个保存着消息队列的模式状态和访问权限的数据结构
若要删除消息队列第二个参数设置IPC_RMID,第三个参数直接设置为nullptr。
消息队列的整个使用方法和共享内存都是一样的;
2. 信号量
进程间通信是让多个执行流看到公共资源,那么公共资源很有可能被多个执行流并发访问,此时就会产生数据不一致的问题,所以需要将公共资源保护起来,采用的是同步和互斥的方式:
- 互斥:任何一个时刻,只允许一个进程(执行流)访问公共资源,通常使用加锁的方式完成。
- 同步:多个执行流并发访问时,按照一定的顺序执行。
被保护起来的公共资源叫做临界资源;
访问该临界资源的代码叫做临界区;
维护临界资源起始就是维护临界区。
2.1 理解信号量
信号量的本质是一把计数器,表示公共资源的数目。
举个例子:
电影院有许多位置,我们买票其实给自己买到了一个位置,这些座位就是公共资源,我们每一个买票的人就是多个执行流,此时的信号量就是座位所剩个数,每当我们要买票,首先看还有没有剩余的座位,也就是先去查看信号量所剩资源数目,有人买走了一张票,那么信号量计数器就--,有人退票信号量计数器就++,所以我们买票时通过信号量就实现了对公共资源的一种预定机制。
信号量:
表示公共资源数目的计数器,每一个执行流要想访问公共资源,首先申请信号量资源,其实就是对信号量计数器--,只要成功,那么就完成了对公共资源的预定机制,如果失败了,那么执行流就会被挂起阻塞。
细节问题:
- 1. 如果公共资源只有一个,此时的信号量叫做二元信号量,只有两种状态(原子的),也就是一种互斥锁,完成互斥功能;
- 2. 每个进程要先能申请信号量,首先得看到同一个信号量资源,所以信号量资源也是由OS提供,并且系统中不止一个信号量,所以OS也要对信号量做管理操作;
- 3. 信号量的本质也是公共资源,所以他的内部操作一定是原子的;
- 4. 信号量要管理,首先要有描述信号量的结构体,该结构体中会存在一个阻塞队列,当一个进程申请信号量失败之后,就会被链入到该阻塞队列中等待。
2.2 接口认识
① 创建信号量
- semget接口:
- 参数:
nsems:表示定制的信号数量,通常情况下为1。
其余参数参考共享内存和消息队列
② 修改信号量
- semop接口:
- 参数:
semid:指定的信号量
sops:描述信号量的结构体
nsops:操作次数
- 返回值:
成功返回0,失败返回-1
③ 控制信号量
- semctl接口:
- 参数:
semid:信号量集标识符
semnum:某一个信号量
cmd:标志位
IPC_STAT:把semid_as结构中的数据设置为信号量的当前关联值
IPC_SET:在进程有足够权限的前提下,把信号量的当前关联值设置为semid_ds数据结构中给出的值
IPC_RMID:删除信号量
朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!