我們知道Linux是分為兩種狀態(tài) 用戶態(tài)和內(nèi)核態(tài),Linux內(nèi)核需要跑在硬件平臺上,硬件平臺也有自己的狀態(tài)。這里還是ARM,ARM有其中處理器的模式。
用戶模式(user):用戶程序運(yùn)行的模式。系統(tǒng)模式(system):特權(quán)模式。一般中斷模式(IRQ):普通中斷模式??焖僦袛嗄J剑‵IQ):快速中斷模式。管理模式(supervisor):操作系統(tǒng)的內(nèi)核通常運(yùn)行在該模式下。數(shù)據(jù)訪問終止模式(abort):當(dāng)數(shù)據(jù)或者指令預(yù)取終止時(shí)進(jìn)入該模式,用于虛擬存儲及存儲保護(hù)。未定義指令模式(undefined):當(dāng)未定義的指令執(zhí)行時(shí)進(jìn)入該模式,可用于支持硬件協(xié)處理器的軟件仿真。
Linux內(nèi)核的用戶態(tài)和內(nèi)核態(tài)兩種模式分別對應(yīng)的用戶模式和管理模式。
這里還是以32位,對應(yīng)4GB,內(nèi)核一般內(nèi)核:用戶按照1:3的比例分配。這也是可以修改的。
我們知道分頁機(jī)制,賦予了每個(gè)進(jìn)程都有尋址4GB的空間,因?yàn)槊總€(gè)進(jìn)程都有自己的進(jìn)程表。
內(nèi)核空間是從3GB開始,lowmem這段空間其實(shí)就是我們常說的線性映射區(qū)。(為啥虛擬地址明明在高位卻是low,繼續(xù)看)所謂的線性映射區(qū),就是物理內(nèi)存線性地映射到這段內(nèi)核空間的區(qū)域中。在 ARM32 平臺上,物理地址[0:760MB]的這一部分內(nèi)存被線性映射到[3GB :3GB+760MB]的虛擬地址上(因?yàn)槠湮锢淼刂吩诘臀唬?/p>
線性映射區(qū)的虛擬地址和物理地址相差PAGE_OFFSET,即3GB。內(nèi)核中有相關(guān)的宏來實(shí)現(xiàn)線性映射區(qū)的虛擬地址到物理地址的查找,例如pa(x)和va(x)。
其中,__pa()把線性映射區(qū)的虛擬地址轉(zhuǎn)換為物理地址,轉(zhuǎn)換公式很簡單,即用虛擬地址減去PAGE_OFFSET(3GB),然后加上PHYS_OFFSET(這個(gè)值在有的ARM平臺上為0,在ARM Vexpress平臺上為0x6000_0000)。
物理內(nèi)存被分成了兩部分,低端的部分用在線性映射區(qū),線性映射區(qū)就是這里的“l(fā)owmem”區(qū)域。剩下的高端部分的物理內(nèi)存被稱為高端內(nèi)存(High Memory),內(nèi)核要使用它,必須通過高端映射的方式來訪問。
內(nèi)核通常把低于760MB的物理內(nèi)存稱為線性映射內(nèi)存(Normal Memory),而高于760MB以上的稱為高端內(nèi)存。 (這個(gè)高端是針對內(nèi)核內(nèi)存來說,780到1G)
這個(gè)分給內(nèi)核的1G分成了高端和線性。
高端780到1G是干啥呢?剩下的264MB虛擬地址空間是保留給vmalloc機(jī)制、fixmap和高端異常向量表等使用的。內(nèi)核很多驅(qū)動使用vmalloc機(jī)制來分配連續(xù)虛擬地址的內(nèi)存,因?yàn)橛械尿?qū)動不需要連續(xù)物理地址的內(nèi)存;除此以外,vmalloc機(jī)制還可以用于高端內(nèi)存的臨時(shí)映射。一個(gè)32位的系統(tǒng)中,實(shí)際支持的內(nèi)存數(shù)量會超過內(nèi)核線性映射的長度,但是內(nèi)核要具有對所有內(nèi)存的尋找能力。
(這里我想的是雖然在內(nèi)核,但是我內(nèi)核還是要對整個(gè)內(nèi)存有個(gè)控制能力,這里就是體現(xiàn),在vmalloc機(jī)制就可以干這個(gè):個(gè)人看法,有糾正的大佬在評論區(qū)告訴小的一下)
編譯器在編譯目標(biāo)文件并且鏈接完成之后,就可以知道內(nèi)核映像文件最終的大小,接下來將其打包成二進(jìn)制文件,該操作由arch/arm/kernel/vmlinux.ld.S 控制,其中也劃定了內(nèi)核的內(nèi)存布局。
內(nèi)核image本身占據(jù)的內(nèi)存空間從_text段到_end段,并分為如下幾個(gè)段。text段:_text和_etext為代碼段的起始和結(jié)束地址,包含了編譯后的內(nèi)核代碼。init段:init_begin和init_end為init段的起始和結(jié)束地址,包含了大部分內(nèi)核模塊初始化的數(shù)據(jù)。data段:_sdata和_edata為數(shù)據(jù)段的起始和結(jié)束地址,保存大部分內(nèi)核的已初始化的變量。BSS段:bss_start和bss_stop為BSS段的開始和結(jié)束地址,包含初始化為0的所有靜態(tài)全局變量。
上述幾個(gè)段的大小在編譯鏈接時(shí)根據(jù)內(nèi)核配置來確定,因?yàn)槊糠N配置的代碼段和數(shù)據(jù)段長度都不相同,這取決于要編譯哪些內(nèi)核模塊,但是起始地址_text 總是相同的。內(nèi)核編譯完成之后,會生成一個(gè)System.map文件,查詢這個(gè)文件可以找到這些符號的具體數(shù)值。
-
處理器
+關(guān)注
關(guān)注
68文章
19384瀏覽量
230508 -
Linux
+關(guān)注
關(guān)注
87文章
11329瀏覽量
209969 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3042瀏覽量
74179 -
進(jìn)程
+關(guān)注
關(guān)注
0文章
204瀏覽量
13971
發(fā)布評論請先 登錄
相關(guān)推薦
評論