1. 程式人生 > >linux內核獲取當前進程路徑分析

linux內核獲取當前進程路徑分析

調用 http 系統調用 源碼 inux 默認 置1 () 架構圖

一個簡單的問題,·linux下獲取當前進程。我們都知道在內核中獲取當前進程可以利用current宏

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

通過get_current發現其是利用當前線程獲取的當前進程線程結構thread_info結構中有指向其所屬的進程指針task

static inline struct thread_info *current_thread_info(void)
{
    struct thread_info *ti;
    __asm__(
        
"move.l %%sp, %0 \n\t" "and.l %1, %0" : "=&d"(ti) : "di" (~(THREAD_SIZE-1)) ); return ti; }

代碼比較簡單,獲取sp寄存器的值,然後和~(THREAD_SIZE-1)相與就得到指向thread_info的指針。原理為何呢?我們都知道每個進程有用一個內核棧,當進程通過某種方式比如系統調用進入內核,需要把棧空間切換到內核棧。默認情況下,內核棧的大小是2個頁面,也就是8KB。在棧的頂部保存著thread_info結構,基於棧是從高地址往低地址生長的,所以thread_info就是位於8KB地址區間的起始位置。例如內核棧空間為0xc9563000~0xc9565000(僅僅做示例,不代表任何實際意義),那麽架構圖如下所示:

技術分享

如圖所示,內核棧中,ESP指向任何時候必定位於0xc9563000~0xc9565000之間,所以此時我們可以看做是內核棧是8KB對齊的,既然如此回想下虛擬頁面中如何獲取虛擬頁框基地址呢?正是把內部偏移位全都置0,然後和地址想與。so~這裏也是如此,THREAD_SIZE-1就是棧內偏移位,取反就把除了偏移部分,其余部分全都置1,想與後無論如何結果始終指向內核棧區間的起始位置,圖中為例就是0xc9563000.that‘s all,thank you!!

感謝主!

參考:

Linux內核3.10.1源碼

linux內核獲取當前進程路徑分析