您的位置:首页 > 运维架构 > Linux

Linux内核开发之并发控制(二)

2013-02-27 10:54 260 查看
上集说到哪儿了呢?瞧这记性,什么?说到"天要下雨,娘要嫁人"那段。。

这是谁在答话,废话,我当然知道讲到这里了,我是说驱动讲到哪里了。算了,不管了..

话说Linux开源社区的开发者们做了什么工作呢,很简单:

利用spin_lock()/spin_unlock()作为自旋锁的基础,将它们和关中断local_irq_disable()/开中断local_irq_enable(),关底半部local_bh_disable()/开底半部local_

bh_enable(),关中断并保存状态字local_irq_save()/开中断并恢复状态local_irq_restore()结合就完成了整套自旋锁机制。

唉吆,我的天啊,不是我说你们开源社区的那些家伙们,说个东西为啥要那么费劲,就为了说完上面那些红色的破话,差点没喘过来,本来在上篇就想说你们的…

好人做到低,送你送到西,嘿嘿..我把上边的关系再帮大家捋捋,免的看着费劲…

spin_lock_irq()=spin_lock()+local_irq_disable()
spin_unlock_irq=spin_unlock()+local_irq_enable()
spin_lock_irqsave()=spin_unlock()+local_irq_save()
spin_unlock_irqrestore()=spin_unlock()+local_irq_restore()
spin_lock_bh()=spin_lock()+local_bh_disable()
spin_unlock_bh()=spin_unlock()+local_bh_enable()


又是一口气,这是什么年头,挣点点击率,怎么就这么难呢..不过也是没办法的事,上了Linux这条贼船,就要有牺牲我一个,幸福全中国的决心,不然微软的又要嚣张了,今天黑你一次屏,明天断你一次网,就连去网吧,微软还伸手到你面前说:对不起,你的系统是盗版…

好了,让他们热闹去吧,说说咱们的事。作为Linux驱动程序工程师,你要在心里刻下几条戒律:

1)什么叫自旋锁,就是忙等待,当锁不可用时,CPU除了在那儿拼命的执行"测试并设置"的傻瓜操作外什么都不做,才不管电影中含情脉脉的你是她的谁,她是你的谁的这些事,任你两情相约,也是执手相看泪眼,竟无语凝咽。可见,这是多么的影响系统的性能。

2)what?你不懂爱情,不在乎第一条,我晕…那就给你来个狠的:处理不好自旋锁可能导致系统死锁(deadlock),系统瘫痪。呵呵怕不,等你哭着闹着要上网而不能时,就怕了。那为啥会这样了,很简单,想想:如果我们不小心在一个递归中使用一个自旋锁,说白了就是一个CPU,它已经获得了这个自旋锁,可还贪心地想第二次获得这个自旋锁,这时就死锁了呗。另外,如果一个进程获得自旋锁之后再阻塞,也是很有可能导致死锁的发生。

理论完了,给你来点代码,就当是程序员点的一点交代吧:

intdevice_count=0;定义文件打开的次数计数
staticintdevice_open(structinode*inode,structfile*filp)
{
...
spinlock(&device_count);
if(device_count)//已经打开
{
spin_unlock(&device_count);
return-EBUSY;
}
device_count++;//增加使用计数
spin_unlock(&device_count);
...
return0;
}

staticintdevice_release(structinode*inode,structfile*filp)
{
...
spinlock(&device_count);
device_count--;//减少使用计数
spin_unlock(&device_count);

return0;
}



出招表四:读写自旋锁(防写不防读)

"找你所说,上面的那招自旋锁看似相当好啊.."

"那是,也不看看是谁教的.."

"那我就不明白了,接着你说的例子:你说我买票是吧,售票员看到一张票(读)也没错啊,错在与她把票卖出去的操作上(写),你这可好,这样一来,一旦一个锁住,别人都别想看了,这也太傻瓜了吧.."小王不屑的鄙视我。

"耶呵,看不出来哈,你都知道用脑袋想问题了,以前不是都是要大脚趾计算的吗..什么时候升级换代的.."我吃惊的瞪着眼,"那好,不拿出点真货你搞不定你了..请看新招之读写自旋锁"

读写自旋锁:它保留了自锁的概念,但是它规定在读方面同时可以有多个读单元,在写方面,只能最多有一个写进程。当然,读和写也不能同时进行。

使用方法:1)初始化读写锁的方法。

rwlock_tx;//动态初始化rwlock_tx=RW_LOCK_UNLOCKED;//动态初始化

rwlock_init(&x);

2)最基本的读写函数。

voidread_lock(rwlock_t*lock);//使用该宏获得读写锁,如果不能获得,它将自旋,直到获得该读写锁

voidread_unlock(rwlock_t*lock);//使用该宏来释放读写锁lock

voidwrite_lock(rwlock_t*lock);//使用该宏获得获得读写锁,如果不能获得,它将自旋,直到获得该读写锁

voidwrite_unlock(rwlock_t*lock);//使用该宏来释放读写锁lock

3)和自旋锁中的spin_trylock(lock),读写锁中分别为读写提供了尝试获取锁,并立即返回的函数,如果获得,就立即返回真,否则返回假:

read_trylock(lock)和write_lock(lock);

4)硬中断安全的读写锁函数:

read_lock_irq(lock);//读者获取读写锁,并禁止本地中断

read_unlock_irq(lock);//读者释放读写锁,并使能本地中断

write_lock_irq(lock);//写者获取读写锁,并禁止本地中断

write_unlock_irq(lock);//写者释放读写锁,并使能本地中断

read_lock_irqsave(lock,flags);//读者获取读写锁,同时保存中断标志,并禁止本地中断

read_unlock_irqrestores(lock,flags);//读者释放读写锁,同时恢复中断标志,并使能本地中断

write_lock_irqsave(lock,flags);//写者获取读写锁,同时保存中断标志,并禁止本地中断

write_unlock_irqstore(lock,flags);写者释放读写锁,同时恢复中断标志,并使能本地中断

5)软中断安全的读写函数:

read_lock_bh(lock);//读者获取读写锁,并禁止本地软中断

read_unlock_bh(lock);//读者释放读写锁,并使能本地软中断

write_lock_bh(lock);//写者获取读写锁,并禁止本地软中断

write_unlock_bh(lock);//写者释放读写锁,并使能本地软中断

呵呵,小王,看到没有有了这第四招,你刚才的问题就没有了,现在给你一个典型应用吧:

rwlock_tlock;//定义rwlock

rwlock_init(&lock);//初始化rwlock

//读时获取锁

read_lock(&lock);

….//临界资源

read_unlock(&lock);

//写时获取锁

write_lock_irqsave(&lock,flags);

….//临界资源

write_unlock_irqrestore(&lock,flags);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: