在 start_kernel 內(nèi)核初始化函數(shù)中,一共調(diào)用 86 個(gè)函數(shù)去初始化,其中有一個(gè) mm_init 函數(shù),用以初始化內(nèi)存。
start_kernel
|--- >mm_init
|--- >mem_init
linux4.14/init/main.c
在 mem_init 函數(shù)中會(huì)初始化伙伴系統(tǒng)和 slab 分配器。
先說(shuō)兩個(gè)概念:
外部碎片 :有一段小內(nèi)存,夾在兩個(gè)大內(nèi)存中間,兩個(gè)大內(nèi)存已經(jīng)被分配給進(jìn)程,這一段小內(nèi)存由于過(guò)小,不夠申請(qǐng)者使用,就一直空閑。
內(nèi)部碎片 :一個(gè)進(jìn)程申請(qǐng)了一段內(nèi)存,可是這個(gè)進(jìn)程從來(lái)沒有全部使用,一直有最后的一段內(nèi)存沒有使用。
為了解決這兩個(gè)問(wèn)題,就出現(xiàn)了伙伴系統(tǒng)和 slab 分配器。伙伴系統(tǒng)解決外部碎片問(wèn)題,slab 分配器解決內(nèi)部碎片問(wèn)題。
1、伙伴系統(tǒng)基于頁(yè)分配,一次分配多頁(yè),這樣就不會(huì)出現(xiàn)夾在中間的小內(nèi)存。
2、slab 分配器基于字節(jié)來(lái)分配,特別適用于需要頻繁分配幾十個(gè)字節(jié)的結(jié)構(gòu)體,我們經(jīng)常使用的 kmalloc 就是基于 slab 分配器。
3、其實(shí)所有的分配方式最底層都是伙伴系統(tǒng),它先分配好一段大的內(nèi)存,然后 slab 再?gòu)钠渲蟹峙湫〉膬?nèi)存。
其中最常用的就是 malloc 和 kmalloc,區(qū)別在于一個(gè)在用戶空間,一個(gè)在內(nèi)核空間,并且 kmalloc 的使用需要注意競(jìng)爭(zhēng),需要指明 flag 。
void *kmalloc(size_t size, int flags);
內(nèi)核編程(驅(qū)動(dòng)編程)一定要注意競(jìng)爭(zhēng)問(wèn)題,重要的數(shù)據(jù)或者內(nèi)存使用前后一定要加鎖。
在 kmalloc 的使用過(guò)程中,常用標(biāo)志位:GFP_KERNEL、GFP_ATOMIC、GFP_USER、GFP_HIGHUSER、GFP_NOIO、GFP_NOFS。
前兩個(gè)最常用,GFP_KERNEL 代表在使用 kmalloc 分配內(nèi)存時(shí),如果內(nèi)存準(zhǔn)備不足,會(huì)等待,也就是會(huì)睡眠。GFP_ATOMIC 代表使用 kmalloc 分配內(nèi)存時(shí),如果內(nèi)存準(zhǔn)備不足,會(huì)立刻返回,不會(huì)引起睡眠,適合在中斷上下文或者進(jìn)程上下文中使用。
補(bǔ)充:
1、基于 slab 分配器,出現(xiàn)了 slob 和 slub 分配器。在多核大系統(tǒng)大內(nèi)存中,一般使用 slub 分配器,在極小的嵌入式系統(tǒng)中,一般使用 slob 分配器(只有600多行代碼)。
2、有的人可能知道 Linux 有一個(gè) bootmem 分配器,這個(gè)是在Linux初始化過(guò)程中的一個(gè)臨時(shí)分配器,他會(huì)在 setup_arch 函數(shù)中初始化,然后在 mm_init 中關(guān)掉,只是在伙伴系統(tǒng)出現(xiàn)之前的臨時(shí)使用。
bootmem 分配器按塊進(jìn)行分配,顆粒度很大,不夠精細(xì),比較浪費(fèi)內(nèi)存。bootmem 分配器只會(huì)在 start_kernel 函數(shù)和mm_init 函數(shù)之前存在,中間的函數(shù)會(huì)調(diào)用它進(jìn)行內(nèi)存分配。
start_kernel
|--- >setup_arch
|--- >paging_init
|--- >bootmem_init
-
嵌入式
+關(guān)注
關(guān)注
5094文章
19184瀏覽量
307859 -
內(nèi)核
+關(guān)注
關(guān)注
3文章
1383瀏覽量
40434 -
Linux
+關(guān)注
關(guān)注
87文章
11350瀏覽量
210466 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3060瀏覽量
74353 -
分配器
+關(guān)注
關(guān)注
0文章
195瀏覽量
25840
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Linux應(yīng)用開發(fā)之內(nèi)存分配
![<b class='flag-5'>Linux</b>應(yīng)用開發(fā)之<b class='flag-5'>內(nèi)存</b><b class='flag-5'>分配</b>](https://file1.elecfans.com/web2/M00/82/8D/wKgaomRYae-AdHVcAAAX3xL4Omc809.png)
Linux內(nèi)存系統(tǒng): Linux 內(nèi)存分配算法
鴻蒙內(nèi)核源碼分析(內(nèi)存分配篇):內(nèi)存的分配方式有哪些
鴻蒙內(nèi)核源碼分析(內(nèi)存分配篇):內(nèi)存的分配方式有哪些
內(nèi)存管理程序結(jié)構(gòu)
一文解析Linux系統(tǒng)保留內(nèi)存的初始化流程
用rt_memheap_init分配堆內(nèi)存初始化失敗是何原因?怎么解決?
Linux內(nèi)存初始化
解析內(nèi)核初始化時(shí)根內(nèi)存盤的加載過(guò)程
淺談內(nèi)存分配方式 避免內(nèi)存浪費(fèi)問(wèn)題
什么是堆內(nèi)存?堆內(nèi)存是如何分配的?
保留Linux內(nèi)存的初始化原理及應(yīng)用實(shí)戰(zhàn)
![保留<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)存</b>的<b class='flag-5'>初始化</b>原理及應(yīng)用實(shí)戰(zhàn)](https://file1.elecfans.com/web2/M00/89/35/wKgZomR9iWyAR14VAAL9KU0_ZI4402.jpg)
評(píng)論