信号量的本质是一种数据操作锁,其本身不具有数据交换的能力,而是通过控制其他的通信资源(文件、外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据的互斥、同步等功能。
当请求一个信号量来表示资源时,进程需要读取信号量的值来判断资源是否可用。大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用。当进程不再使用一个信号量量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作均为原子操作,因为在信号量的创建及初始化上,不能保证操作均为原子性。
信号量的作用:
可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域(执行数据更新的代码需要独占式地执行),信号量可让一个临界区间同一时间只有一个线程在访问它。
信号量的工作原理:
(1)P(sv)操作:若sv的值大于0,则给sv的值减1;若它的值为0,就挂起该进程的执行;
(2) V(sv)操作:若有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1;
注意:P、V操作总是成对出现.
通常使用:
ipcs -s 查看信号量
ipcrm -s semid 删除信号量
信号量的创建及使用如下所示(以父子进程为例,申请二元信号量集,初始值设为1):
程序代码:
comm.h
comm.c
semop操作中:sembuf结构的sem_flg成员可以为0、IPC_NOWAIT、SEM_UNDO 。为SEM_UNDO时,它将使操作系统跟踪当前进程对这个信号量的修改情况,如果这个进程在没有释放该信号量的情况下终止,操作系统将自动释放该进程持有的资源。
若使用SEM_UNDO标志,则操作系统将自动释放该进程持有的信号量,从而使得另外一个进程可以继续工作。若没有这个标志,另外一个进程将P操作永远阻塞。
(1)子进程异常退出时,设置了SEM_UNDO
(2)子进程异常退出时,未设置时
(3)子进程未异常退出,父子进程均上锁时
server.c
对信号量的几点说明:
(1)信号量相当于描述临界资源的计数器,信号量必须先被申请;
(2)信号量本身也是一种临界资源,其P、V操作具有原子性,即要么被申请到,要么未被申请到,只有这两种可能;
(3)二元信号量相当于一把互斥锁;
(4)信号量属于进程通信范畴,仅能保证数据传输的安全性;
(5)信号量的生命周期为“随内核”,即必须用户手动删除;
(6)信号量自带同步与互斥机制;