有這麼一系列的問題,是否在困擾着你:用戶程序編譯連接形成的地址空間在什麼範圍內?內核編譯後地址空間在什麼範圍內?要對外設進行訪問,I/O的地址空間又是什麼樣的?
先回答第一個問題。Linux最常見的可執行文件格式爲elf(Executable and Linkable Format)。在elf格式的可執行代碼中,ld總是從0x8000000開始安排程序的“代碼段”,對每個程序都是這樣。至於程序執行時在物理內存中的實際地址,則由內核爲其建立內存映射時臨時分配,具體地址取決於當時所分配的物理內存頁面。
我們可以用Linux的實用程序objdump對你的程序進行反彙編,從而知曉其地址範圍。
例如:假定我們有一個簡單的C程序Hello.c
# include
#define __PAGE_OFFSET (0xC0000000)
……
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
對於內核空間而言,給定一個虛地址x,其物理地址爲“x- PAGE_OFFSET”,給定一個物理地址x,其虛地址爲“x+ PAGE_OFFSET”。
這裏再次說明,宏__pa()僅僅把一個內核空間的虛地址映射到物理地址,而決不適用於用戶空間,用戶空間的地址映射要複雜得多,它通過分頁機制完成。