Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121470
  • 博文数量: 15
  • 博客积分: 1581
  • 博客等级: 上尉
  • 技术积分: 411
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-29 09:48
文章分类

全部博文(15)

文章存档

2011年(8)

2010年(7)

我的朋友

分类: LINUX

2010-08-08 15:16:17

《linux 设备驱动》---第三章:字符驱动 一
 
学习目的:编写一个完整的字符设备驱动。
学习成果:完成一个字符驱动模块。

scull( Simple Character Utility for Loading Localities). scull 是一个字符驱动, 操作
一块内存区域好像它是一个设备. 在本章, 因为 scull 的这个怪特性, 我们可互换地使用设备这个词和"scull 使用的内存区".
 
编写驱动的第一步是定义驱动将要提供给用户程序的能力(机制)。linux设备分为三种:字符,块,网络
scull实现的设备被引用成一种模型。

3.1主/次设备编号
设备号表示设备对应的驱动程序;次设备号由内核使用,用于正确确定设备文件所指的设备。
dev_t 类型(在 中定义)用来持有设备编号 -- 主次部分都包括.
dev_t 是 32 位的量, 12 位用作主编号, 20位用作次编号.
设备编号获得:
//中的一套宏定义. 为获得一个 dev_t的主或者次编号
          MAJOR(dev_t dev);          
          MINOR(dev_t dev);
如果你有主次编号, 需要将其转换为一个 dev_t, 使用:
          MKDEV(int major, int minor);

3.2分配和释放设备编号
我们关注几个函数:register_chrdev_region;int alloc_chrdev_region;void unregister_chrdev_region。
 
 
 

int register_chrdev_region(dev_t first, unsigned int count, char *name);
//用于注册设备

//first 是你要分配的起始设备编号,通常为0

//count是你请求的连续设备编号总数.不要太大

//name 是应当连接到这个编号范围的名字。

/*如果分配成功进行, register_chrdev_region 的返回值
是 0. 出错的情况下, 返回一个负的错误码, 你不能存取请求的区域.*/


动态分配的方法:

 

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned
int count, char *name);

 

使用这个函数, dev 是一个只输出的参数, 它在函数成功完成时持有你的分配
范围的第一个数. fisetminor 应当是请求的第一个要用的次编号; 它常常是 0.
count 和 name 参数如同给 request_chrdev_region 的一样.

释放设备:

void unregister_chrdev_region(dev_t first, unsigned int count);

调用 unregister_chrdev_region 的地方常常是你的模块的 cleanup 函数.
上面的函数分配设备编号给你的驱动使用, 但是它们不告诉内核你实际上会对
这些编号做什么. 在用户空间程序能够存取这些设备号中一个之前, 你的驱动
需要连接它们到它的实现设备操作的内部函数上. 我们将描述如何简短完成这
个连接, 但首先顾及一些必要的枝节问题.

PS:以上都是节选于《LDD》--第三章原文




if (scull_major) {//全局变量
  dev = MKDEV(scull_major, scull_minor);
    result = register_chrdev_region(dev, scull_nr_devs, "scull");
} else {
    result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,"scull");
    scull_major = MAJOR(dev);
}
if (result < 0) {
    printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
    return result;
}

 

本书使用的几乎所有例子驱动使用类似的代码来分配它们的主编号.其中细节可以自己去看《ldd》。


struct file_operations是一个字符设备把驱动的操作集合在一起,与设备号进行互动的结构。文件在linux/fs.h中描述。

struct file_operations {
        struct module *owner; //设备拥有者

        loff_t (*llseek) ();
        ssize_t (*read) ();
        ssize_t (*write) ();
        ssize_t (*aio_read) ();
        ssize_t (*aio_write) ();
        int (*readdir) ();
        unsigned int (*poll) ();
        int (*ioctl) ();
       long (*unlocked_ioctl) ();
        long (*compat_ioctl) ();
        int (*mmap) ();
        int (*open) ();
        int (*flush) ();
        int (*release) ();
        int (*fsync) ();
        int (*aio_fsync) ();
        int (*fasync) ();
        int (*lock) ();
        ssize_t (*sendfile) ();
        ssize_t (*sendpage) ();
        unsigned long (*get_unmapped_area) ();
        int (*check_flags) ();
        int (*dir_notify) ();
        int (*flock) ();
        ssize_t (*splice_write) ();
        ssize_t (*splice_read) ();
};


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