信号量的本质是一种数据操作锁,它本⾝身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。当请求一个使⽤用信号量来表⽰示的资源时,进程需要先读取信号量的值来判断资源是否可 用。大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直⾄至资源可用。 当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减 操作均为原子操作,这是由于信号量主要的作⽤用是维护资源的互斥或多进程的同步访问。 而在信号量的创建及初始化上,不能保证操作均为原子性。
为什么要使⽤用信号量?
为了防⽌止出现因多个程序同时访问一个共享资源⽽而引发的一系列问题,我们需要一种⽅方法, 它可以通过⽣生成并使⽤用令牌来授权,在任⼀时刻只能有一个执⾏行线程访问代码的临界区域。 临界区域是指执⾏行数据更新的代码需要独占式地执⾏。而信号量就可以提供这样的一种访 问机制,让一个临界区同一时间只有一个线程在访问它, 也就是说信号量是⽤用来调协进程 对共享资源的访问的。其中共享内存的使⽤用就要⽤用到信号量。
信号量的工作原理
由于信号量只能进⾏行两种操作等待和发送信号,即P(sv)和V(sv),他们的⾏行为是这样的:
(1) P(sv):如果sv的值⼤大于零,就给它减1;如果它的值为零,就挂起该进程的执⾏
(2) V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运⾏,如果没有进程因等待sv⽽挂起,就给它加1.
Linux的信号量机制
Linux提供了一组精心设计的信号量接口来对信号量进⾏行操作,它们不只是针对二进制信号 量,下面将会对这些函数进⾏行介绍,但请注意,这些函数都是⽤用来对成组的信号量值进行操作的。它们声明在头文件sys/sem.h中。
(1)创建信号量集(semget):
函数原型:
int semget(int semid, int senmnum, int cmd, …);
信号量集被建立的情况有两种:
(1).如果键的值是IPC_PRIVATE。
(2).或者键的值不是IPC_PRIVATE,并且键所对应的信号量集不存在,同时标志中指定IPC_CREAT。
当调用semget创建一个信号量时,他的相应的semid_ds结构被初始化。ipc_perm中各个量被设置为相应值:
sem_nsems被设置为nsems所示的值;
sem_otime被设置为0;
sem_ctime被设置为当前时间
用法:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
参数:
key:所创建或打开信号量集的键值。
nsems:创建的信号量集中的信号量的个数,该参数只在创建信号量集时有效。
semflg:调用函数的操作类型,也可用于设置信号量集的访问权限,两者通过or表示
sem_flags是一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC_CREAT || IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。
返回值说明:
如果成功,则返回信号量集的IPC标识符。
如果失败,则返回-1,errno被设定成以下的某个值
EACCES:没有访问该信号量集的权限
EEXIST:信号量集已经存在,无法创建
EINVAL:参数nsems的值小于0或者大于该信号量集的限制;或者是该key关联的信号量集已存在,并且nsems
大于该信号量集的信号量数
ENOENT:信号量集不存在,同时没有使用IPC_CREAT
ENOMEM :没有足够的内存创建新的信号量集
ENOSPC:超出系统
信号量是Linux中实现进程间通信的重要工具,用于控制对共享资源的访问,防止并发问题。它通过P和V操作实现资源的互斥与同步,确保临界区的线程安全。Linux提供了semget、semctl和semop等函数来创建、管理和操作信号量,包括信号量集的创建、初始化、摧毁,以及信号量值的获取和设置。在实际应用中,使用信号量能够有效地避免死锁现象,特别是在处理多个进程竞争资源的场景下。
最低0.47元/天 解锁文章
335

被折叠的 条评论
为什么被折叠?



