zoukankan      html  css  js  c++  java
  • ioremap&buddy system

    生死契阔,与子成说,执子之手,与子携老

    一、ioremap

    1.参考:

    理解

    (1)http://www.linuxidc.com/Linux/2011-04/34295.htm

    代码过程

    (1)http://wenku.baidu.com/link?url=ol3FJuVkhMrs80Q8wbGsFjTwclEMKZdN2fzsaqggSnGEPyqLuWOI0YDvXil0P2cp5UHQrd4Za7BWEuQGGN2NKrhbFYxxUqgFG-wMM5uFTN_

    (2)

    http://hi.baidu.com/zengzhaonong/item/a2dc5eb4f805fe9719469726

    ioremap代码参数

    (1)

    http://baike.baidu.com/link?url=vfrIFDTnwR1aW_yDOkVLvnoQci4TwmD8jT28m9KSdTL5LEnyfG_nAB1Wcb9aozQSnjrJNMOu28qbL83SmdWxsK

    (2)

    http://blog.csdn.net/fuyjlu/article/details/5039782

    (3)

    http://www.hh010.com/os/html/47-2/2811.htm

    2.实现

    (1) Linux在io.h头文件中声明了函数ioremap(),用来将I/O内存资源的物理地 址映射到核心虚地址空间(3GB-4GB)中,原型如下:

    void * ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);

      iounmap函数用于取消ioremap()所做的映射,原型如下:

    void iounmap(void * addr);

      这两个函数都是实现在mm/ioremap.c文件中。

    (2)

      在将I/O内存资源的物理地址映射成核心虚地址后,理论上讲我们就可以象读写RAM那样直接读写I/O内存资源了。为了保证驱动程序的跨平台的 可移植性,我们应该使用Linux中特定的函数来访问I/O内存资源,而不应该通过指向核心虚地址的指针来访问。如在x86平台上,读写I/O的函数如下 所示:

    #define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
    #define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
    #define readl(addr) (*(volatile unsigned int *) __io_virt(addr))

    #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
    #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
    #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))

    #define memset_io(a,b,c) memset(__io_virt(a),(b),(c))
    #define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))
    #define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))

    (3)

    在内核驱动程序的初始化阶段,通过ioremap()将物理地址映射到内核虚拟空间;在驱动程序的mmap系统调用中,使用remap_page_range()将该块ROM映射到用户虚拟空间。这样内核空间和用户空间都能访问这段被映射后的虚拟地址。

    remap_page_range函数的功能是构造用于映射一段物理地址的新页表,实现了内核空间与用户空间的映射,其原型如下:

    int remap_page_range(vma_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_tprot); 

    (4)

    在X86体系下的,CPU的物理地址和PCI总线地 址共用一个空间。linux内核将3G-4G的虚拟地址固定映射到了物理地址的0-1G的地方。但是如果外围设备上的地址高于1G,例如某块PCI卡分配 到了一个高于1G的地址,就需要调用ioremap来重新建立该物理地址(总线地址)和虚拟地址之间的映射。这个映射过程是这样的:在ioremap.c 文件的__ioremap函数中首先对将来映射的物理地址进行检查,也就是不能重新映射640K-1M地址(由于历史的原因,物理地址640k到1M空间 被保留给了显卡),普通的ram地也不能重新被映射。之后调用get_vm_area获得可用的虚拟地址,然后根这虚拟地址和欲映射的物理地址修改页表, 之后内核就可以用这个虚拟地址来访问映射的物理地址了。

     二、buddy system

     

  • 相关阅读:
    vue动态设置页面title方法
    laravel 只有/login路由403,如何解决
    vue-cli中使用rem,vue自适应
    Vuex的全面用法总结
    template or render function not defined.
    Laravel Mix编译前端资源
    laravel学习:模块化caffeinated
    laravel学习:php写一个简单的ioc服务管理容器
    Aspose Cells dll 实现数据简单下载
    sessionStorage 的使用
  • 原文地址:https://www.cnblogs.com/yaolei/p/3415696.html
Copyright © 2011-2022 走看看