linux內核中task_struct與thread_info及stack三者的關系


在linux內核中進程以及線程(多線程也是通過一組輕量級進程實現的)都是通過task_struct結構體來描述的,我們稱它為進程描述符。而thread_info則是一個與進程描述符相關的小數據結構,它同進程的內核態棧stack存放在一個單獨為進程分配的內存區域。由於這個內存區域同時保存了thread_info和stack,所以使用了聯合體來定義,相關數據結構如下(基於4.4.87版本內核):
 thread_union聯合體定義:
union thread_union {
    struct thread_info thread_info;
    unsigned long stack[THREAD_SIZE/sizeof(long)];
};

thread_info結構體定義:

struct thread_info {
    unsigned long        flags;        /* low level flags */
    mm_segment_t        addr_limit;    /* address limit */
    struct task_struct    *task;        /* main task structure */
    int            preempt_count;    /* 0 => preemptable, <0 => bug */
    int            cpu;        /* cpu */
};
task_struct的結構比較復雜,只列出部分成員變量,完整的可以在下面這個網站直接查看對應版本的內核代碼
struct task_struct {
    volatile long state;
    void *stack; 
 //...
#ifdef CONFIG_SMP
    int on_cpu;
    int wake_cpu;
#endif
    int on_rq;
  //...
#ifdef CONFIG_SCHED_INFO
    struct sched_info sched_info;
#endif
 //... 
    pid_t pid;
    pid_t tgid;
 //...
}; 
用一副圖來表示:
 
這樣設計的好處就是,得到stack,thread_info或task_struct任意一個數據結構的地址,就可以很快得到另外兩個數據的地址。
我們可以通過crash工具在ubuntu系統上做個實驗,來窺視一下某個進程的進程描述符
如果通過crash分析內核數據結構,可參考:
這里以進程systemd進程為例,其pid=1
crash> task 1
PID: 1      TASK: ffff88007c898000  CPU: 1   COMMAND: "systemd"
struct task_struct {
  state = 1,
  stack = 0xffff88007c894000,
  usage = {
    counter = 2
  },
。。。
可以看到systemd進程的task_struct結構體指針task=0xffff88007c898000
通過task->stack這個結構體成員即可定位到進程的內核棧地址 stack=0xffff88007c894000
另外從之前的圖可以看到,thread_info和stack處於同一地址空間,且thread_info在這段地址空間的最低地址處,而且這個地址空間是以THREAD_SIZE對齊的,所以只要將stack地址的最低N位變為0,即可得到thread_info的地址(2^N=THREAD_SIZE)
例如當THREAD_SZIE=8K時,systemd的thread_info地址就等於0xffff88007c894000&(~(0x1FFF)) = 0xffff88007c894000
crash> * thread_info 0xffff88007c894000
struct thread_info {
  task = 0xffff88007c898000,
  flags = 0,
  status = 0,
  cpu = 0,
  addr_limit = {
    seg = 140737488351232
  },
  sig_on_uaccess_error = 0,
  uaccess_err = 0
}

 

 
  而通過thread_info->task這個成員變量,又能訪問到進程的task_struct結構體,這樣就形成了task_struct, thread_info,stack三者之間的關系網,知道其中任何一個,都可以快速的訪問到另外兩個,提高了數據存取的效率。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM