Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316769
  • 博文数量: 89
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 691
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-20 16:58
文章分类

全部博文(89)

文章存档

2017年(1)

2016年(35)

2015年(53)

我的朋友

分类: LINUX

2015-09-29 09:47:58

 参考资料:

    Uio即是user space I/O,用户空间驱动的简称, 可以运行在用户空间写硬件驱动。
    
    硬件设备可以根据功能分为网络设备,块设备,字符设备,或者根据与CPU相连的方式 分为PCI设备,USB设备等。它们被不同的内核子系统支持。这些标准的设备的驱动编写 较为容易而且容易维护。很容易加入主内核源码树。但是,又有很多设备难以划分到这些子系统中,比如I/O卡,现场总线接口或者定制的FPGA。 
    
    通常这些非标准设备的驱动被实现为字符驱动。这些驱动使用了很多内核内部函数和宏。 而这些内部函数和宏是变化的。这样驱动的编写者必须编写一个完全的内核驱动,而且一直维护这些代码。而且这些驱动进不了主内核源码。于是就出现了用户空间I/O框架(Userspace I/O framework)。 

UIO 的工作原理:
    UIO分成2个部分,主要是内核部分和用户空间部分, 在内核部分主要是实现硬件寄存器的内存映射(struct uio_info -> struct uio_mem)及读写操作, 在用户空间部分,将uio设备的uio_mem映射到本地(mmap), 这样就可以实现在用户空间访问硬件设备寄存器的目的, 再通过设备的控制逻辑,就可以实现硬件设备的驱动。 
    
    一个UIO设备驱动的主要任务有两个:
         
        1. 存取设备的内存 UIO 核心实现了mmap()可以处理物理内存(physical memory),逻辑内存(logical memory),虚拟内存(virtual memory)。UIO驱动的编写是就不需要再考虑这些繁琐的细节。 如果有些设备的总线不是PCI总线, 那么仍需要做相关的处理   
        
        2. 处理设备产生的中断 对于设备中断的应答必须在内核空间进行。所以在内核空间有一小部分代码 用来应答中断和禁止中断,但是其余的工作全部留给用户空间处理。  

              如果用户空间要等待一个设备中断,它只需要简单的阻塞在对 /dev/uioX的read()操作上。当设备产生中断时,read()操作立即返回。UIO 也实现了poll()系统调用,你可以使用  select()来等待中断的发生。select()有一个超时参数可以用来实现有限时间内等待中断。   

            对设备的控制还可以通过/sys/class/uio下的各个文件的读写来完成。你注册的uio设备将会出现在该目录下。假如你的uio设备是uio0那么映射的设备内存文件出现在 /sys/class/uio/uio0/maps/mapX,对该文件的读写就是对设备内存的读写。  

        如下的图描述了uio驱动的内核部分,用户空间部分,和uio 框架以及内核内部函数的关系。     

UIO的具体实现 
    UIO内核部分 
    一个uio驱动的注册过程简单点说有两个步骤:
        1. 初始化设备相关的 uio_info结构。 uio_info包括了name, open(),release(), mmap(),  struct uio_mem等 
        
        2. 调用uio_register_device 分配并注册一个uio设备。 uio核心字符设备注册的函数有: uio_open,uio_fasync,uio_release,uio_poll,uio_read, uio_write 当用户空间访问该uio设备的时候, 就会调用这些接口 
        
        3, Uio核心除了完成相关的维护工作外,还调用了注册在uio_info中的相关方法进行初始化。 

    Uio用户空间部分
    通过open,mmap, write read等函数与内核空间交互, 间接和硬件的寄存器交互。 在内核空间驱动中所描述的内存区域uio_mem可以通过mmap()调用映射到用户空间中。 同时根据设备的使用规则,就可以编写驱动了 
    
    设备中断处理
     在__uio_register_device中,为uio设备注册了统一的中断处理函数uio_interrupt, 在该函数中,调用了uio设备自己提供的中断处理函数handler(uio_info结构中)。 并调用了uio_event_notify函数对uio设备的中断事件计数器(listener)增一, 通知各个读进程 “有数据可读”。每个uio设备的中断处理函数都是单独注册的。 
    
    用户空间调用poll/(uio_poll)操作判断是否有数据可读的依据就是 listener中的中断事件计数值(event_count)和uio设备中的中断事件计数器值不一致(前者小于后者)。因为listener的值除了在执行文件打开操作时被置为被赋值外,只在uio_read操作中被更新为uio设备的中断事件计数器值。               
阅读(5710) | 评论(0) | 转发(0) |
0

上一篇:常用存储接口简介

下一篇:iscsi简介

给主人留下些什么吧!~~