Linux通信System V:消息队列 & 信号量
- 一、信号量概念
- 二、信号量意义
- 三、操作系统如何管理ipc资源(2.36版本)
- 四、如何对信号量资源进行管理
一、信号量概念
信号量本质上就是计数器,用来保护共享资源。多个进程在进行通信时,前提需要看到同一份共享资源。但多个进程对公共资源并发访问时,通常会伴随着数据不一致问题。我们。一般采用同步和异步机制对公共资源进行保护!!其中被保护的资源被称为临界资源;访问该临界资源的代码称为临界区!!
- 同步:任何时候只运行一个执行流(进程)访问公共资源,通过加锁完成!
- 异步:多个执行流执行的时候,按照一定的顺序执行。
- 原子性:只有2态,要么做,要么不做。
- 被保护的公共资源被称为公共资源,访问该公共资源的代码称为临界区。
二、信号量意义
首先,我们先来想一个问题:当我们买票看电影时,座位是购买票后就属于你,还是只有当你坐在那个位置才属于你?显然,当我们买完票后,票上显示的座位就属于你。电影院是公共资源,而买票的行为本质上是对公共资源(作为)的预定!!
同理,信号量本质上就是一把表示公共资源数目的计数器。在计算机中,公共资源可以被分为多个部分,而信号量表示资源数目的计数器。当一个执行流想要访问公共资源时,不因该直接让其访问,否则会导致数据不一致问题!(例如:多个进程通过一块公共资源进程通信时,当进程A在向公共资源中写入数据但还未写完时,如果此时其他进程此时读取公共资源中的数据,可能会导致数据被覆盖,最后可能导致所有进程的数据都错误失效!!)
所以当执行流想要访问公共资源时,因该让其先申请信号量资源,也就是让计数器减1。一旦申请成功就完成公共资源的预定,可以访问随时访问公共资源。否则信号量申请失败,执行流就要被挂起阻塞!!
三、操作系统如何管理ipc资源(2.36版本)
下面我们先来看看消息队列和共享内存结构体中都维护了哪些信息!
【消息队列】:
【公共内存】:
我们发现两种ipc资源结构体中的首元素都是struct ipc_perm
类型,即使ipc种类不同,但是struct ipc_perm
类型结构体中保存的数据却全部一样!!而在也是OS管理不同ipc资源的核心!!
原因在于在系统层面上,系统可以找到一个名为ipc_ids
结构体,在该结构体中存在一个指针*entires
。该指针指向一个柔性数组。该柔性数组首元素保存ipc资源个数,而1 ~ n-1保存的是每个一ipc资源首元素地址。也就是上面我们所看到的struct ipc_perm
结构体,具体如下:
struct ipc_perm {
key_t __key; /* Key supplied to shmget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions + SHM_DEST and
SHM_LOCKED flags */
unsigned short __seq; /* Sequence number */
};
当操作系统需要访问不同ipc资源时,我们已经在柔性数组中得到了ipc资源的首元素地址,此时我们只需将其强转为特定ipc类型即可!!
即使ipc资源类型各异,但我们将所有ipc资源的首元素struct ipc_perm
结构体保存到柔性数组。让操作系统以统一的视角看待所有的ipc资源,从而实现对不同ipc资源的统一管理!
四、如何对信号量资源进行管理
访问共享资源时,首先要申请信号量资源。这也意味访问同一块公共资源的进程需要看到同一份信号量资源,而该资源只能由OS申请,被添加到ipc体系!
信号量是用来保护公共资源的,但多个进程需要看到同一份信号量资源,即信号量资源本身也是公共资源。那谁来保护信号量资源呢?
所以在OS中,信号量资源被设计成原子的。即任意时刻,只运行一个执行流访问信号资源。信号量资源的申请和释放本质上是计数器的++和–。其中申请信号量资源被称为P策略
,释放信号量资源被称为V策略
。
既然信号量资源是一种ipc资源,并且操作系统中存在多个信号量资源。操作系统需要对信号量资源进行管理,先组织,在描述!对于单个信号量资源,OS中会维护下面这样一个结构体进行描述:(暂时简单理解如下)
struct sem
{
int count;//信号量资源个数
task_struct *wait_queue;//等待访问该公共资源的进程队列
}