对LDD3中,重映射特定的IO区域的迷惑
对于操作一个设备的IO端口,或者IO内存。一共有三种办法。
(1) 一种方法是:直接使用IO端口操作函数:在设备打开或驱动模块被加载时申请IO端口区域,之后使用inb(),outb()等进行端口访问
(2)将IO端口映射为内存进行访问,在设备打开或驱动模块被加载时,申请IO端口区域并使用ioport_map()映射到内存,之后使用IO内存的函数进行端口访问
(3)首先调用request_mem_region()申请资源,接着将寄存器地址通过ioremap()映射到内核空间的虚拟地址,之后就可以Linux设备访问编程接口访问这些寄存器了
当然释放是有相应的函数的。
如果是对IO内存访问,通过ioremap()映射,那返回的就是一个虚拟地址。
当要把IO内存映射到用户空间的时候。
一般是调用
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot);
int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long phys_addr, unsigned long size, pgprot_t prot);
这两个函数。
其中第三个参数 unsigned long pfn,让我很迷惑
这是一个把内核空间内存映射到用户空间的一个简单例子,在LDD3上有
static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma)
{
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
vma->vm_ops = &simple_remap_vm_ops;
simple_vma_open(vma);
return 0;
}
他的第三个参数 传的是 vma->vm_pgoff 按照书上写的关于vm_area_struct结构解释。这个参数是以页为单位,文件中该区域的偏移量。我理解的是 一个应用程序应该有多个VMA,这个vm_pgoff 是当前VM在这个程序或者进程或者文件中的偏移量
而 remap_pfn_page 中第三个参数 写的是 与物理内存对应的页帧号。也就是说 把所有的物理内存都分页 然后各个挂在不同的队列上,比如空闲队列等等。这个PFN也可以说是这个物理地址在内存中的偏移量。
看了别人写的一个文章,好像Linux内核把所有的物理内存都当成了一个文件求了一次偏移,然后从新对vm_pgoff赋值。一开始vm_pgoff跟物理内存本来是没有关系的。后来内核搞得有关系了。
不知我这样理解对吗
而在P424页,重映射特定的IO区域 这一节
举例中
映射一个simple_region_size 字节的区域, 在物理地址 simple_region_start(应当是页对齐的) 开始:
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
unsigned long physical = simple_region_start + off;
unsigned long vsize = vma->vm_end - vma->vm_start;
unsigned long psize = simple_region_size - off;
if (vsize > psize)
return -EINVAL; /* spans too high */
remap_pfn_range(vma, vma_>vm_start, physical, vsize, vma->vm_page_prot);
而在这里我觉得不是物理了,再次看不懂vm_pgoff 的含义 尤其是最后一句 .麻烦高手说说自己的见解,能让我茅塞顿开。。谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
顶顶
http://www.yiwuen.com/wholesale-office-equipment_c48