关于linux内核中 等待队列 数据结构之思考

关于linux等待队列,大体有如下描述:

等待队列是一个双向循环链表,在这个链表中,有两种数据结构:等待队列头(wait_queue_head_t)和等待队列项(wait_queue_t)。

 

等待队列头和等待队列项中都包含一个list_head类型的域作为"连接件"。

 

 

 

等待对头wait_queue_head_t 和等待队列元素wait_queue_t的定义如下:

 

//队头结构

struct __wait_queue_head {
 spinlock_t lock;
 struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;

 

//队列元素结构

struct __wait_queue {
 unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
 void *private;
 wait_queue_func_t func;
 struct list_head task_list;
};

typedef struct __wait_queue wait_queue_t;

 

 

从队头和队列元素的定义中,可以看出,都包含了list_head类型的结构,而这个结构中只保存了向前和向后的指针。定义如下。

struct list_head {
 struct list_head *next, *prev;
};

 

看到这里就有些纳闷了,为什么这些方向指针和外面的结构体是分开的,也就是说,实际的指向关系只是这些方向指针之间的关系,而其他元素是附加在这些指针之上的。和我们传统的数据结构中的链表定义有很大的不同。

 

由此,又产生了一个疑问:那通过这些指针来获得具体的队列元素属性的时候,岂不是很不方便?(需要通过结构体某个成员的地址来计算该结构体的的地址?联想到之前学校的函数container_of或许可以完成此功能)

 

好奇心驱使下,最终了解了内核中队列的wakeup函数的实现,果不其然,在list_entry的定义中,找到了container_of的调用。

 

具体调用关系如下:

__wake_up_common--》list_for_each_entry_safe——》list_entry——》container_of

static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
   int nr_exclusive, int wake_flags, void *key)
{
 wait_queue_t *curr, *next;

 list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
  unsigned flags = curr->flags;

  if (curr->func(curr, mode, wake_flags, key) &&
    (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
   break;
 }
}

 

 

#define list_for_each_entry_safe(pos, n, head, member)   /
 for (pos = list_entry((head)->next, typeof(*pos), member), /
  n = list_entry(pos->member.next, typeof(*pos), member); /
      &pos->member != (head);      /
      pos = n, n = list_entry(n->member.next, typeof(*n), member))

 

 

#define list_entry(ptr, type, member) /
 container_of(ptr, type, member)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值