內核棧與thread_info結構詳解


本文轉載自內核棧與thread_info結構詳解

什么是進程的內核棧?

在內核態(比如應用進程執行系統調用)時,進程運行需要自己的堆棧信息(不是原用戶空間中的棧),而是使用內核空間中的棧,這個棧就是進程的內核棧

進程的內核棧在計算機中是如何描述的?

linux中進程使用task_struct數據結構描述,其中有一個stack指針

struct task_struct
{
    // ...
    void *stack;    //  指向內核棧的指針
    // ...
};

task_struct數據結構中的stack成員指向thread_union結構(Linux內核通過thread_union聯合體來表示進程的內核棧)

union thread_union {
	struct thread_info thread_info;
	unsigned long stack[THREAD_SIZE/sizeof(long)];  
};

struct thread_info是記錄部分進程信息的結構體,其中包括了進程上下文信息:

struct thread_info {
	struct pcb_struct	pcb;		/* palcode state */
 
	struct task_struct	*task;		/* main task structure */  /*這里很重要,task指針指向的是所創建的進程的struct task_struct
	unsigned int		flags;		/* low level flags */
	unsigned int		ieee_state;	/* see fpu.h */
 
	struct exec_domain	*exec_domain;	/* execution domain */  /*表了當前進程是屬於哪一種規范的可執行程序,
                                                                        //不同的系統產生的可執行文件的差異存放在變量exec_domain中
	mm_segment_t		addr_limit;	/* thread address space */
	unsigned		cpu;		/* current CPU */
	int			preempt_count; /* 0 => preemptable, <0 => BUG */
 
	int bpt_nsaved;
	unsigned long bpt_addr[2];		/* breakpoint handling  */
	unsigned int bpt_insn[2];
 
	struct restart_block	restart_block;
};

img

從用戶態剛切換到內核態以后,進程的內核棧總是空的。因此,esp寄存器指向這個棧的頂端,一旦數據寫入堆棧,esp的值就遞減

thread_info的作用是?

這個結構體保存了進程描述符中中頻繁訪問和需要快速訪問的字段,內核依賴於該數據結構來獲得當前進程的描述符(為了獲取當前CPU上運行進程的task_struct結構,內核提供了current宏。

    #define get_current() (current_thread_info()->task)
    #define current get_current()

內核還需要存儲每個進程的PCB信息, linux內核是支持不同體系的的, 但是不同的體系結構可能進程需要存儲的信息不盡相同,

這就需要我們實現一種通用的方式, 我們將體系結構相關的部分和無關的部門進行分離,用一種通用的方式來描述進程, 這就是struct task_struct, 而thread_info

就保存了特定體系結構的匯編代碼段需要訪問的那部分進程的數據,我們在thread_info中嵌入指向task_struct的指針, 則我們可以很方便的通過thread_info來查找task_struct

內核棧的大小?

進程通過alloc_thread_info函數分配它的內核棧,通過free_thread_info函數釋放所分配的內核棧,查看源碼

alloc_thread_info函數通過調用__get_free_pages函數分配2個頁的內存(8192字節)


免責聲明!

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



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