自旋锁的应用

自旋锁是一种忙等锁,内核中自旋锁的类型是spinlock_t,相关的API如下:

spin_lock_init:初始化自旋锁,在使用自旋锁之前必须要初始化。
spin_lock:获取自旋锁,如果不能获得自旋锁,则进行忙等待。
spin_lock_bh:获取自旋锁并进行下半部。
spin_lock_irq:获取自旋锁并进行下半部。
spin_lock_irqsave:获取自旋锁并竞争中断,保存中断屏蔽状态到flags中。
spin_lock_trylock:尝试获取自旋锁,即使不能获取,也立即返回,返回0表示成功获得自旋锁,否则表示没有获得自旋锁。其他的变体和spin_lock变体的意义相同。
spin_unlock:释放自旋锁,其他的unlock版本可以根据前面的解释判断作用。

在 i++ 的例子中,我们可以使用下面的代码来时自旋锁对i的操作进行互斥:

int i = 5;
/*定义自旋锁*/
spinlock_t lock;
/*用于保存中断屏蔽状态的变量*/
unsigned long flags;

/*使用自旋锁之前必须初始化自旋锁*/
spin_lock_init(&lock);
/*访问共享资源之前获得自旋锁,禁止中断,并将之前的中断屏蔽状态保存在flags变量中*/
spin_lock_irqsave(&lock,flags);
/*访问共享资源*/
i++;
/*共享资源访问完成后释放自旋锁,用flags的值恢复中断屏蔽的状态*/
spin_unlock_irqrestore(&lock,flags);

从上面的例子可以看到,自旋锁的使用还是比较直观的,基本的的步骤是定义锁、初始化锁、访问共享资源之前获得锁、访问完成之后释放锁。
关于自旋锁的一些重要特性和使用注意事项总结如下:

  1. 获得自旋锁的临界代码段执行时间不宜过长,因为是忙等锁,如果时间过长,就意味着其他想获得锁的内核执行路径会进行长时间的忙等待,这回影响系统的运行效率。
  2. 在获得锁的期间,不能调用可能会引起进程切换的函数,因为这会增加持锁的时间,导致其他要获得锁的代码进行更长时间的等待,更糟糕的情况是,如果新调度的进程要获取同样的自旋锁,就会造成死锁。
  3. 自旋锁是不能进行递归的,即获得锁之后不能再获得自旋锁,否则会因为一个不能获得的锁而将自己锁死。
  4. 自旋锁可以用于中断上下文中,因为他是忙等锁,所以不会造成进程的切换。
  5. 如果中断中也要访问共享资源,则在非中断处理代码中访问共享资源之前应该先禁止中断在获取,如果不这样,及时获得了锁中断也会发生,在中断中访问共享资源之前,中断也要获得一个已经被获得的自旋锁,那么中断将会被锁死,中断的下半部也会出现这种情况。
  6. 虽然一直都在说自旋锁是忙等锁,但是在单处理器的无抢占内核中,单纯的自旋锁(指不是禁止中断,禁止下半部的一些变体)获取操作其实是一个空操作,而在单处理器的可抢占内核中也仅仅是禁止抢占而已,真正的忙等待的特性只有在多处理器中才会体现出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值