信号量
- 信号量的本质是一种数据操作锁
- 信号量的本质是具有原子性的计数器
- 信号量本身只是一种外部资源的标识
- 信号量本身不具有数据交换的功能,而是通过控制其他的通信资源来实现进程间通信,在此过程中负责数据操作的互斥、同步等功能
原子性
- 两种状态
- 如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性
临界资源
- 不同进程共同看到的资源
- 一次仅允许一个进程使用的资源称为临界资源
临界区
- 共同访问临界资源的那份代码
同步
- 以特定顺序访问临界资源
互斥
- 任何时刻,只允许一个进程进入临界区访问临界资源并且属性是原子的
信号量的工作原理
- 信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv)
- P(sv):如果sv的值大于零,就给他减1;如果它的值为零,就挂起该进程的执行
- V(sv):如果有其他进程因等待sv而挂起,就让他恢复运行,如果没有进程因等待sv而挂起,就给他加1
举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行行了P(sv)操作,它将得到信号量,并可以进入入临界区,使sv减1。而第二个进程将被阻止进入临界区,因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。
函数
-原型: int semget(key_t key, int nsems, int semflg)返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1
errno=EACCESS(没有权限)
EEXIST(信号量集已经存在,无法创建)
EIDRM(信号量集已经删除)
ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
ENOMEM(没有足够的内存创建新的信号量集)
ENOSPC(超出限制)
参数key系统调用semget()的第一个参数是关键字值(一般是由系统调用ftok()返回的)。系统内核将此值和系统中存在的其他的信号量集的关键字值进行比较。
参数semflg中的相关内容:如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识符,要么返回系统中已经存在的信号量集的标识符。
如果IPC_EXCL和IPC_CREAT一同使用,则要么返回新创建的信号量集的标识符,要么返回-1。
IPC_EXCL单独使用没有意义。
参数nsems指出了一个新的信号量集中应该创建的信号量的个数。
- 原型:int semctl(int semid, int semnum, int cmd, …)
函数说明:得到一个信号量集标识符或创建一个信号量集对象并返回信号量集标识符
参数:
semid:信号量集标识符
semnum:信号量集数组上的下标,表示某一个信号量
cmd: IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
IPC_RMID将信号量集从内存中删除。
GETALL用于读取信号量集中的所有信号量的值。
GETNCNT返回正在等待资源的进程数目。
GETPID返回最后一个执行semop操作的进程的PID。
GETVAL返回信号量集中的一个单个的信号量的值。
GETZCNT返回这在等待完全空闲的资源的进程数目。
SETALL设置信号量集中的所