- 参数:
msqid
为消息队列的标识符,msgp
为消息缓冲区指针,msgsz
为消息长度,msgtyp
为消息类型,msgflg
为接收标志。 - 返回值:成功时返回接收到的消息数据的长度,失败时返回-1并设置
errno
。
3.System V 信号量
3.1概念
- 信号量本质:
- 信号量通常被用来保护公共资源,确保多个进程或线程能够有序地访问和使用这些资源
- 信号量是一个整型变量,通常用于控制对共享资源的访问。信号量的值可以表示可用资源的数量或者某个资源的占用情况
- 信号量:信号量本质是一个计数器,描述临界资源数量的计数器
为什么不能直接用一个int来进行呢?
无法在进程间共享 而且一个int
- -
不是原子的 - 信号量:公共资源中,对局部性资源进行预定的机制。可以被用于对局部性资源进行预定,实现对资源的合理分配和控制
- 信号量是让不同的进程看到同一个计数器资源,而进程间通信是让不同的进程看到一份资源。所以信号量也属于进程间通信
进程申请信号量一旦成功:就一定有这个进程的资源了(相当于去看电影买票,一定有我们的座位了,而且别人也买不了这个座位) 当我们释放信号量后,这份资源才能给别人(看完电影后,这个座位才能接着被下一个买) 申请信号量和释放信号量来保护临界资源, 是大家都要遵守的规则(我们程序员)
- 所有的进程,访问临界资源,都必须先申请信号量, 所有进程都得先看到同一个信号量
==>
信号量本身就是共享资源 - 信号量操作: 那谁来保护信号量呢? 通过使用原子的PV操作来保障
- P操作(等待操作):当进程需要访问共享资源时,首先执行P操作,即尝试获取信号量。如果信号量的值大于0,则将信号量的值减1,表示资源已被占用,进程可以继续执行;如果信号量的值为0,则表示资源已被占用,进程需要等待。(允许申请多个信号量)
- V操作(释放操作):当进程使用完共享资源后,执行V操作,即释放信号量。释放信号量会增加信号量的值,表示资源已经释放,其他进程可以继续访问。
3.2周边知识
- 互斥和同步:
- 互斥:指的是在访问共享资源时,任何时刻只允许一个执行流访问,其他执行流需要等待。这样可以避免多个执行流同时修改共享资源导致数据不一致。互斥是通过使用锁或信号量等机制来实现的。(任何时候都只有一个人能访问,当信号量为1——只有一个整体资源时,不就是互斥吗)
- 同步:指的是在访问共享资源时,具有一定的顺序性,确保多个执行流按照特定的顺序访问资源。同步可以通过信号量、条件变量等机制来实现,以确保执行流之间的协调和顺序性。
- 临界资源和临界区:
- 临界资源:是指被保护起来的,任何时刻只允许一个执行流访问的公共资源。访问临界资源的代码段被称为临界区。
- 临界区:是指访问临界资源的代码段,程序员需要在临界区内使用互斥和同步机制来确保对临界资源的安全访问。
- 原子性:指的是操作对象的操作是不可分割的,要么整个操作完成,要么没有开始。在多线程或多进程环境中,保证操作的原子性是非常重要的,可以通过锁或原子操作等机制来实现。
- 保护临界区的本质:程序员需要保护临界区,确保在任何时刻只有一个执行流可以访问临界资源,避免数据竞争和不一致性。这通常通过使用锁、信号量或其他同步机制来实现。
4.内核中
内核中,所有的描述管理IPC资源的结构体,第一个成员大家都一样 kern_ipc_perm。我们可以用指针数组来进行管理
在内核中,对IPC资源的管理也是转变为对数组的增删查改
类型不同我们怎么解决呢?——直接强转
- (msg_ queue*)ipc0> q _time;
- (sem_array)ipc1->q_time;
- (shmid kernel)ipc2-> 。。。
那怎么知道是什么类型呢?
kern_ipc_perm里有一个有个mode变量,能来表示类型
代码语言:javascript复制#define IPC TYPE SHM Ox1
#define IPC TYPE MSG (0x1<<1)
#define IPC TYPE SEM(0x1 << 2)//定义这三个宏后
shmid kernel* (kern ipc_perm* p)
{
if (p->mode & IPC TYPE SHM)
{
return (shmid kernel)ipc
}
else if (p->mode & IPC TYPE MSG)
{
///
}
else
{
///
}
}
好啦,我也是结束了实训,才到家!!!
感谢大家的支持