Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1696319
  • 博文数量: 511
  • 博客积分: 967
  • 博客等级: 准尉
  • 技术积分: 2560
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-06 14:19
文章分类

全部博文(511)

文章存档

2016年(11)

2015年(61)

2014年(257)

2013年(63)

2012年(119)

分类: Android平台

2015-01-25 01:09:15

 UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由搜集整理)

    UIO(Userspace I/O)是运行在用户空间的I/O技术。Linux系统中一般的驱动设备都是运行在内核空间,而在用户空间用应用程序调用即可,而UIO则是将驱动的很少一部分运行在内核空间,而在用户空间实现驱动的绝大多数功能!使用UIO可以避免设备的驱动程序需要随着内核的更新而更新的问题.通过UIO的运行原理图可以看出,用户空间下的驱动程序比运行在内核空间的驱动要多得多,UIO框架下运行在内核空间的驱动程序所做的工作很简单,常做的只有两个:分配和记录设备需要的资源和注册uio设备和必须在内核空间实现的小部分中断应答函数,经过实践表明后面的工作也是可以省略的!我们认为uio内核空间的程序所做的越少越好,在用户空间能完成的我们就不需要放在内核空间做(比如说响应中断),这样假如内核有变化,uio框架中的驱动维护也是比较简单。

Linux UIO 驱动模型(图)

    Linux UIO 驱动模型(图)

  uio驱动的内核部分,用户空间部分,和uio 框架以及内核内部函数的关系图


uio驱动的内核部分,用户空间部分,和uio 框架以及内核内部函数的关系图


uio驱动重要的数据结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
struct uio_device {
    struct module       *owner;
    struct device       *dev; //在__uio_register_device中初始化
    int         minor; // 次设备id号,uio_get_minor
    atomic_t        event; //中断事件计数
    struct fasync_struct    *async_queue;//该设备上的异步等待队列// 
                                                               // 关于 “异步通知“ //参见LDD3第六章
    wait_queue_head_t   wait; //该设备上的等待队列,在注册设备时(__uio_register_device)初始化
    int         vma_count;
    struct uio_info     *info;// 指向用户注册的uio_info,在__uio_register_device中被赋值的
    struct kobject      *map_dir;
    struct kobject      *portio_dir;
};  
      /*
 * struct uio_info - UIO device capabilities
 * @uio_dev:        the UIO device this info belongs to
 * @name:       device name
 * @version:        device driver version
 * @mem:        list of mappable memory regions, size==0 for end of list
 * @port:       list of port regions, size==0 for end of list
 * @irq:        interrupt number or UIO_IRQ_CUSTOM
 * @irq_flags:      flags for request_irq()
 * @priv:       optional private data
 * @handler:        the device's irq handler
 * @mmap:       mmap operation for this uio device
 * @open:       open operation for this uio device
 * @release:        release operation for this uio device
 * @irqcontrol:     disable/enable irqs when 0/1 is written to /dev/uioX
 */     
struct uio_info { 
    struct uio_device   *uio_dev; // 在__uio_register_device中初始化
    const char      *name; // 调用__uio_register_device之前必须初始化
    const char      *version; //调用__uio_register_device之前必须初始化
    struct uio_mem      mem[MAX_UIO_MAPS];
    struct uio_port     port[MAX_UIO_PORT_REGIONS];
    long            irq; //分配给uio设备的中断号,调用__uio_register_device之前必须初始化
    unsigned long       irq_flags;// 调用__uio_register_device之前必须初始化
    void            *priv; //
    irqreturn_t (*handler)(int irq, struct uio_info *dev_info); //uio_interrupt中调用,用于中断处理
                                                                // 调用__uio_register_device之前必须初始化
    int (*mmap)(struct uio_info *info, struct vm_area_struct *vma); //在uio_mmap中被调用,
                                                                // 执行设备打开特定操作
    int (*open)(struct uio_info *info, struct inode *inode);//在uio_open中被调用,执行设备打开特定操作
    int (*release)(struct uio_info *info, struct inode *inode);//在uio_device中被调用,执行设备打开特定操作
    int (*irqcontrol)(struct uio_info *info, s32 irq_on);//在uio_write方法中被调用,执行用户驱动的
                                                        //特定操作。
};

UIO的内核部分和用户空间的工作

内核空间

UIO的少量运行在内核空间的驱动所做的工作有哪些呢?

(1)分配和记录设备需要的资源和注册uio设备

在设备的探测函数中:

- 使能PCI 设备

- 申请资源

- 读取并记录配置信息

- 注册uio设备// uio_register_device()

// uio_8139d_pci_probe & uio_8139d_handler

(2)必须*在内核空间实现的小部分中断应答函数

用户空间的关键操作

1关键操作

2.响应硬件中断

1
2
3
4
5
6
7
8
9
10
int32_t irq_count;
int fd = open("/dev/uio0", O_RDWR);
/* Map the register regions to proccess's virtual memspace */
void * access = mmap(NULL, 4096,
// 寄存器的读写操作,可用过普通内存读写的方式完成
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);// [1]
while (read(fd, &irq_count, 4) == 4) {[2]
printf("Interrupt number %d\n", irq_count);
}

阅读(4620) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~