Chinaunix首页 | 论坛 | 博客
  • 博客访问: 300338
  • 博文数量: 35
  • 博客积分: 836
  • 博客等级: 准尉
  • 技术积分: 678
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-07 20:11
文章分类

全部博文(35)

文章存档

2013年(1)

2012年(24)

2011年(10)

分类: LINUX

2012-02-15 20:51:36

最近在看linux rtmutex部分的实现过程,就像他注释中写的一样,还是比较简单的。其中比较复杂的部分就是关于任务优先级继承的部分。

 

首先介绍优先级反转的背景。

何为优先级反转?通俗来说就是低优先级的任务抢占了高优先级的运行权。下面举出一个优先级翻转的场景。

 

系统中有三个具有不同优先级的任务ABC。其中A的优先级最高,B次之,C的优先级最低。系统中AC共享一个资源,此时C任务先就绪获得此资源的使用权限,这时A任务就绪,也想使用此资源,但是由于C已经在访问状态,所以A被阻塞。此时B任务就绪,如果系统中无优先级翻转处理等机制,那么B任务就会剥夺C任务的运行权限,从而也就剥夺了A任务的运行权限,这样稍低优先级的任务就抢占了高优先级的任务。此种现象就是优先级翻转问题。

 

解决优先级翻转的问题通常有几种,一种是优先级继承方式,还有就是天花板方式。

1.         优先级继承方式是指在有任务阻塞到相应共享资源时,所获得资源的任务继承被阻塞任务的优先级,当然只是继承更高的优先级,小于等于的无视。在上例中就为A获得资源被C阻塞时,C任务继承A任务的高优先级,这样B再就绪时就不会抢占C的运行权,从而就避免了优先级翻转现象。

2.         优先级天花板办法,就是将获得共享资源时,直接提升任务的优先级到可以获得此种资源的最高优先级。在上例中,当C获得此资源时,直接升到最高的优先级,如果系统中只有AC使用此资源,那么就升级到A的优先级,这样B就绪时也无法抢占C的运行权,从而避免了优先级反转现象。

两者的区别主要在获得优先级提升的时间,前者在有高优先级任务发生阻塞时,后者是直接在获得资源时提升优先级。

rtmutex主要数据结构

rt_mutex,就是一个互斥锁的结构,只有三个元素。

  1. struct rt_mutex {
  2.     raw_spinlock_t wait_lock; /* 保护此结构的自旋锁 */
  3.     struct plist_head wait_list; /* 等待此互斥锁的所有waiter链表 */
  4.     struct task_struct *owner; /* 获得此锁的task,如果没有为NULL */

  5. }

rtmutex waiter的数据结构:用于记录等待互斥锁得结构

  1. struct rt_mutex_waiter {
  2.     struct plist_node    list_entry; /* 用于将此结构连接到对应的互斥锁上 */
  3.     struct plist_node    pi_list_entry; /* 用于将此结构连接到互斥锁所有者上等待链表中 */
  4.     struct task_struct    *task /* 此waiter所属的task,也即等待此mutex的task */
  5.     struct rt_mutex        *lock; /* 此waiter等待的mutex */
  6. };

主要的数据结构如上所示,后续介绍rtmutex的具体函数调用流程,由于是mutex,那么主要从最大需求的三个方面来介绍,一个是init,一个是lock,最后一个就是unlock

1)初始化函数

  1. void __rt_mutex_init(struct rt_mutex *lock, const char *name)
  2. {
  3.     lock->owner = NULL;
  4.     raw_spin_lock_init(&lock->wait_lock);
  5.     plist_head_init(&lock->wait_list);

  6.     debug_rt_mutex_init(lock, name);
  7. }

此函数已经简单到不能再简单了,将rt_mutex中的相关item初始化。

2)lock函数

  1. void __sched rt_mutex_lock(struct rt_mutex *lock)
  2. {
  3.     might_sleep();

  4.     rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock);
  5. }

其中,rt_mutex_fastlock首先尝试快速获得lock,如果尝试无法成功,则调用rt_mutex_slowlock 继续获得锁。

3)unlock函数

  1. void __sched rt_mutex_unlock(struct rt_mutex *lock)
  2. {
  3.     rt_mutex_fastunlock(lock, rt_mutex_slowunlock);
  4. }

此函数与上述lock函数一样,首先尝试快速的unlock,如果不符合条件,那么再调用rt_mutex_slowunlock函数完成解锁操作。


内部机制,我是很想好好阐述出来的,但是由于自己表达能力有限,等后续总结好了,再更改此篇博客。想写一篇好的技术博客真TM难啊。看懂一个东西简单,讲明白一个东西真TM难,想要理解为啥这么搞更TM难。




阅读(6611) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~