欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Linux驅動(dòng)IO篇——mmap操作

前言

平時(shí)我們寫(xiě)Linux驅動(dòng)和用戶(hù)空間交互時(shí),都是通過(guò)copy_from_user把用戶(hù)空間傳過(guò)來(lái)的數據進(jìn)行拷貝,為什么要這么做呢?

因為用戶(hù)空間是不能直接內核空間數據的,他們映射的是不同的地址空間,只能先將數據拷貝過(guò)來(lái),然后再操作。

如果用戶(hù)空間需要傳幾MB的數據給內核,那么原來(lái)的拷貝方式顯然效率特別低,也不太現實(shí),那怎么辦呢?

想想,之所以要拷貝是因為用戶(hù)空間不能直接訪(fǎng)問(wèn)內核空間,那如果可以直接訪(fǎng)問(wèn)內核空間的buffer,是不是就解決了。

簡(jiǎn)單來(lái)說(shuō),就是讓一塊物理內存擁有兩份映射,即擁有兩個(gè)虛擬地址,一個(gè)在內核空間,一個(gè)在用戶(hù)空間。關(guān)系如下:

通過(guò)mmap映射就可以實(shí)現。

應用層

應用層代碼很簡(jiǎn)單,主要就是通過(guò)mmap系統調用進(jìn)行映射,然后就可以對返回的地址進(jìn)行操作。

char * buf;

/* 1. 打開(kāi)文件 */

fd = open('/dev/hello', O_RDWR);

if (fd == -1)

{

printf('can not open file /dev/hello\n');

return -1;

}

/* 2. mmap

* MAP_SHARED  : 多個(gè)APP都調用mmap映射同一塊內存時(shí), 對內存的修改大家都可以看到。

*               就是說(shuō)多個(gè)APP、驅動(dòng)程序實(shí)際上訪(fǎng)問(wèn)的都是同一塊內存

* MAP_PRIVATE : 創(chuàng )建一個(gè)copy on write的私有映射。

*               當APP對該內存進(jìn)行修改時(shí),其他程序是看不到這些修改的。

*               就是當APP寫(xiě)內存時(shí), 內核會(huì )先創(chuàng )建一個(gè)拷貝給這個(gè)APP,

*               這個(gè)拷貝是這個(gè)APP私有的, 其他APP、驅動(dòng)無(wú)法訪(fǎng)問(wèn)。

*/

buf =  mmap(NULL, 1024*8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

mmap的第一個(gè)參數是想要映射的起始地址,通常設置為NULL,表示由內核來(lái)決定該起始地址。

第二參數是要映射的內存空間的大小。

第三個(gè)參數PROT_READ | PROT_WRITE表示映射后的空間是可讀可寫(xiě)的。

第四個(gè)參數可填MAP_SHARED或MAP_PRIVATE:

MAP_SHARED:多個(gè)APP都調用mmap映射同一塊內存時(shí), 對內存的修改大家都可以看到。就是說(shuō)多個(gè)APP、驅動(dòng)程序實(shí)際上訪(fǎng)問(wèn)的都是同一塊內存。

MAP_PRIVATE:創(chuàng )建一個(gè)copy on write的私有映射。當APP對該內存進(jìn)行修改時(shí),其他程序是看不到這些修改的。就是當APP寫(xiě)內存時(shí), 內核會(huì )先創(chuàng )建一個(gè)拷貝給這個(gè)APP,這個(gè)拷貝是這個(gè)APP私有的, 其他APP、驅動(dòng)無(wú)法訪(fǎng)問(wèn)。

驅動(dòng)層

驅動(dòng)層主要是實(shí)現mmap接口,而mmap接口的實(shí)現,主要是調用了remap_pfn_range函數,函數原型如下:int remap_pfn_range(

struct vm_area_struct *vma, 

unsigned long addr, 

unsigned long pfn, 

unsigned long size, 

pgprot_t prot);

vma:描述一片映射區域的結構體指針

addr:要映射的虛擬地址起始地址

pfn:物理內存所對應的頁(yè)框號,就是將物理地址除以頁(yè)大小得到的值

size:映射的大小

prot:該內存區域的訪(fǎng)問(wèn)權限

驅動(dòng)主要步驟:

1、使用kmalloc或者kzalloc函數分配一塊內存kernel_buf,因為這樣分配的內存物理地址是連續的,mmap后應用層會(huì )對這一個(gè)基地址去訪(fǎng)問(wèn)這塊內存。

2、實(shí)現mmap函數

static int hello_drv_mmap(struct file *file, struct vm_area_struct *vma)

{

/* 獲得物理地址 */

unsigned long phy = virt_to_phys(kernel_buf);//kernel_buf是內核空間分配的一塊虛擬地址空間

/* 設置屬性:cache, buffer*/

vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);

/* map */

if(remap_pfn_range(vma, vma->vm_start, phy>>PAGE_SHFIT,

vma->vm_end - vma->start, vma->vm_page_prot)){

printk('mmap remap_pfn_range failed\n');

return -ENOBUFS;

}

return 0;

}

static struct file_operations my_fops = {

.mmap = hello_drv_mmap,

};

1、通過(guò)virt_to_phys將虛擬地址轉為物理地址,這里的kernel_buf是內核空間的一塊虛擬地址空間

2、設置屬性:不使用cache,使用buffer

3、映射:通過(guò)remap_pfn_range函數映射,phy>>PAGE_SHIFT其實(shí)就是按page映射,除了這個(gè)參數,其他的起始地址、大小和權限都可以由用戶(hù)在系統調用函數中指定。

當應用層調用mmap后,就會(huì )調用到驅動(dòng)層的mmap函數,最終應用層的虛擬地址和驅動(dòng)中的物理地址就建立了映射關(guān)系,應用層也就可以直接訪(fǎng)問(wèn)驅動(dòng)的buffer了。

來(lái)源:嵌入式Linux充電站

溫馨提示:

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
mmap內存映射操作
Linux內核開(kāi)發(fā)之內存與I/O訪(fǎng)問(wèn)(四)
mmap詳解
關(guān)于驅動(dòng)開(kāi)發(fā)中mmap函數的實(shí)現
Linux設備驅動(dòng)之mmap設備操作
Linux內核虛擬內存管理之匿名映射缺頁(yè)異常分析
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久