解析Linux内核的同步与互斥机制(二)

源出处:http://www.startos.com/linux/tips/2011011921499_2.html

全局或者在栈中定义一个wait_queue_t类型变量的同时对其初始化,这保证了系统的可靠性,避免因用户忘记初始化时导致的问题。通用的初始化宏,tsk为任意指针。分两步:

  1) 内部宏__WAITQUEUE_INITIALIZER初始化相应成员;当wq内嵌在别的结构体中时,此宏很重要,提高了可移植性;

  2) 提供给外部的接口,定义一个变量,并将第一步的结果赋值给该变量。

  static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)

  {

  q->flags = 0;

  q->private = p;

  q->func = default_wake_function;

  }

  动态初始化一个等待队列入口项,将其和当前进程关联起来,以便唤醒当前进程。

  2.1.3 数据结构设计规则

  今后凡遇到新设计一类结构体,若此类结构体变量必须初始化且有相对集中的操作,则应提供以下两个操作接口:

  a) 定义新建一个结构体变量,并初始化之;

  b) 动态初始化一个已经分配内存的该类变量

  为了适应在堆栈及全局等任意地方分配的该变量,其应该接收指向该类变量的指针。

  2.2 陈旧sleep_on系列

  //初始化一个wait_queue_t

  #define SLEEP_ON_VAR \

  unsigned long flags; \

  wait_queue_t wait; \

  init_waitqueue_entry(&wait, current);

  //添加到队列中

  #define SLEEP_ON_HEAD \

  spin_lock_irqsave(&q->lock,flags); \

  __add_wait_queue(q, &wait); \

  spin_unlock(&q->lock);

  //从队列中删除

  #define SLEEP_ON_TAIL \

  spin_lock_irq(&q->lock); \

  __remove_wait_queue(q, &wait); \

  spin_unlock_irqrestore(&q->lock, flags);

  SLEEP_ON_VAR、 SLEEP_ON_HEAD及SLEEP_ON_ TAIL总是同时出现,不可分割。上述宏不是函数,只是连续的表达式而已,因为函数就将他们隔离开来了,函数他退出后变量就无意义了。也不能写成 do――while的多语句宏,变量定义离开“{}”后就没有意义了。是为了编写代码更清晰明了,同时避免多写字,实际上就是代码封装复用。

  void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)

  {

  SLEEP_ON_VAR //注意没“;”

  current->state = TASK_INTERRUPTIBLE;

  SLEEP_ON_HEAD

  schedule(); //此处可能出问题

  SLEEP_ON_TAIL

  }

  EXPORT_SYMBOL(interruptible_sleep_on);

  添加到队列和从队列中删除由同一个模块做,符合模块设计规则,减小了耦合性。

  唤醒的wakeup只负责改变进程状态,进程重新获得cpu后从队列中删除。

  long fastcall __sched

  interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)

  {

  SLEEP_ON_VAR

  current->state = TASK_INTERRUPTIBLE;

  SLEEP_ON_HEAD

  timeout = schedule_timeout(timeout);

  SLEEP_ON_TAIL

  return timeout;

  }

  EXPORT_SYMBOL(interruptible_sleep_on_timeout);

  void fastcall __sched sleep_on(wait_queue_head_t *q)

  {

  SLEEP_ON_VAR

  current->state = TASK_UNINTERRUPTIBLE;

  SLEEP_ON_HEAD

  schedule();

  SLEEP_ON_TAIL

  }

  EXPORT_SYMBOL(sleep_on);

  long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)

  {

  SLEEP_ON_VAR

  current->state = TASK_UNINTERRUPTIBLE;

  SLEEP_ON_HEAD

  timeout = schedule_timeout(timeout);

  SLEEP_ON_TAIL

  return timeout;

  }

  EXPORT_SYMBOL(sleep_on_timeout);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值