信号量的定义及原理
原子操作:不可中断的一个或者一系列操作,即要么做要么不做
临界资源: 各进程采取互斥的方式,实现共享的资源称作临界资源。一次只能被一个进程使用
PV操作:P用于等待,V用于发送信号
P(s):s如果大于0就给减一,如果等于零,则挂起该进程的执行
V(s):如果有其他进程因等待s而被挂起,就让它恢复运行,如果没有进程因等待s而挂起,就给它加1
信号量的定义
为了防止出现因多个进程同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
信号量的原理
1. 测试控制该资源的信号量;
2. 若信号量的值为正,则进程可以使用该资源,进程的信号量值减1,表示一个资源被使用;
3. 若此信号量为0,则进程进入休眠,直到该信号量值大于0;
4. 当进程不再使用一个由一个信号控制的共享资源时,该信号量加1,如果有进程正在休眠等待该信号量,则该进程会被唤醒。
信号量的使用
Semget函数
#include<sys/sem.h>
int semget(key_t key,int num_sems,int sem_falgs);
功能;创建一个新的信号量或者取得一个已有信号量的键;
参数:
key:整数值,不相关的进程可以通过他访问同一个信号量。程序对所有信号量的访问都是间接的,他先提供一个键,再有系统生成一个相应的信号量标识符。只有semget函数才可以直接使用信号量的键,所有其他信号量函数都是使用semget函数返回的信号量标识符。如果多个程序使用相同的key值,key将负责协调工作。
num_sems:指定需要的信号数目,他几乎总是取值为1.。
sem_falgs:一组标志,他与open函数的标志非常相似,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。
semget函数成功返回一个正数(非零),他就是其他信号量函数要用到的信号量标识符。失败返回-1
Semop函数
#include<sys/sem.h>
int semop(int sem_id,struct*sem_ops,size_t num_sem_ops)
功能:用于改变信号量的值
参数:sem_id:信号量编码
sem_ops:表示一个由sembuf结构表示的信号量操作数组;
num_sem_ops:规定该数组中操作的数量。
返回值:成功返回0,失败返回-1。
Semctl函数
#include<sys/sem.h>
int semctl(int sem_id ,int sem_num,int command....);
功能:直接控制信号量的信息
参数:sem_id:信号量标识符;
sem_num:信号量的值;
command:通常是下面两个值中的其中一个:
SETVAL:用来把信号量初始化为一个已知的值。p 这个值通过union semun中的val成员设置,其作用是在信号量第一次使用前对它进行设置;
IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。
返回值:成功返回0,失败返回-1。