linux内核启动(2)——2.4.Linux执行链表

来源:互联网 发布:程序员在公司的装备 编辑:程序博客网 时间:2024/05/09 13:42
2.4.        Linux执行链表

在遍历等待队列之前,首先执行Linux标准的双向执行链表。等待队列用起来繁杂,行话称之为“list.h 实现”,因为它最相关的文件是include/linux/list.h。
基础数据结构是list_head结构:
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) /
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { /
(ptr).>;next = (ptr); (ptr).>;prev = (ptr); /
} while (0)
#define list_entry(ptr, type, member) /
((type *)((char *)(ptr).(unsigned long)(&((type *)0).>;member)))
#define list_for_each(pos, head) /
for (pos = (head).>;next; pos != (head); pos = pos.>;next)
前三个宏用来初始化一个next和prev指针皆指向自身的空链表,宏可以用到的地方明显受限于c语法约束。例如,LIST_HEAD_INIT()用来初始化结构元素,第二个宏用来初始化静态变量,第三个用于函数内部。
list_entry()宏提供了对单独链表元素的操作,例如(fs/file_table.c:fs_may_remount_ro()函数):
struct super_block {
...
struct list_head s_files;
...
} *sb = &some_super_block;
struct file {
...
struct list_head f_list;
...
} *file;
struct list_head *p;

for (p = sb.>;s_files.next; p != &sb.>;s_files; p = p.>;next) {
struct file *file = list_entry(p, struct file, f_list);
// do something to 'file'
}
一个使用list_for_each()宏的最好例子就是任务调度函数中遍历运行队列以查找高优先级的进程部分。
static LIST_HEAD(runqueue_head);
struct list_head *tmp;
struct task_struct *p;

list_for_each(tmp, &runqueue_head) {
p = list_entry(tmp, struct task_struct, run_list);
if (can_schedule(p)) {
int weight = goodness(p, this_cpu, prev.>;active_mm);
if (weight >; c)
c = weight, next = p;
}
}
p.>;run_list 被定义成task_struct结构内的list_head结构成员run_list,serves为指向链表的指针。向链表里面删除或者添加一个元素由list_del()/list_add()/list_add_tail()三个宏完成。下面的例子向运行队列添加并删除一个任务。
static inline void del_from_runqueue(struct task_struct * p)
{
nr_running..;
list_del(&p.>;run_list);
p.>;run_list.next = NULL;
}
static inline void add_to_runqueue(struct task_struct * p)
{
list_add(&p.>;run_list, &runqueue_head);
nr_running++;
}
static inline void move_last_runqueue(struct task_struct * p)
{
list_del(&p.>;run_list);
list_add_tail(&p.>;run_list, &runqueue_head);
}
static inline void move_first_runqueue(struct task_struct * p)
{
list_del(&p.>;run_list);
list_add(&p.>;run_list, &runqueue_head);
}
原创粉丝点击