歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> request_mem_region 申請內存函數講解

request_mem_region 申請內存函數講解

日期:2017/3/1 10:12:47   编辑:Linux編程

request_mem_region
這裡我們看到的那個 request_mem_region 是申請 I/O 內存用的 . 申請了之後 , 還需要使用 ioremap 或者 ioremap_nocache 函數來映射 .對於 request_region, 三個參數 start,n,name 表示你想使用從 start 開始的 size 為 n 的 I/O port 資源 ,name 自然就是你的名字了

以我們家 Intel 為代表的 i386 系列處理器中 , 內存和外部 IO 是獨立編址獨立尋址的 , 於是有一個地址空間叫做內存空間 , 另有一個地址空間叫做 I/O 空間 . 也就是說 , 從處理器的角度來說 ,i386 提供了一些單獨的指令用來訪問 I/O 空間 . 換言之 , 訪問 I/O 空間和訪問普通的內存得使用不同的指令 . 而在一些玩嵌入式的處理器中 , 比如 PowerPC, 他們家就只使用一個空間 , 那就是內存空間 , 那像這種情況 , 外設的 I/O 端口的物理地址就被映射到內存地址空間中 , 這就是傳說中的 Memory-mapped, 內存映射 . 而我們家那種情況 , 外設的 I/O 端口的物理地址就被映射到 I/O 地址空間中 , 這就是傳說中的 I/O-mapped, 即 I/O 映射 .

要使用 I/O 內存首先要申請 , 然後要映射 , 而要使用 I/O 端口首先要申請 , 或者叫請求 , 對於 I/O 端口的請求意思是讓內核知道你要訪問這個端口 , 這樣內核知道了以後它就不會再讓別人也訪問這個端口了 . 畢竟這個世界僧多粥少啊 . 申請 I/O 端口的函數是 request_region, 這個函數來自 include/linux/ioport.h,

/* Convenience shorthand with allocation */

#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))

#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))

#define rename_region(region, newname) do { (region)->name = (newname); } while (0)


extern struct resource * __request_region(struct resource *,

resource_size_t start,

resource_size_t n, const char *name);


這裡我們看到的那個 request_mem_region 是申請 I/O 內存用的 . 申請了之後 , 還需要使用 ioremap 或者 ioremap_nocache 函數來映射 .對於 request_region, 三個參數 start,n,name 表示你想使用從 start 開始的 size 為 n 的 I/O port 資源 ,name 自然就是你的名字了 .


這兩個函數在內核的驅動中幾乎都會出現,例如ohci-at91.c裡面的probe函數:

view plaincopy to clipboardprint?
hcd->rsrc_start = pdev->resource[0].start;
hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed\n");
retval = -EBUSY;
goto err1;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed\n");
retval = -EIO;
goto err2;
}
hcd->rsrc_start = pdev->resource[0].start;
hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed\n");
retval = -EBUSY;
goto err1;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed\n");
retval = -EIO;
goto err2;
}

這樣的好處是寄存器訪問方式比較好看,只要加個偏移地址就可以了。

不過我有時候又不太喜歡用。因為這兩句話說到底是為了訪問寄存器用的。相當於獲得寄存器虛擬地址。但是我們在初始化的時候虛擬地址就已經映射過了,所以我喜歡直接操作寄存器的虛擬地址

Copyright © Linux教程網 All Rights Reserved