1.什麼是進程的內核棧? 在內核態(比如應用進程執行系統調用)時,進程運行需要自己的堆棧信息(不是原用戶空間中的棧),而是使用內核空間中的棧,這個棧就是進程的內核棧 2.進程的內核棧在電腦中是如何描述的? linux中進程使用task_struct數據結構描述,其中有一個stack指針 task_ ...
1.什麼是進程的內核棧?
在內核態(比如應用進程執行系統調用)時,進程運行需要自己的堆棧信息(不是原用戶空間中的棧),而是使用內核空間中的棧,這個棧就是進程的內核棧
2.進程的內核棧在電腦中是如何描述的?
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;
};
從用戶態剛切換到內核態以後,進程的內核棧總是空的。因此,esp寄存器指向這個棧的頂端,一旦數據寫入堆棧,esp的值就遞減
3.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
4.內核棧的大小?
進程通過alloc_thread_info函數分配它的內核棧,通過free_thread_info函數釋放所分配的內核棧,查看源碼
alloc_thread_info函數通過調用__get_free_pages函數分配2個頁的記憶體(8192位元組)