位置:持久對映區在核心位址空間中,夾在vmalloc區和固定對映區之間,(pkmap_base至fixmap_start)。
步驟:通過kmap將傳入的page*對映到虛擬記憶體時分以下幾步:1.在核心位址空間(持久對映區)分配乙個頁;2.建立傳入的物理記憶體頁和虛擬位址之間的對映;3.統計核心位址空間中哪些頁被引用。
kmap函式實現:
void *kmap(struct page *page)
如果傳入的物理記憶體頁幀不是高階記憶體,直接呼叫page_address(page);計算虛擬位址;通過page在mem_map中的位置計算是第幾個物理頁,在根據低端記憶體域與核心空間前896m的直接對映關係可得出虛擬位址。
如果傳入的物理記憶體頁幀是高階記憶體,則呼叫kmap_high(page);函式處理。
void *kmap_high(struct page *page)
在kmap_high函式中先呼叫page_address檢查該page是否已經被對映。如果沒有對映呼叫map_new_virtual(page);處理。
pkmap_count是乙個整數陣列,其中每個元素都對應持久對映區的乙個持久對映頁,功能是作為計數器用。標示該頁被引用的次數。
map_new_virtual函式如下:
static inline unsigned long map_new_virtual(struct page *page)
if (!pkmap_count[last_pkmap_nr])
break; /* found a usable entry */
if (--count)
continue;
/** sleep for somebody else to unmap their entries*/}
vaddr = pkmap_addr(last_pkmap_nr);
set_pte_at(&init_mm, vaddr,
&(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
pkmap_count[last_pkmap_nr] = 1;
set_page_address(page, (void *)vaddr);
return vaddr;
}
該函式功能:
1.從上一次使用的位置last_pkmap_nr開始反向掃瞄pkmap_count陣列,直到找到乙個空閒位置,如果沒有空閒位置,該函式進入睡眠狀態,知道核心的另一部分執行解除對映操作。
2.呼叫set_pte_at()修改核心頁表,將該頁對映到指定位置,但尚未更新tlb。
3.pkmap_count[last_pkmap_nr] = 1;新位置的使用計數器設定為1,表示該分頁已分配,但是無法使用。因為tlb項未更新。
4.呼叫set_page_address()將該頁新增到核心對映的資料結構。
set_page_address()函式實現如下:
void set_page_address(struct page *page, void *virtual)
else
} spin_unlock_irqrestore(&pas->lock, flags);
}done:
return;
}
該函式為page指標和虛擬位址建立乙個page_address_map結構來對映,並將結構新增到page_address_maps全域性hash鍊錶中。
struct page_address_map ;
static struct page_address_map page_address_maps[last_pkmap];
**如下:
總結一下上述過程:
1.當呼叫kmap函式,傳入乙個物理頁幀page的指標時,會返回該page關聯的虛擬位址。kmap函式中先判斷該page是低端記憶體還是高階記憶體,如果是低端記憶體,則直接呼叫page_address函式,通過直接對映關係,計算出該page關聯的虛擬位址;如果傳入kmap函式的page對應的是高階記憶體的物理頁幀,則呼叫kmap_high函式處理。
2.進入在kmap_high函式中,說明入參page對應高階記憶體的物理頁幀,仍然要先呼叫page_address判斷該物理頁是否已經關聯了虛擬位址。如果已經關聯則將對應的虛擬位址在pkmap_count中的項+1,返回該page對應的虛擬位址。如果沒有關聯,則呼叫map_new_virtual函式,給該page建立關聯的實體地址。
3.在map_new_virtual函式中,先通過掃瞄pkmap_count中的項為該page找到未用的虛擬位址,然後修改頁表,便於通過虛擬位址找到實體地址。然後呼叫set_page_address函式為page和虛擬位址建立對映結構page_address_map,並新增到上圖所示的結構中。
page_address_map結構的作用:
該結構是用於建立物理記憶體頁page示例和虛擬記憶體區中位置之間的對映。該結構在記憶體中的組織圖如上圖所示。
page_address_maps與頁表的功能的區別:
二者都建立虛擬位址和物理記憶體頁之間的對映,個人理解區別主要有兩點:(1)核心空間的頁表包含所有核心位址空間和實體地址之間的對映,而page_address_maps只包含持久對映區的虛擬位址和物理記憶體頁之間的對映。(2)核心頁表主要用於通過虛擬位址尋找實體地址,也用於低端記憶體,而page_address_maps主要用於page_address中通過page*找到其對映的虛擬位址。
page_address函式實現:
void *page_address(const struct page *page)
} }done:
spin_unlock_irqrestore(&pas->lock, flags);
return ret;
}
如果不是高階記憶體呼叫lowmem_page_address函式通過低端記憶體直接對映的特性計算出虛擬位址。
如果是高階記憶體,迭代page_address_maps,找到對應的page_address_map結構,然後返回虛擬位址。
linux核心學習筆記
核心的配置 a.make s3c2410 deconfig b.make menuconfig 圖形化配置 c.使用廠家給出的配置 生成.config 編譯生成核心,使用如下命令 make vmlinux make uimage 帶頭部 真正核心 1 config 建立生成autoconf.h 供源...
Linux核心學習筆記
2.2 核心原始碼樹 arch 特定體系結構的原始碼 block crypto api crypto 核心原始碼文件 drivers 裝置驅動程式 firmware fs vfs和各種檔案系統 include 核心標頭檔案 init 核心引導和初始化 ipc 程序間通訊 kernel 像排程程式這樣...
Linux核心學習筆記 核心同步
linux核心中執行的程式,時刻都要防止併發引起的競態。這將會導致資料結構被破壞,嚴重的時候會引起核心崩潰。所以核心同步技術對核心開發的驅動程式來說非常重要。不懂核心同步技術的人,是寫不出安全健壯的核心驅動程式來的。在學習核心同步技術之前需要掌握一下幾個概念。1 並行,併發與競態 在smp執行的li...