1 、概念: 类似于计数器,记录资源数量,一个资源只能被一个进程使用。
临界资源:同一时刻只能被一个进程访问的资源。
临界区:操作临界资源的代码区域原子操作:不能被中断的操作,操作一旦开始执行,就必须执行结束,中途不能被任何原因打断。
2 、作用:
进程同步执行:一个进程的执行需要另一个进程提供一定的条件,
信号量就是完成进程同步控制的!
3、内核对象和键值对
内核对象: 系统内核中,创建、控制、销毁的一个对象(变量)
键值对: key--val
4、信号量的命令操作
查看: ipcs -s删除: ipcrm -s id
5、信号量的操作使用的函数:
创建或者获取: semget();
int semget(key_t key,int num_sems,int sem_flags);
第一个参数key是整数值,可以随机设置。不相关的进程可以通过它访问同一个信号量。
注意:有一个特殊的信号量键值IPC_PRIVATE,它的作用是创建一个只有创建者进程才能风问得信号量,但不常用。
第二个参数是指定需要的信号量数目;(大多时候为1个,当为多个时,在后序对信号量的操作时,要注意操作的信号量是第几个)
第三个参数sem_flags参数是一组标志,它的作用是设置对该信号量的权限,或者和值IPC_CREATE做按位或操作,来创建一个新的信号量。
semgt函数成功时返回一个正数值,即后序所需的信号标志符,失败返回-1。
初始化: semctl();
int semctl(int sem_id,int sem_num,int command, ...);
此函数是可变参函数,第四个参数与第三个参数有关,在某些环境下使用时可忽略;
第一个参数sem_id是由semget返回的信号量标识符;
第二个参数sem_num是需要进行操作的信号量数组下标;(如果信号量的个数大于一个,在内存中是按数组的方式排列的)
第三个参数command是将要采取的动作,它可以设置许多不同的值,常用的有两个:
SETVAL:用来把信号量初始化一个已知的值,这个值通过union semun中的val成员设置,在某些Linux系统中,这个联合体没有被系统定义,需要自己定义。
联合体的结构:union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
}
IPC_RMID:用于删除一个已经无需继续使用的信号量。主要用于删除信号量。
semctl函数的返回值根据command的参数不同而返回不同的值,对于SETVAL和IPC_RMID 成功返回0,失败返回-1.
P 操作: semop(); 当信号量值<=0 时, 会阻塞运行
V操作:semop();
int semop(int sem_id,struct sembuf *sem_ops,size_t sem_num_ops);
第二个参数sem_ops是一个指向结构数组的指针,每个数组元素包括:
struct sembuf{
short sem_num; //信号量编号
short sem_op; //信号量在一次操作中需要改变的数值(可以用一个非1的数值改变信号量),通常使用-1,即p操作,等待信号 量变为可用; +1,v操作,发送消息表示信号量现在可用;
short sem_flg; //通常被设置为SEM_UNDO,
};