php 自旋锁,Linux内核驱动之自旋锁

自旋锁概念上简单.一个自旋锁是一个互斥设备,只能有2个值:"上锁"和"解锁".它常常实现为一个整数值中的一个单个位.想获取一个特殊锁的代码测试相关的位.如果锁是可用的,这个"上锁"位被置位并且代码继续进入临界区.相反,如果这个锁已经被别人获得,代码进入一个紧凑的循环中反复检查这个锁,直到它变为可用.这个循环就是自旋锁的"自旋"部分.

自旋锁API简介

自旋锁原语要求的包含文件是.一个实际的锁有类型spinlock_t.象任何其他数据结构,一个 自旋锁必须初始化.这个初始化可以在编译时完成,如下:

spinlock_t my_lock = SPIN_LOCK_UNLOCKED;

或者在运行时使用:

void spin_lock_init(spinlock_t *lock);

在进入一个临界区前,你的代码必须获得需要的lock ,用:

void spin_lock(spinlock_t *lock);

注意所有的自旋锁等待是,由于它们的特性,不可中断的.一旦你调用spin_lock,你将自旋直到锁变为可用.

为释放一个你已获得的锁,传递它给:

void spin_unlock(spinlock_t *lock);

其他参考内容:

自旋锁函数

我们已经看到2个函数, spin_lock和spin_unlock,可以操作自旋锁.有其他几个函数,然而,有类似的名子和用途.我们现在会展示全套.这个讨论将带我们到一个我们无法在几章内适当涵盖的地方;自旋锁API的完整理解需要对中断处理和相关概念的理解.

实际上有4个函数可以加锁一个自旋锁:

void spin_lock(spinlock_t *lock);

void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);

void spin_lock_irq(spinlock_t *lock);

void spin_lock_bh(spinlock_t *lock)

我们已经看到自旋锁如何工作. spin_loc_irqsave禁止中断(只在本地处理器)在获得自旋锁之前;之前的中断状态保存在flags里.如果你绝对确定在你的处理器上没有禁止中断的(或者,换句话说,你确信你应当在你释放你的自旋锁时打开中断),你可以使用spin_lock_irq代替,并且不必保持跟踪flags.最后, spin_lock_bh在获取锁之前禁止软件中断,但是硬件中断留作打开的.

如果你有一个可能被在(硬件或软件)中断上下文运行的代码获得的自旋锁,你必须使用一种spin_lock形式来禁止中断.其他做法可能死锁系统,迟早.如果你不在硬件中断处理里存取你的锁,但是你通过软件中断(例如,在一个tasklet运行的代码,在第7章涉及的主题),你可以使用spin_lock_bh来安全地避免死锁,而仍然允许硬件中断被服务.

也有4个方法来释放一个自旋锁;你用的那个必须对应你用来获取锁的函数.

void spin_unlock(spinlock_t *lock);

void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);

void spin_unlock_irq(spinlock_t *lock);

void spin_unlock_bh(spinlock_t *lock);

每个spin_unlock变体恢复由对应的spin_lock函数锁做的工作.传递给spin_unlock_irqrestore的flags参数必须是传递给spin_lock_irqsave的同一个变量.你必须也调用spin_lock_irqsave和spin_unlock_irqrestore在同一个函数里.否则,你的代码可能破坏某些体系.

还有一套非阻塞的自旋锁操作:

int spin_trylock(spinlock_t *lock);

int spin_trylock_bh(spinlock_t *lock);

这些函数成功时返回非零(获得了锁),否则0.没有"try"版本来禁止中断.

读者/写者自旋锁

内核提供了一个自旋锁的读者/写者形式,直接模仿我们在本章前面见到的读者/写者旗标.这些锁允许任何数目的读者同时进入临界区,但是写者必须是排他的存取.读者写者锁有一个类型rwlock_t,在中定义.它们可以以2种方式被声明和被初始化:

rwlock_t my_rwlock = RW_LOCK_UNLOCKED; /* Static way */

rwlock_t my_rwlock;

rwlock_init(&my_rwlock); /* Dynamic way */

可用函数的列表现在应当看来相当类似.对于读者,下列函数是可用的:

void read_lock(rwlock_t *lock);

void read_lock_irqsave(rwlock_t *lock, unsigned long flags);

void read_lock_irq(rwlock_t *lock);

void read_lock_bh(rwlock_t *lock);

void read_unlock(rwlock_t *lock);

void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);

void read_unlock_irq(rwlock_t *lock);

void read_unlock_bh(rwlock_t *lock);

有趣地,没有read_trylock.对于写存取的函数是类似的:

void write_lock(rwlock_t *lock);

void write_lock_irqsave(rwlock_t *lock, unsigned long flags);

void write_lock_irq(rwlock_t *lock);

void write_lock_bh(rwlock_t *lock);

int write_trylock(rwlock_t *lock);

void write_unlock(rwlock_t *lock);

void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);

void write_unlock_irq(rwlock_t *lock);

void write_unlock_bh(rwlock_t *lock);

读者/写者锁能够饿坏读者,就像rwsem一样.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值