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


一個簡單的問題,·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源碼

 


免責聲明!

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



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