我們在教材或閱讀中,經常需要直觀的用圖示來展示資料在記憶體中的分布,那麼資料是如何在記憶體中組織的呢?不同的機器有不同的表示法,我們以最常見的intel x86系列計算機為例來說明這個問題。
如上圖示記憶體示意圖:記憶體低址在上。記憶體高址在下,記憶體單位為16bit。對於基於intel i386架構的計算機,系統採用小端位元組序來存放資料,所謂小端位元組序是指低序位元組低位址,高序位元組高位址(記憶體位址增大方向),大端位元組序反之,給定系統所用的位元組序稱為主機位元組序;cpu也以小端位元組序形式讀取資料,如上圖所示,如果變數num是16位的short短整型別,則cpu從記憶體中讀出的num=0x1234;如果num是32位的int型別,則cpu從記憶體中讀出的是num=0x56781234,其中num位址是0x12345678,即&num=0x12345678
明白了系統記憶體資料表示,我們現在來看看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
每個程序都有乙個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、返回位址、內部資料等相關資料了,位址值要減小;只要符合0xc2342*** 、0xc2343***的位址指標都是正確的),來通過**運算看是否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 0000
8191ul 0000 0000 0000 0000 0001 1111 1111 1111
~8191ul(反碼) 1111 1111 1111 1111 1110 0000 0000 0000
0xc2343ffe 1100 0010 0011 0100 0011 1111 1111 1110
andl結果: 1100 0010 0011 0100 0010 0000 0000 0000
|| (對照著看)
0x c 2 3 4 2 0 0 0
所以按位與操作之後的結果位0xc2342000,正好是struct task_struct結構的位址指標.通過觀察可知,只要符合0xc2342*** 、0xc2343***的位址指標經過相同的計算,都可以得到核心程序任務結構的指標。
另外,在進入中斷或系統呼叫時所引用的巨集操作(include\asm-i386\ hw_irq.h):
#define get_current \
"movl %esp, �x\n\t" \
"andl $-8192, �x\n\t"
其原理與上述描述也是一致的。
C Process獲取當前程序資訊
1.獲取當前程序資訊整理 process.getcurrentprocess 返回當前程式的程序物件。process cur process.getcurrentprocess 當前程序的id console.writeline cur.id 獲取關聯的程序的終端服務會話識別符號。console.w...
C 獲取當前程序HASH的方法
用c 實現在這個過程,我們需要進行下面幾個步驟 得到當前程序所對應的本地宿主檔案 開啟這個檔案流 確定hash演算法,計算檔案流的hash 將hash結果轉換為我們熟悉的字串表現形式。下面就分別就這幾個方面來進行解釋。在system.diagnostics命名空間下,有個process類,msdn的...
Android獲取當前程序和執行緒ID常用方法總結
獲取當前程序id android.os.process.mypid 獲取當前程序的使用者id android.os.process.myuid 獲取當前執行緒id 1 thread.currentthread getid 獲取當前執行緒id 2 android.os.process.mytid 獲取...