成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

操作系統(tǒng)就用一張大表管理內(nèi)存?

系統(tǒng) 存儲(chǔ)軟件
今天我們不聊具體內(nèi)存管理的算法,我們就來看看,操作系統(tǒng)用什么樣的一張表,達(dá)到了管理內(nèi)存的效果。

今天我們不聊具體內(nèi)存管理的算法,我們就來看看,操作系統(tǒng)用什么樣的一張表,達(dá)到了管理內(nèi)存的效果。

我們以 Linux 0.11 源碼為例,發(fā)現(xiàn)進(jìn)入內(nèi)核的 main 函數(shù)后不久,有這樣一坨代碼。

  1. void main(void) { 
  2.     ... 
  3.     memory_end = (1<<20) + (EXT_MEM_K<<10); 
  4.     memory_end &= 0xfffff000; 
  5.     if (memory_end > 16*1024*1024) 
  6.         memory_end = 16*1024*1024; 
  7.     if (memory_end > 12*1024*1024)  
  8.         buffer_memory_end = 4*1024*1024; 
  9.     else if (memory_end > 6*1024*1024) 
  10.         buffer_memory_end = 2*1024*1024; 
  11.     else 
  12.         buffer_memory_end = 1*1024*1024; 
  13.     main_memory_start = buffer_memory_end; 
  14.  
  15.     mem_init(main_memory_start,memory_end); 
  16.     ... 

除了最后一行外,前面的那一大坨的作用很簡(jiǎn)單。

其實(shí)就只是針對(duì)不同的內(nèi)存大小,設(shè)置不同的邊界值罷了,為了理解它,我們完全沒必要考慮這么周全,就假設(shè)總內(nèi)存一共就 8M 大小吧。

那么如果內(nèi)存為 8M 大小,memory_end 就是

8 * 1024 * 1024

也就只會(huì)走倒數(shù)第二個(gè)分支,那么 buffer_memory_end 就為

2 * 1024 * 1024

那么 main_memory_start 也為

2 * 1024 * 1024

你仔細(xì)看看代碼邏輯,看是不是這樣?

當(dāng)然,你不愿意細(xì)想也沒關(guān)系,上述代碼執(zhí)行后,就是如下效果而已。

你看,其實(shí)就是定了三個(gè)箭頭所指向的地址的三個(gè)邊界變量。具體主內(nèi)存區(qū)是如何管理和分配的,要看 mem_init 里做了什么。

  1. void main(void) { 
  2.     ... 
  3.     mem_init(main_memory_start, memory_end); 
  4.     ... 

而緩沖區(qū)是如何管理和分配的,就要看再后面的 buffer_init 里干了什么。

  1. void main(void) { 
  2.     ... 
  3.     buffer_init(buffer_memory_end); 
  4.     ... 

不過我們今天只看,主內(nèi)存是如何管理的,很簡(jiǎn)單,放輕松。

進(jìn)入 mem_init 函數(shù)。

  1. #define LOW_MEM 0x100000 
  2. #define PAGING_MEMORY (15*1024*1024) 
  3. #define PAGING_PAGES (PAGING_MEMORY>>12) 
  4. #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) 
  5. #define USED 100 
  6.  
  7. static long HIGH_MEMORY = 0; 
  8. static unsigned char mem_map[PAGING_PAGES] = { 0, }; 
  9.  
  10. // start_mem = 2 * 1024 * 1024 
  11. // end_mem = 8 * 1024 * 1024 
  12. void mem_init(long start_mem, long end_mem) 
  13.     int i; 
  14.     HIGH_MEMORY = end_mem; 
  15.     for (i=0 ; i<PAGING_PAGES ; i++) 
  16.         mem_map[i] = USED; 
  17.     i = MAP_NR(start_mem); 
  18.     end_mem -= start_mem; 
  19.     end_mem >>= 12; 
  20.     while (end_mem-->0) 
  21.         mem_map[i++]=0; 

發(fā)現(xiàn)也沒幾行,而且并沒有更深的方法調(diào)用,看來是個(gè)好欺負(fù)的方法。

仔細(xì)一看這個(gè)方法,其實(shí)折騰來折騰去,就是給一個(gè) mem_map 數(shù)組的各個(gè)位置上賦了值,而且顯示全部賦值為 USED 也就是 100,然后對(duì)其中一部分又賦值為了 0。

賦值為 100 的部分就是 USED,也就表示內(nèi)存被占用,如果再具體說是占用了 100 次,這個(gè)之后再說。剩下賦值為 0 的部分就表示未被使用,也即使用次數(shù)為零。

是不是很簡(jiǎn)單?就是準(zhǔn)備了一個(gè)表,記錄了哪些內(nèi)存被占用了,哪些內(nèi)存沒被占用。這就是所謂的“管理”,并沒有那么神乎其神。

那接下來自然有兩個(gè)問題,每個(gè)元素表示占用和未占用,這個(gè)表示的范圍是多大?初始化時(shí)哪些地方是占用的,哪些地方又是未占用的?

還是一張圖就看明白了,我們?nèi)匀患僭O(shè)內(nèi)存總共只有 8M。

可以看出,初始化完成后,其實(shí)就是 mem_map 這個(gè)數(shù)組的每個(gè)元素都代表一個(gè) 4K 內(nèi)存是否空閑(準(zhǔn)確說是使用次數(shù))。

4K 內(nèi)存通常叫做 1 頁內(nèi)存,而這種管理方式叫分頁管理,就是把內(nèi)存分成一頁一頁(4K)的單位去管理。

1M 以下的內(nèi)存這個(gè)數(shù)組干脆沒有記錄,這里的內(nèi)存是無需管理的,或者換個(gè)說法是無權(quán)管理的,也就是沒有權(quán)利申請(qǐng)和釋放,因?yàn)檫@個(gè)區(qū)域是內(nèi)核代碼所在的地方,不能被“污染”。

1M 到 2M 這個(gè)區(qū)間是緩沖區(qū),2M 是緩沖區(qū)的末端,緩沖區(qū)的開始在哪里之后再說,這些地方不是主內(nèi)存區(qū)域,因此直接標(biāo)記為 USED,產(chǎn)生的效果就是無法再被分配了。

2M 以上的空間是主內(nèi)存區(qū)域,而主內(nèi)存目前沒有任何程序申請(qǐng),所以初始化時(shí)統(tǒng)統(tǒng)都是零,未來等著應(yīng)用程序去申請(qǐng)和釋放這里的內(nèi)存資源。

那應(yīng)用程序如何申請(qǐng)內(nèi)存呢?我們本講不展開,不過我們簡(jiǎn)單展望一下,看看申請(qǐng)內(nèi)存的過程中,是如何使用 mem_map 這個(gè)結(jié)構(gòu)的。

在 memory.c 文件中有個(gè)函數(shù) get_free_page(),用于在主內(nèi)存區(qū)中申請(qǐng)一頁空閑內(nèi)存頁,并返回物理內(nèi)存頁的起始地址。

比如我們?cè)?fork 子進(jìn)程的時(shí)候,會(huì)調(diào)用 copy_process 函數(shù)來復(fù)制進(jìn)程的結(jié)構(gòu)信息,其中有一個(gè)步驟就是要申請(qǐng)一頁內(nèi)存,用于存放進(jìn)程結(jié)構(gòu)信息 task_struct。

  1. int copy_process(...) { 
  2.     struct task_struct *p; 
  3.     ... 
  4.     p = (struct task_struct *) get_free_page(); 
  5.     ... 

我們看 get_free_page 的具體實(shí)現(xiàn),是內(nèi)聯(lián)匯編代碼,看不懂不要緊,注意它里面就有 mem_map 結(jié)構(gòu)的使用。

  1. unsigned long get_free_page(void) { 
  2.     register unsigned long __res asm("ax"); 
  3.     __asm__( 
  4.         "std ; repne ; scasb\n\t" 
  5.         "jne 1f\n\t" 
  6.         "movb $1,1(%%edi)\n\t" 
  7.         "sall $12,%%ecx\n\t" 
  8.         "addl %2,%%ecx\n\t" 
  9.         "movl %%ecx,%%edx\n\t" 
  10.         "movl $1024,%%ecx\n\t" 
  11.         "leal 4092(%%edx),%%edi\n\t" 
  12.         "rep ; stosl\n\t" 
  13.         "movl %%edx,%%eax\n" 
  14.         "1:" 
  15.         :"=a" (__res) 
  16.         :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES), 
  17.         "D" (mem_map + PAGING_PAGES-1) 
  18.         :"di","cx","dx"); 
  19.     return __res; 

就是選擇 mem_map 中首個(gè)空閑頁面,并標(biāo)記為已使用。

好了,本講就這么多,只是填寫了一張大表而已,簡(jiǎn)單吧?之后的內(nèi)存申請(qǐng)與釋放等騷操作,統(tǒng)統(tǒng)是跟著張大表 mem_map 打交道而已,你一定要記住它哦。

 

責(zé)任編輯:武曉燕 來源: 低并發(fā)編程
相關(guān)推薦

2013-08-14 09:21:16

Ubuntu

2019-09-22 18:31:46

Oracleundo空間

2022-11-28 07:21:53

操作系統(tǒng)內(nèi)存管理

2009-08-17 08:32:56

Linux操作系統(tǒng)內(nèi)存管理Linux

2021-03-28 13:54:31

操作系統(tǒng)內(nèi)存管理

2010-02-04 17:16:30

2009-12-02 11:02:54

操作系統(tǒng)

2010-04-20 14:17:21

Unix操作系統(tǒng)

2010-04-14 13:59:45

Unix操作系統(tǒng)

2021-06-11 07:26:16

操作系統(tǒng)內(nèi)存管理Cpu

2025-01-13 00:30:17

2010-04-13 16:11:15

Unix操作系統(tǒng)

2022-11-17 12:09:51

2010-04-07 15:37:16

Unix操作系統(tǒng)

2010-04-08 17:05:21

Unix操作系統(tǒng)

2024-08-05 00:05:00

操作系統(tǒng)內(nèi)存管理

2021-02-07 09:01:10

Java并發(fā)編程

2019-09-11 10:12:12

華為

2024-08-28 17:45:00

內(nèi)存Linux

2024-08-05 11:20:41

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 男人天堂网址 | 日韩精品一区二区久久 | 国产精品九九 | 在线观看久草 | 99精品久久99久久久久 | 久久久91| av片免费观看 | 伊人网伊人网 | 欧美一级α片 | 日本粉嫩一区二区三区视频 | 国产精品中文在线 | 国产精品99久久免费观看 | 日韩精品久久一区 | 日韩欧美在线观看 | 中文字幕在线观看精品 | 午夜影院在线观看免费 | 日本亚洲精品 | 亚洲成av人片在线观看无码 | 99久久亚洲 | 成人特级毛片 | 国产一区不卡 | 亚洲欧美视频在线观看 | 国产成人99 | 国产欧美精品 | 免费在线观看成人 | 亚洲午夜网 | 亚洲欧美成人 | 999国产视频| 国产成人精品一区二区三区四区 | 国产成人99av超碰超爽 | 国产精品毛片一区二区在线看 | 美女日批免费视频 | 亚洲欧美精品在线 | 亚洲一一在线 | 99在线精品视频 | 成年人在线观看 | 久久6视频| 日本精品视频 | 一级免费毛片 | 中文亚洲字幕 | 亚洲永久字幕 |