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

来源:互联网 发布:淘宝装修图 编辑:程序博客网 时间:2024/05/02 00:37

上集说到哪儿了呢?瞧这记性,什么?说到"天要下雨,娘要嫁人"那段。。

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

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

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

int device_count = 0;  定义文件打开的次数计数static int device_open(struct inode *inode, struct file *filp){    ...    spinlock(&device_count);    if(device_count)  //已经打开     {         spin_unlock(&device_count);         return -EBUSY;    }    device_count++;  //增加使用计数    spin_unlock(&device_count);    ...    return 0;}static int device_release(struct inode *inode, struct file *filp){    ...    spinlock(&device_count );    device_count--; //减少使用计数    spin_unlock(&device_count );    return 0;}
 

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

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

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

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

"耶呵,看不出来哈,你都知道用脑袋想问题了,以前不是都是要大脚趾计算的吗..什么时候升级换代的.."我吃惊的瞪着眼,"那好,不拿出点真货你搞不定你了..请看新招之读写自旋锁"
读写自旋锁:它保留了自锁的概念,但是它规定在读方面同时可以有多个读单元,在写方面,只能最多有一个写进程。当然,读和写也不能同时进行。

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

               rwlock_t x;//动态初始化                                            rwlock_t x=RW_LOCK_UNLOCKED;//动态初始化

               rwlock_init(&x);

             2)最基本的读写函数。

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

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

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

              void write_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_t lock; //定义rwlock

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

 

//读时获取锁

read_lock(&lock);

….//临界资源

read_unlock(&lock);

 

//写时获取锁

write_lock_irqsave(&lock, flags);

….//临界资源

write_unlock_irqrestore(&lock, flags);

原创粉丝点击