“小王,今天咱們開始講有關記憶體和I/O訪問的內容,心裡先要有點低,這部分內容還是有點煩,有點難的哦”說著話,我心裡都沒底,怕嚇著小王,不瞞你說,當時看這部分,我可是沒少費勁。
“哦,那咋辦,不能不學是不?沒事,有小濤哥在,俺就不怕”小王信心十足的說。
“哦!看不出來,還讓你來安慰我了”看著小王這充滿信心的樣子,我也沒啥顧慮了。好了,深吸一口氣,開始今天的課程。
我們知道,在X86中,有I/O空間的概念,I/O空間是相對於記憶體空間的概念,它通過特定的指令in,out來訪問。連接埠號碼標識了外設的寄存器地址。而巧的是Arm等內嵌控制器中並不提供I/O空間,所以我們就不考慮了,我們重點放在記憶體空間。
記憶體空間可以通過地址,指標來訪問,在C語言中的表現就是通過指標來操作,如在186處理器中:
unsigned char *p = (unsigned char *)0xF000FF00;
*P=11;
這段代碼的意思就是:在絕對位址0xF000+0xFF00(186處理器使用16位段地址和16位位移地址)寫入11。在ARM, PPC等未採用段地址的處理器中,P指向的記憶體
空間就是0xF000FF00,而*p=11就是在該地址寫入11。
說完記憶體空間,就不得不說說MMU(記憶體管理單元),它輔助作業系統進行記憶體管理,提供虛擬位址和物理地址的映射,記憶體存取權限保護和Cache緩衝控制等硬體支援,作業系統核心藉助MMU,可以讓使用者感覺好像程式可以使用非常大的記憶體空間,從而使得編程人員在寫程式時不用考慮電腦中實體記憶體的實際容量。
為了理解基本的MMU操作原理,先介紹幾個概念:
1)TLB:Translation Lookaside Buffer,即轉換旁路緩衝。也稱快表,是轉換表的cache,緩衝少量的虛擬位址與物理地址的對應關係。
2)TTW:Translation Table walk,即轉換表漫遊。當TLB中沒有緩衝對應的地址轉換關係時,需要通過對記憶體中轉換表的訪問來獲得虛擬位址和物理地址的對應關係。TTW成功後,結果應寫入TLB.
為了說明MMU在訪問記憶體中的使用,我特意畫了一個流程圖。如下:
說了MMU,現在就來和linux聯絡一下,對於包含MMU的處理而言,Linux系統提供了複雜的儲存管理系統,使得進程所能訪問的記憶體達到4GB,這4GB是分為2個部
分---使用者空間和核心空間,前者一般分布為0~3GB(即PAGE_OFFSET,在0x86中等於0xC0000000),剩下的3~4GB是核心空間。通常情況下,使用者進程只有通過系統調用等方式才可以訪問到核心空間。
小王你學過C語言,知道在使用者空間動態申請記憶體用malloc()函數,釋放用free,這在各種作業系統上的使用是一致的。這方面的內容,比如記憶體流失啦,具體使用等就不細講了,我們的重點放在核心空間,核心空間怎麼做呢?
前邊有個知識點沒說,後面要用到,就提一下:linux核心空間3~4GB是還可以在分的,從低到高依次是:實體記憶體映射區->隔離帶->vmalloc虛擬記憶體分配器->隔
離帶->高端記憶體映射區->專用頁面影視區->保留區。
在Linux核心空間中申請記憶體涉及的函數主要包括kmalloc(),__get_free_pages()【這兩個申請的記憶體位於實體記憶體映射區在實體記憶體上也是連續的,和實體記憶體有簡單的轉換關係】和vmalloc【它是在虛擬記憶體空間給出一塊連續的記憶體區,在實體記憶體中不一定是聯絡的,和實體記憶體也沒有簡單的換算關係】等。有關這三個函數的使用網上一大堆,我就我細說了,小王,你的我都給你列印好了,你直接看就行了。
我們說虛擬位址和物理地址是有一定的轉換關係,具體是使用virt_to_phys()可以實現虛擬位址轉換為物理地址,代碼清單如下:
#define _ _pa(x) ((unsigned long)(x)-PAGE_OFFSET) extern inline unsigned long virt_to_phys(volatile void * address) { return _ _pa(address); }
與之對應的函數是phys_to_virt(),用於將物理地址轉化為虛擬位址。具體代碼如下:
#define _ _pa(x) ((unsigned long)(x)+PAGE_OFFSET)
extern inline unsigned long virt_to_phys(volatile void * address)
{
return _ _pa (address);
}
值得說明的是上述方法僅適用與常規記憶體,高端記憶體的虛擬位址與物理地址之間不存在這樣簡單的換算關係。
“小王不知道,你聽的怎麼樣,我說的時候心裡都沒底啊,這一章確實很難,挺那個的..”
“小濤哥,沒事,你放心講吧,經過那麼多,我覺得自己應該有一定能力了,理解起來應該能跟上,如果跟不上再找你哈”小王又給了我繼續講下去的信心。