1.信号量怎样实现同步互斥?
信号量并不是让进程间能够直接的发送字符串数据,而是通过自身计数器的性质,来完成进程之间的同步互斥(通过使用信号量来完成令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域,临界区域是指执行数据更新的代码需要独占式的执行,而信号量则是让一个临界区同一时间只有一个线程在访问他,即就是说信号量是用来协调进程对共享资源的访问的一种手段)
ps:信号量其实就是一个计数器
2.同步互斥
(1)互斥:有些资源不能进行共享的访问,需要互斥的访问来保证数据的完整性,进程间的这种关系为进程的互斥
(2)临界资源:需要进行互斥访问的资源就是临界资源
(3)临界区:某一区域的代码在进行数据更新时,只能被独占式的进行(涉及到临界资源的代码段就是临界区)
3.信号量
(1)信号量的使用场景
信号量可以使用在同步中也可以在异步中使用
互斥:P、V在同一进程
同步:P、V不在同一进程
(2)信号量值含义
S>0—>S表示现在有多少个资源可以使用
S<0—>|S|的值是现在等待进程的个数
S=0—>现在已经没有资源可用了,也没有进程在等待
ps:注意system V版本的信号量不会小于0,当可用资源的个数等于0时,就会阻塞,直到某个资源被释放,才会在进行相关操作
(3)P、V的含义
P—>P表示申请资源,此时可用资源的个数会减少一个
V—>V表示释放资源,此时可用资源的个数会增加一个
ps:注意区分pv量,pv量有时表示信号量,有时是某网站被用户在一天中总访问的次数,此时的PV是page view,简称pv
4.信号量结构体伪代码
struct semaphore
{
int value;
pointer_PCB queue;
}
5.P、V原语
(1)申请资源
P(s)
{
s.value=s.value--;//如果s<0那就会阻塞等待,直到有资源释放
if(s.value<0)
{
该进程状态置为等待状态
将该进程的PCB插入相应的等待队列s.queue
}
}
(2)释放资源
V(s)
{
s.value=value++;//只有value<=0,才会有等待队列,否则不会有等待队列,故当 value<=0,唤醒等待队列就好
if(s.value<=0)
{
唤醒相应等待队列s.queue中的一个等待队列
改变其状态为就绪状态
将其插入就绪队列
}
}
6.相关函数
(1)semget()
功能:创建和访问一个信号集
头文件:#include<sys/sem.h>
int semget(key_t key,int nsems,int semflag);
参数说明:
key:信号集的名字
ps:key是ftok()函数的返回值
nsems:信号集中信号量的个数
ps:此参数的值总是1
semflag:由9个权限构成
返回值:
成功:返回一个非负整数,此整数就是信号集的标识码
失败:返回-1