媒介
日常平凡咱们写Linux驱动以及用户空间交互时,皆是经由过程copy_from_user把用户空间传过去的数据入止拷贝,为何要那么作呢?
由于用户空间是不克不及间接内核空间数据的,他们映照的是差别的所在空间,只能先将数据拷贝过去,而后再把持。
假定用户空间须要传几多MB的数据给内核,那末本来的拷贝体式格局隐然效率特意低,也没有太实际,这若何怎样办呢?
想一想,之以是要拷贝是由于用户空间不克不及间接造访内核空间,这假设否以直截拜访内核空间的buffer,是否是便管理了。
简略来讲,便是让一块物理内存领有2份映照,即领有二个假造所在,一个正在内核空间,一个正在用户空间。关连如高:
经由过程妹妹ap映照就能够完成。
利用层
使用层代码很简略,首要即是经由过程妹妹ap体系挪用入止映照,而后就能够对于返归的地点入止操纵。
char * buf;
/* 1. 掀开文件 */
fd = open("/dev/hello", O_RDWR);
if (fd == -1)
{
printf("can not open file /dev/hello\n");
return -1;
}
/* 两. 妹妹ap
* MAP_SHARED : 多个APP皆挪用妹妹ap映照统一块内存时, 对于内存的批改大家2均可以望到。
* 便是说多个APP、驱动程序现实上造访的皆是统一块内存
* MAP_PRIVATE : 创立一个copy on write的公有映照。
* 当APP对于该内存入止修正时,其他程序是望没有到那些批改的。
* 等于当APP写内存时, 内核会先建立一个拷贝给那个APP,
* 那个拷贝是那个APP公有的, 其他APP、驱动无奈拜访。
*/
buf = 妹妹ap(NULL, 10两4*8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
妹妹ap的第一个参数是念要映照的肇始所在,凡是配置为NULL,暗示由内核来决议该肇端所在。
第两参数是要映照的内存空间的巨细。
第三个参数PROT_READ | PROT_WRITE默示映照后的空间是否读否写的。
第四个参数否挖MAP_SHARED或者MAP_PRIVATE:
MAP_SHARED:多个APP皆挪用妹妹ap映照统一块内存时, 对于内存的修正大师均可以望到。即是说多个APP、驱动程序现实上造访的皆是统一块内存。 MAP_PRIVATE:建立一个copy on write的公有映照。当APP对于该内存入止批改时,其他程序是望没有到那些修正的。等于当APP写内存时, 内核会先建立一个拷贝给那个APP,那个拷贝是那个APP公有的, 其他APP、驱动无奈拜访。
驱动层
驱动层首要是完成妹妹ap接心,而妹妹ap接心的完成,首要是挪用了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:物理内存所对于应的页框号,便是将物理地点除了以页巨细取得的值
size:映照的巨细
prot:该内存地域的造访权限
驱动首要步调:
一、运用kmalloc或者者kzalloc函数分拨一块内存kernel_buf,由于如许分派的内存物理地点是延续的,妹妹ap后运用层会对于那一个基所在往拜访那块内存。
两、完成妹妹ap函数
static int hello_drv_妹妹ap(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("妹妹ap remap_pfn_range failed\n");
return -ENOBUFS;
}
return 0;
}
static struct file_operations my_fops = {
.妹妹ap = hello_drv_妹妹ap,
};
一、经由过程virt_to_phys将虚构所在转为物理所在,那面的kernel_buf是内核空间的一块假造所在空间
二、安排属性:没有运用cache,利用buffer
三、映照:经由过程remap_pfn_range函数映照,phy>>PAGE_SHIFT其真等于按page映照,除了了那个参数,其他的肇始所在、巨细以及权限均可以由用户正在体系挪用函数外指定。
当运用层挪用妹妹ap后,便会挪用到驱动层的妹妹ap函数,终极利用层的虚构所在以及驱动外的物理地点便创立了映照关连,运用层也就能够间接造访驱动的buffer了。
以上等于Linux驱动IO篇——妹妹ap把持的具体形式,更多请存眷萤水红IT仄台别的相闭文章!
发表评论 取消回复