信号量

在设备驱动程序中,信号量是解决并发控制的重要工具。当多个线程访问共享资源时,信号量能防止竞态条件。Linux内核提供sema_init、DECLARE_MUTEX等函数初始化信号量,并通过down、down_interruptible、down_trylock获取信号量,以及用up释放信号量。信号量适用于长时间持有,只在进程上下文使用,而自旋锁常用于中断处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



【设备驱动程序中的并发控制】

在驱动程序中,当多个线程同时访问像全局变量这样的共享资源时,会引发竞态,需要对共享资源进行控制。Linux内核中解决并发控制的最常用方法是信号量与自旋锁。信号量是一种睡眠锁,如果有一个任务试图获得一个已经被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠,这时候处理器获得自由去执行其他代码。当持有信号量的进程释放信号量之后,在等待队列中的一个任务将被唤醒,从而获得这个信号量;信号量适合于保持时间较长的情况,只能在进程上下文来使用,不能再中断上下文来使用。自旋锁是专为多处理器并发控制而引入的一种锁,它在内核中大量应用于中断处理部分,但对于大多只有单处理器的嵌入式系统来说,中断处理中的并发控制可采用关闭中断的方式,不需要自旋锁。

Linux内核在include/asm中定义了一个semaphore结构体,它就是信号量。信号量可以定义如下:

Struct semaphore sem;   //定义一个名为sem的信号量。

 

【信号量的初始化】

信号的初始化有以下几个函数可供使用:

  1. void sema_init(struct semaphore *sem,int val)

    该函数用于初始化设置信号量的初值,它设置信号量sem的值为val

  2. DECLARE_MUTEX(name)

    该宏声明一个信号量name并初始化它的值为0,即声明一个互斥锁。

  3. DECLARE_MUTEX_LOCKED(name)

    该宏声明一个互斥锁name,但把它的初始值设置为0,即锁在创建时就处在已锁状态。因此对于这种锁,一般是先释放后获得的。

  4. void init_MUTEX(struct semaphore *sem)

    该函数用于初始化一个互斥锁,即它把信号量sem的值设置为1

  5. void init_MUTEX_LOCKED(struct semaphore *sem)

    该函数也用于初始一个互斥锁,但它把信号量sem设置为0,即一开始就是已锁状态。

     

    【信号量的申请】

    信号量的申请有以下几个函数的可供选择:

  1. void down(struct semaphore*sem)

    该函数用于获得信号量sem,它会导致睡眠,因此不能中断处理程序(包括硬件中断和软件中断)中使用该函数。该函数将把sem值减1,如果信号量sem的值非负,就直接返回,否则调用者将被挂起,直到别的任务释放该信号量才能继续运行。

  2. int down_interruptible(struct semaphore *sem)

    该函数功能与down相同类似,不同之处为,down不会被信号(signal)打断,但down_interruptible()能被信号打断。因此该函数有返回值来区分是正常返回还是被信号中断,如果返回0,表示获得信号量正常返回,如果信号被打断,返回-EINTR

  3. int down_trylock(struct semaphore *sem)

    该函数试着获得信号量sem,如果能够立刻获得,它就获得该信号并且返回0,否则,表示不能获得信号量sem,返回值为非0值。因此他不会导致调用者睡眠,可以在中断处理程序中使用。

     

    【信号的释放】

    信号的释放函数如下:

    void up(struct semaphore*sem);

    该函数释放信号量sem,即把sem的值加1,如果sem的值为非正数,表明有任务等待该信号,因此唤醒这些等待者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值