1.1.1 共享內存
共享內存(Share Memory)是類似FIFO的數據傳輸設備[43]。共享內存採用的主要技術是內存映射。在共享內存中,由於所有高層的虛擬內存都基於底層物理內存,因此,物理內存是共享內存系統中最重要部分。在XtratuM系統中,物理內存是由Linux內核管理,因此,系統可以採用Linux內核APIs分配物理內存。爲了提高系統分配物理內存的效率和成功率。共享內存的建立遵循以下準則:
l 物理內存的分配應該先於域的加載。也就是說,高層應用域無需物理內存分配而可以直接應用共享內存;
l 物理內存可以使用非連續物理內存;
l 共享內存的大小應該是PAGE_SIZE或者是該值的整數倍。
爲了避免XtratuM內核太大,共享內存使用的物理內存由共享內存模塊直接管理,並且與XtratuM內核分離。共享內存通過調用內核函數vmalloc()函數分配物理內存。由於共享內存使用的是塊物理內存,動態管理機制被引用。用戶可以通過”make menuconfig”的相應配置選項設置共享內存大小。在XtratuM系統,共有8個默認共享內存,並且共享內存的默認大小是128K。在系統中,vmalloc()函數被採用進行物理內存分配而沒有選用kmalloc()函數,這是由於vmalloc()函數分配連續的虛擬內存空間,但是並不能保證分配的物理內存連續,而kmalloc()函數不僅可以分配連續的虛擬內存空間,而且物理內存分配亦連續。因此,kmalloc()函數的使用,尤其是分配大塊內存時,其失敗率相對較高,爲此,共享內存中採用vmalloc()函數。類似於FIFO,頁表內存的分配也是通過__get_free_page()函數。
域中的低地址已經被FIFO,堆,事件以及其它資源佔用,因此,共享內存的默認虛擬地址是從0x 3000000開始。並且,由於共享內存是採用vmalloc()函數分配,所得地址爲內核虛擬地址,爲了將該地址轉換成物理地址,系統採用了kvirt_to_phy()函數。
static inline unsigned long kvirt_to_phy(unsigned long vaddr)
{
unsigned long ret = 0UL;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t pte;
pgd = pgd_offset_k(vaddr);
if(! pgd_none(*pgd)) {
pud = pud_offset(pgd, vaddr);
if(!pud_none(*pud)) {
pmd = pmd_offset(pud, vaddr);
if(!pmd_none(*pmd)) {
pte = *(pte_offset_kernel(pmd, vaddr));
if(pte_present(pte)) {
ret=(unsigned long) age_address(pte_page(pte));
ret |= (vaddr & (PAGE_SIZE - 1));
}
}
}
}
return ret;
}
內存通過vmalloc()函數分配,並且相應虛擬地址可以通過kvirt_to_phy()函數轉換爲物理地址,接下來的任務就是將對應的物理內存映射到域空間地址。映射任務是在域加載時完成。
Int load_domain_sys(…)
{
…
/* share memory map */
vaddress = DEFAULT_SHM_ADDRESS;
shm_ctlpage_map(gd, vaddress, alloc_page);
event->shm_ctladdr = vaddress;
vaddress += PAGE_SIZE;
for(i = 0; i < SHM_COUNT; i++) {
shm_datapage_map(gd, vaddress+i*buffer_size, alloc_page, index);
event->shm_dataddr[i] = vaddress+i*buffer_size;
}
…
}