国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
嵌入式驅(qū)動入門

Linux設(shè)備驅(qū)動編程之內(nèi)存與I/O操作

2006-10-27 13:35作者:宋寶華出處:天極開發(fā)責(zé)任編輯:方舟

    相關(guān)專題: Linux設(shè)備驅(qū)動程序開發(fā)入門

  對于提供了MMU(存儲管理器,輔助操作系統(tǒng)進(jìn)行內(nèi)存管理,提供虛實地址轉(zhuǎn)換等硬件支持)的處理器而言,Linux提供了復(fù)雜的存儲管理系統(tǒng),使得進(jìn)程所能訪問的內(nèi)存達(dá)到4GB。

  進(jìn)程的4GB內(nèi)存空間被人為的分為兩個部分--用戶空間與內(nèi)核空間。用戶空間地址分布從0到3GB(PAGE_OFFSET,在0x86中它等于0xC0000000),3GB到4GB為內(nèi)核空間,如下圖:


  內(nèi)核空間中,從3G到vmalloc_start這段地址是物理內(nèi)存映射區(qū)域(該區(qū)域中包含了內(nèi)核鏡像、物理頁框表mem_map等等),比如我們使用的VMware虛擬系統(tǒng)內(nèi)存是160M,那么3G~3G+160M這片內(nèi)存就應(yīng)該映射物理內(nèi)存。在物理內(nèi)存映射區(qū)之后,就是vmalloc區(qū)域。對于160M的系統(tǒng)而言,vmalloc_start位置應(yīng)在3G+160M附近(在物理內(nèi)存映射區(qū)與vmalloc_start期間還存在一個8M的gap來防止躍界),vmalloc_end的位置接近4G(最后位置系統(tǒng)會保留一片128k大小的區(qū)域用于專用頁面映射),如下圖:


  kmalloc和get_free_page申請的內(nèi)存位于物理內(nèi)存映射區(qū)域,而且在物理上也是連續(xù)的,它們與真實的物理地址只有一個固定的偏移,因此存在較簡單的轉(zhuǎn)換關(guān)系,virt_to_phys()可以實現(xiàn)內(nèi)核虛擬地址轉(zhuǎn)化為物理地址:

#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
extern inline unsigned long virt_to_phys(volatile void * address)
{
 return __pa(address);
}

  上面轉(zhuǎn)換過程是將虛擬地址減去3G(PAGE_OFFSET=0XC000000)。

  與之對應(yīng)的函數(shù)為phys_to_virt(),將內(nèi)核物理地址轉(zhuǎn)化為虛擬地址:

#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
extern inline void * phys_to_virt(unsigned long address)
{
 return __va(address);
}

  virt_to_phys()和phys_to_virt()都定義在include\asm-i386\io.h中。

  而vmalloc申請的內(nèi)存則位于vmalloc_start~vmalloc_end之間,與物理地址沒有簡單的轉(zhuǎn)換關(guān)系,雖然在邏輯上它們也是連續(xù)的,但是在物理上它們不要求連續(xù)。

  我們用下面的程序來演示kmalloc、get_free_page和vmalloc的區(qū)別:

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
MODULE_LICENSE("GPL");
unsigned char *pagemem;
unsigned char *kmallocmem;
unsigned char *vmallocmem;

int __init mem_module_init(void)
{
 //最好每次內(nèi)存申請都檢查申請是否成功
 //下面這段僅僅作為演示的代碼沒有檢查
 pagemem = (unsigned char*)get_free_page(0);
 printk("<1>pagemem addr=%x", pagemem);

 kmallocmem = (unsigned char*)kmalloc(100, 0);
 printk("<1>kmallocmem addr=%x", kmallocmem);

 vmallocmem = (unsigned char*)vmalloc(1000000);
 printk("<1>vmallocmem addr=%x", vmallocmem);

 return 0;
}

void __exit mem_module_exit(void)
{
 free_page(pagemem);
 kfree(kmallocmem);
 vfree(vmallocmem);
}

module_init(mem_module_init);
module_exit(mem_module_exit);

  我們的系統(tǒng)上有160MB的內(nèi)存空間,運(yùn)行一次上述程序,發(fā)現(xiàn)pagemem的地址在0xc7997000(約3G+121M)、kmallocmem地址在0xc9bc1380(約3G+155M)、vmallocmem的地址在0xcabeb000(約3G+171M)處,符合前文所述的內(nèi)存布局。

  接下來,我們討論Linux設(shè)備驅(qū)動究竟怎樣訪問外設(shè)的I/O端口(寄存器)。

  幾乎每一種外設(shè)都是通過讀寫設(shè)備上的寄存器來進(jìn)行的,通常包括控制寄存器、狀態(tài)寄存器和數(shù)據(jù)寄存器三大類,外設(shè)的寄存器通常被連續(xù)地編址。根據(jù)CPU體系結(jié)構(gòu)的不同,CPU對IO端口的編址方式有兩種:

 ?。?)I/O映射方式(I/O-mapped)

  典型地,如X86處理器為外設(shè)專門實現(xiàn)了一個單獨的地址空間,稱為"I/O地址空間"或者"I/O端口空間",CPU通過專門的I/O指令(如X86的IN和OUT指令)來訪問這一空間中的地址單元。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
關(guān)于驅(qū)動開發(fā)中mmap函數(shù)的實現(xiàn)
ARM32 內(nèi)核內(nèi)存布局
linux內(nèi)存映射相關(guān)知識點
Linux設(shè)備驅(qū)動程序之內(nèi)存與I/O訪問(一)
ARM Linux的啟動過程這一切的開始Linux內(nèi)核(討論內(nèi)核在自解壓后如何在物理內(nèi)存中執(zhí)行自引導(dǎo)直到能夠在虛擬內(nèi)存中執(zhí)行用C編寫的通用內(nèi)核代碼)
Linux內(nèi)核空間內(nèi)存管理(一):內(nèi)存尋址、內(nèi)存管理機(jī)制綜述
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服