system V消息队列和信号量的学习
消息队列
IPC:看到同一份资源 维护成为一个队列
1. 消息队列提供了一种一个进程给另一个进程发送有类型数据块的方式
2. OS要对消息队列进行管理,先描述再组织
3. 两个进程通过同一个队列 => key ,来保证自己看到的是同一个消息队列
描述消息队列的结构体
把节点构建成有类型数据块
消息队列的调用接口
msgget
用于创建一个新的消息队列或者获取已存在的消息队列的标识符(ID)
msgget
的第二个参数 msgflg
用于控制操作行为和权限 。其中,IPC_CREAT
和 IPC_EXCL
是 msgflg
中可设置的标志位
msgctl
用于对已创建的消息队列执行多种控制操作,如获取 / 设置消息队列属性、删除消息队列等
用于描述消息队列属性的 msqid_ds
结构体定义
ipc_perm
结构体定义,用于存储进程间通信(IPC)对象(如消息队列、共享内存、信号量 )的权限和所有者相关信息
当程序不再需要某个消息队列时,可调用 msgctl 并传入 IPC_RMID 来释放系统资源,避免无用消息队列占用系统空间
IPC_STAT 是 msgctl 函数中 cmd 参数的一种取值
当 msgctl 函数的 cmd 参数设置为 IPC_STAT 时,函数会将与指定消息队列标识符 msqid 相关联的内核数据结构中的信息,复制到 buf 所指向的 msqid_ds 结构体中。通过这种方式,可以获取消息队列的各种属性,如消息队列的创建时间、所有者信息、消息数量、队列字节数等(这些信息存储在 msqid_ds 结构体的相应成员中 )
msgsnd
用于向指定的消息队列发送消息
msgrcv
用于从指定的消息队列接收消息
msgsz一般指的是正文的大小
msgbuf 结构体与 msgsnd 和 msgrcv 函数的第二个参数有关
第二个参数 msgp 是指向消息缓冲区的指针 ,这个缓冲区通常是用户自定义的 msgbuf 结构体,用来暂时存储要发送的消息
第二个参数 msgp 同样是指向消息缓冲区的指针 ,用于存储从消息队列接收到的消息,一般也是 msgbuf 结构体
伪代码:
comm.hpp
#define PROJID XXX
#define PATHNAME YYY
#define CLIENT 1
#define SERVER 2
//System V 消息队列通信里常用的消息缓冲区结构体
struct mssgbuf
{
long mtype;
char mtext[1000];
};
消息队列的生命周期也是随内核的
删除 ipcrm -q msqid
(消息队列标识符)
共享内存
看到同一份是通信的前提条件,如果没有保护机制,数据就不一致
怎么解决?
信号量,是一种具体的方案
数据不一致
1. 没有被保护起来的共享资源
2. 各自的代码,访问了这个没有被保护的公共资源
保护(约束)临界区的代码,即变相地保护临界资源
1. 多个进程能看到同一份公共资源:共享资源
2. 被保护起来的共享资源叫做临界资源
3. 涉及到互斥资源的程序段叫临界区;只允许一个执行流访问资源 --> 互斥 (我们联想atm机只允许一个人来认识)
4. 多个执行流,访问临界资源的时候具有一定的顺序性 --> 同步
对共享资源进行保护,本质是对访问共享资源的代码进行保护
锁本身也要被共享,谁来保护锁的安全?(申请锁的时候必须是原子的)
对临界区的保护 --> 任何时刻,只允许一个执行流访问资源
原子性 两态 ,即做或者不做
要么所有操作都完整、不间断地执行成功,要么所有操作都不执行
信号量
信号量是什么?
信号灯,本质是一个计数器,用来表明临界资源中资源数量的多少
我们类比电影院来理解
我们买票,票买到了这个位置就是我们的。这个买票本质是对电影院座位资源的预定
电影院放映厅就是一个临界资源(内部包含了很多子资源)。我们想访问临界资源就要先买票。
而卖票最怕的是
1.票卖多了
2.票号重复
信号量:计数器,描述的是临界资源中资源数量的多少。
所有进程访问临界资源中的一小块就必须先申请信号量。(本质是对资源的预定机制。资源就是我们的了,等我们随时去访问)
而一个电影放映厅那个空间就是共享内存,我们把共享内存按照不同的区域部分使用,可以实现让多个进程并发访问
避免:1.访问同一个位置2.放入过多的进程
信号量本身就是共享资源,不让别人过多进到共享资源
申请资源计数器就--,原子性 P操作
释放资源sem++,原子性 V操作
当一个线程或进程需要访问共享资源时,就需要先获取信号量(--);使用完资源后,再释放信号量(++)
信号量只有0或1两态的信号量叫做二元信号量(就是互斥)
即资源是整体使用的,就像ATM机的封闭使用
公共电影院的资源不是整体使用,有很多位置的,就是多元信号量 (多个进程并发访问不出问题)
信号量?
struct sem
{
//锁
//int count;
//task_struct *waitqueue;
}
信号量和通信的关系?
1.先访问信号量p,每个进程都得先看到同一个进程
2.不是传递数据,才是通信IPC,同步互斥也算
信号量接口
semget:创建或获取 System V 信号量集的系统调用函数
semctl:用于对信号量集进行多种操作,初始化、删除以及获取信号量的值等
信号量的初始值
SETVAL Set the semaphore value (semval) to arg.val for the semnum-th semaphore of the
set
struct XXXid_ds的结构体 --> key
ipcs -s
ipcrm -s XXX:移除(删除)系统中进程间通信(IPC)对象
semop :对 System V 信号量集进行操作的系统调用函数。它允许进程对信号量集中的一个或多个信号量进行原子操作,常用于进程间的同步和互斥
共享内存,消息队列,信号量 =>key区分唯一性
OS内,共享内存,消息队列,信号量,被当作了同一种资源
system V IPC主要包含三种不同的通信方式:消息队列、共享内存和信号量