下一页 上一页 目录

13. 实用函数

13.1 list_entry [include/linux/list.h]

定义

#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

含义

"list_entry" 宏用于通过仅使用一个内部结构指针来检索父结构指针。

示例

struct __wait_queue {
   unsigned int flags; 
   struct task_struct * task; 
   struct list_head task_list;
};
struct list_head { 
   struct list_head *next, *prev; 
};

// and with type definition:
typedef struct __wait_queue wait_queue_t;

// we'll have
wait_queue_t *out list_entry(tmp, wait_queue_t, task_list);

// where tmp point to list_head

因此,在这种情况下,通过 *tmp 指针 [list_head],我们检索到 *out 指针 [wait_queue_t]。

 ____________ <---- *out [we calculate that]
|flags       |             /|\
|task *-->   |              |
|task_list   |<----    list_entry
|  prev * -->|    |         |
|  next * -->|    |         |
|____________|    ----- *tmp [we have this]
 

13.2 Sleep

Sleep 代码

文件

函数

被调用的函数

互调用分析

|sleep_on
   |init_waitqueue_entry  --
   |__add_wait_queue        |   enqueuing request to resource list
      |list_add              |
         |__list_add        -- 
   |schedule              ---     waiting for request to be executed
      |__remove_wait_queue --   
      |list_del              |   dequeuing request from resource list
         |__list_del        -- 
 

描述

在 Linux 中,每个资源(理想情况下是多个用户和多个进程之间共享的对象)都有一个队列来管理所有请求它的任务。

这个队列被称为 “等待队列”,它由许多项组成,我们称之为 “等待队列元素”。

***   wait queue structure [include/linux/wait.h]  ***


struct __wait_queue {
   unsigned int flags; 
   struct task_struct * task; 
   struct list_head task_list;
}
struct list_head { 
   struct list_head *next, *prev; 
};

图形化工作原理

        ***  wait queue element  ***

                             /|\
                              |
       <--[prev *, flags, task *, next *]-->
 
                     


                 ***  wait queue list ***  
 
          /|\           /|\           /|\                /|\
           |             |             |                  |
--> <--[task1]--> <--[task2]--> <--[task3]--> .... <--[taskN]--> <--
|                                                                  |
|__________________________________________________________________|
          

           
              ***   wait queue head ***

       task1 <--[prev *, lock, next *]--> taskN
   
 

“等待队列头” 指向 “等待队列列表” 的第一个(使用 next *)和最后一个(使用 prev *)元素。

当需要添加新元素时,会调用 "__add_wait_queue" [include/linux/wait.h],之后将执行通用例程 "list_add" [include/linux/wait.h]。

***   function list_add [include/linux/list.h]  ***

// classic double link list insert
static __inline__ void __list_add (struct list_head * new,  \
                                   struct list_head * prev, \
                                   struct list_head * next) { 
   next->prev = new; 
   new->next = next; 
   new->prev = prev; 
   prev->next = new; 
}

为了完整描述,我们还看到 "remove_wait_queue" [include/linux/wait.h] 内部的 "list_del" [include/linux/list.h] 调用了 "__list_del" [include/linux/list.h] 函数。

***   function list_del [include/linux/list.h]  ***


// classic double link list delete
static __inline__ void __list_del (struct list_head * prev, struct list_head * next) { 
   next->prev = prev; 
   prev->next = next; 
}

栈的考量

典型的列表(或队列)通常通过将其分配到堆中来管理(有关堆和栈的定义以及变量的分配位置,请参见第 10 章)。 然而,在这里,我们将等待队列数据静态分配在局部变量(栈)中,然后函数被调度中断,最后,(从调度返回后)我们将擦除局部变量。

  new task <----|          task1 <------|          task2 <------|
                |                       |                       |
                |                       |                       | 
|..........|    |       |..........|    |       |..........|    | 
|wait.flags|    |       |wait.flags|    |       |wait.flags|    |
|wait.task_|____|       |wait.task_|____|       |wait.task_|____|   
|wait.prev |-->         |wait.prev |-->         |wait.prev |-->
|wait.next |-->         |wait.next |-->         |wait.next |-->   
|..        |            |..        |            |..        |    
|schedule()|            |schedule()|            |schedule()|     
|..........|            |..........|            |..........|    
|__________|            |__________|            |__________|     
 
   Stack                   Stack                   Stack

下一页 上一页 目录