Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1732282
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类:

2012-06-16 09:06:09


    一.设备号
    对字符设备的访问是通过文件系统内的设备名称来访问的,设备名称位于目录/dev下.为了便于系统管理,设置了和设备名称一一对应的设备号,它分为主设备 号和次设备号.通常来说,主设备号标示了设备对应的驱动程序,次设备号则用来分辨拥有同一个主设备号的的各个不同设备.
    在内核中,设备号使用类型dev_t来保存,它包括了主设备号和次设备号.dev_t是一个32位的整数,其中的12位用来标示主设备号,其余的20位用来标示次设备号.我们可以使用两个宏来获得设备的主设备号及次设备号:
    MAJOR(dev_t dev_id);
    MINOR(dev_t dev_id);
    将主设备号和次设备号转换为dev_t类型,则可以使用下面的宏:
    MKDEV(int major, int minor);
    其中,major为主设备号,minor为次设备号.
    二.分配设备号
    在建立一个字符设备之前.首先要申请设备号,完成该功能的函数有两个,都包含在头文件中.下面分别来看这两个文件:
    1.int register_chrdev_region(dev_t first, unsigned int count, char *name);
    其中, first为要分配的设备编号范围的起始值,经常被置零.count则是所请求的连续设备编号的个数,这意味着只能申请连续的设备编号.
    2.int alloc_chrdev_region(dev_t *dev, unsigned firstminor, int count, char *name);
    其中dev用于保存申请成功后动态分配的第一个设备号, firstminor则是请求使用的第一个次设备号.其余与上个函数相同.
    三.定义并初始化file_operations结构体.
    file_operations结构体用于连接设备号和驱动程序的操作.在该结构体的内部包含了一组函数指针,这些函数用来实现系统调用.通常情况下,要注册如下的几个函数:
    1.struct module *owner:用来指向拥有该结构体的模块.
    2.ssize_t read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops):用来从设备中读取数据.其中:
    filp为文件属性结构体指针.
    buf为用户态函数使用的字符内存缓冲.
    count为要读取的数据数.
    f_ops为文件指针的偏移量.
    2.ssize_t write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops):用来向设备输入数据.各函数的含义与上个函数相同.
    3.int open(struct inode *inode, struct file *):该函数用来打开一个设备文件.
    4.int release(struct inode *inode, struct file *):该函数用来关闭一个设备文件.
    该结构体的初始化形式如下例:
    struct file_operations scull_fops = {
        .owner = THIS_MODULE,
        .read = read,
        .write = write,
    .open = open,
    .release = release,
    }
    四.字符设备的注册.
    内核内部使用struct cdev结构来表示字符设备.在内核调用设备的操作之前,必须分配或注册一个或者多个该结构体.该结构体包含在头文件中.一般的步骤如下:
    首先定义该结构体:
    struct cdev my_cdev;
    然后即可以初始化该结构,使用如下的函数初始化:
    int cdev_init(struct cdev *dev, struct file_operations *fops).
    然后定义该结构体中的一个所有者字段:
    my_cdev.owner = THIS_MODULE;
    最后即可以向模块添加该结构体:
    int cdev_add(struct cdev *dev, dev_t dev_num, usigned int count).其中dev是cdev结构体,dev_num是该设备对应的第一个设备编号, count则是与该设备关联的设备编号数量.
    五.移除字符设备
    void cdev_del(struct cdev *dev);
    六.注销设备号.
    unregister_chrdev_region(dev_t first, unsigned int count);
    以上两个函数一般用于模块出口函数中.
               
阅读(457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~