日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人
[導(dǎo)讀]我們知道,linux系統(tǒng)中用戶空間和內(nèi)核空間是隔離的,用戶空間程序不能隨意的訪問內(nèi)核空間數(shù)據(jù),只能通過中斷或者異常的方式進(jìn)入內(nèi)核態(tài)

1.開場(chǎng)白

  • 環(huán)境:處理器架構(gòu):arm64內(nèi)核源碼:linux-5.11ubuntu版本:20.04.1代碼閱讀工具:vim ctags cscope
我們知道,linux系統(tǒng)中用戶空間和內(nèi)核空間是隔離的,用戶空間程序不能隨意的訪問內(nèi)核空間數(shù)據(jù),只能通過中斷或者異常的方式進(jìn)入內(nèi)核態(tài),一般情況下,我們使用copy_to_user和copy_from_user等內(nèi)核api來實(shí)現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)拷貝,但是像顯存這樣的設(shè)備如果也采用這樣的方式就顯的效率非常底下,因?yàn)橛脩艚?jīng)常需要在屏幕上進(jìn)行繪制,要消除這種復(fù)制的操作就需要應(yīng)用程序直接能夠訪問顯存,但是顯存被映射到內(nèi)核空間,應(yīng)用程序是沒有訪問權(quán)限的,如果顯存也能同時(shí)映射到用戶空間那就不需要拷貝操作了,于是字符設(shè)備中提供了mmap接口,可以將內(nèi)核空間映射的那塊物理內(nèi)存再次映射到用戶空間,這樣用戶空間就可以直接訪問不需要任何拷貝操作,這就是我們今天要說的0拷貝技術(shù)。
下面是正常情況下用戶空間和內(nèi)核空間數(shù)據(jù)訪問圖示:

2. 體驗(yàn)一下

首先我們通過一個(gè)例子來感受一下:
驅(qū)動(dòng)代碼:
注:驅(qū)動(dòng)代碼中使用misc框架來實(shí)現(xiàn)字符設(shè)備,misc框架會(huì)處理如創(chuàng)建字符設(shè)備,創(chuàng)建設(shè)備等通用的字符設(shè)備處理,我們只需要關(guān)心我們的實(shí)際的邏輯即可(內(nèi)核中大量使用misc設(shè)備框架來使用字符設(shè)備操作集如ioctl接口,像實(shí)現(xiàn)系統(tǒng)虛擬化kvm模塊,實(shí)現(xiàn)安卓進(jìn)程間通信的binder模塊等)。
0copy_demo.c
#include
#include
#include
#include
#include
#define MISC_DEV_MINOR 5
static char *kbuff;
static ssize_t misc_dev_read(struct file *filep, char __user *buf, size_t count, loff_t *offset)
{
int ret;
size_t len = (count > PAGE_SIZE ? PAGE_SIZE : count);
pr_info("###### %s:%d kbuff:%s ######\n", __func__, __LINE__, kbuff);
ret = copy_to_user(buf, kbuff, len);  //這里使用copy_to_user  來進(jìn)程內(nèi)核空間到用戶空間拷貝
return len - ret;
}
static ssize_t misc_dev_write(struct file *filep, const char __user *buf, size_t count, loff_t *offset)
{
pr_info("###### %s:%d ######\n", __func__, __LINE__);
return 0;
}
static int misc_dev_mmap(struct file *filep, struct vm_area_struct *vma)
{
int ret;
unsigned long start;
start = vma->vm_start;
ret =  remap_pfn_range(vma, start, virt_to_phys(kbuff) >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot); //使用remap_pfn_range來映射物理頁(yè)面到進(jìn)程的虛擬內(nèi)存中  virt_to_phys(kbuff) >> PAGE_SHIFT作用是將內(nèi)核的虛擬地址轉(zhuǎn)化為實(shí)際的物理地址頁(yè)幀號(hào)  創(chuàng)建頁(yè)表的權(quán)限為通過mmap傳遞的 vma->vm_page_prot   映射大小為1頁(yè)
return ret;
}
static long misc_dev_ioctl(struct file *filep, unsigned int cmd, unsigned long args)
{
pr_info("###### %s:%d ######\n", __func__, __LINE__);
return 0;
}
static int misc_dev_open(struct inode *inodep, struct file *filep)
{
pr_info("###### %s:%d ######\n", __func__, __LINE__);
return 0;
}
static int misc_dev_release(struct inode *inodep, struct file *filep)
{
pr_info("###### %s:%d ######\n", __func__, __LINE__);
return 0;
}
static struct file_operations misc_dev_fops = {
.open = misc_dev_open,
.release = misc_dev_release,
.read = misc_dev_read,
.write = misc_dev_write,
.unlocked_ioctl = misc_dev_ioctl,
.mmap = misc_dev_mmap,
};
static struct miscdevice misc_dev = {
MISC_DEV_MINOR,
"misc_dev",
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關(guān)閉