一、記憶體資料表示:
推薦文章:《linux 進程管理》
我們在教材或閱讀中,經常需要直觀的用圖示來展示資料在記憶體中的分布,那麼資料是如何在記憶體
中組織的呢?不同的機器有不同的標記法,我們以最常見的Intel X86系列電腦為例來說明這個問題。 如示記憶體:記憶體低址在上。記憶體高址在下,記憶體單位為16bit。對於基於intel i386架構的電腦,系統採用小端位元組序來存放資料,所謂小端位元組序是指低序位元組低地址,高序位元組高地址(記憶體位址增大方向),大端位元組序反之,給定系統所用的位元組序稱為主機位元組序;CPU也以小端位元組序形式讀取資料,如所示,如果變數num是16位的short短整類型,則CPU從記憶體中讀出的num=0x1234;如果num是32位的int類型,則CPU從記憶體中讀出的是num=0x56781234,其中num地址是0x12345678,即&num=0x12345678 二、linux核心擷取進程任務結構的指標 明白了系統記憶體資料表示,我們現在來看看linux核心是如何擷取當前進程的任務結構指標的,以下代碼均參照linux核心2.4.0的源碼。 在include/asm-i386/ current.h中
#ifndef _I386_CURRENT_H#define _I386_CURRENT_H struct task_struct; static inline struct task_struct * get_current(void){ struct task_struct *current; __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); return current; }#define current get_current() #endif /* !(_I386_CURRENT_H) */ |
每個進程都有一個task_struct任務結構,和一片用於系統空間堆棧的儲存空間,他們在實體記憶體空間中也是聯絡在一起的,當給進程申請task_struct任務結構空間時,系統將連同系統的堆棧空間一起分配,如為某個進程切換時刻的記憶體配置圖: 下面針對代碼實現來分析一下系統如何通過一系列操作擷取進程在核心中的任務結構指標的:由於linux核心分配進程任務結構空間時,是以8KB(2個頁面空間,即2^1*4KB,linux對實體記憶體空間和虛擬記憶體空間管理時,均規定其頁面單位的尺寸為4KB)為單位來分配的,所以記憶體應用地址是8KB(2^13)的整數倍,即指標地址的低13位全為0,所以根據小端位元組序,分配記憶體返回地址應該是指向struct task_struct結構,中的0xc2342000地址所指,至於為何採用代碼中的做法而不是直接將此指標儲存在全域變數中以供應用,核心是從其自身的效率方面來考慮的,我們在此只針對代碼解釋:根據,此刻記憶體esp內容必定在0xc2342000和0xc2344000之間的一個數值,我們假設取0xc2343ffe(即堆棧壓棧EIP、返回地址、內部資料等相關資料了,地址值要減小;只要符合0xc2342xxx 、0xc2343xxx的地址指標都是正確的),來通過代碼運算看是否current的指標是0xc2342000。__asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));語句的意思是將ESP的內容與8191UL的反碼按位進行與操作,之後再把結果賦值給current,其中8191UL=8192-1=2^13-1,計算過程如下:
8192UL=2^13 0000 0000 0000 0000 0010 0000 0000 00008191UL 0000 0000 0000 0000 0001 1111 1111 1111~8191UL(反碼) 1111 1111 1111 1111 1110 0000 0000 00000xc2343ffe 1100 0010 0011 0100 0011 1111 1111 1110andl結果: 1100 0010 0011 0100 0010 0000 0000 0000 || (對照著看) 0xc 2 3 4 2 0 0 0 |
所以按位與操作之後的結果位0xc2342000,正好是struct task_struct結構的地址指標.通過觀察可知,只要符合0xc2342xxx 、0xc2343xxx的地址指標經過相同的計算,都可以得到核心進程任務結構的指標。 另外,在進入中斷或系統調用時所引用的宏操作(include/asm-i386/ hw_irq.h):
#define GET_CURRENT / "movl %esp, %ebx/n/t" / "andl $-8192, %ebx/n/t" |
其原理與上述描述也是一致的。
上一篇:《rh9實現視頻的捕獲》
下一篇:《【linux編程】C++記憶體管理詳解(一)》