Chinaunix首页 | 论坛 | 博客
  • 博客访问: 111665
  • 博文数量: 19
  • 博客积分: 1716
  • 博客等级: 上尉
  • 技术积分: 275
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-25 14:03
文章分类

全部博文(19)

文章存档

2011年(8)

2010年(11)

我的朋友

分类: LINUX

2010-04-27 20:46:24

1.字符设备与块设备IO操做的区别

1)块设备只能以块为单位接收输入返回输出,而字符设备则以byte为单位.大多数设备是字符设备,他们不需要缓冲并且不以固定块大小进行操作.

2)块设备对于IO请求有对应的缓冲区,所以他们可以选择以什么顺序进行响应.字符设备无须缓冲且被直接读写.

3)字符设备只能被顺序读写,块设备可以随机访问.

 

 

2.block_device_operations结构体

block_device_operations描述了对块设备的操作的集合

    struct block_device_operations {

        int (*open) (struct inode *, struct file *);/*打开*/

        int (*release) (struct inode *, struct file *);/*释放*/

        int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);

        long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);

        long (*compat_ioctl) (struct file *, unsigned, unsigned long);

        int (*direct_access) (struct block_device *, sector_t, unsigned long *);

        int (*media_changed) (struct gendisk *);/*介质被改变?*/

        int (*revalidate_disk) (struct gendisk *);/*使介质改变*/

        int (*getgeo)(struct block_device *, struct hd_geometry *);/*填充驱动器信息*/

        struct module *owner;/*模块拥有者,一般初始化为THIS_MODULE*/

    };

关于block_device_operations的操作:

    //open and release

    int (* open)(struct inode*, struct file*);

    int (* release)(struct inode*, struct file*);

    //io contrl

    //系统调用实现,块设备包含大量的标准请求,由设备层处理,所以此函数一般相当短

    int (* ioctl)(struct inode*,struct file*,unsigned int,unsigned long);

    //media changed

    //如果改变返回非0,否则返回0

    int (*media_changed)(struct gendisk*);

    //revalidate media

    //用于相应一个介质的改变,给驱动一个机会做准备工作

    int (* revalidate_disk)(struct gendisk*);

    //get driver informaiton

    //根据驱动器的几何信息填充hd_geometry,包含磁头,柱面,扇区等信息.

    int (* getgeo)(struct block_device*, struct hd_geometry*);

 

 

3.gendisk结构体

使用gendisk结果提来描述一个独立的磁盘设备或分区.

    //gendisk structure

    struct gendisk{

        /*前三个元素共同表征了一个磁盘的主,次设备号,同一个磁盘的各个分区共享一个主设备号*/

        int major;/*主设备号*/

        int first_minor;/*第一个次设备号*/

        int minors;/*最大的次设备数,如果不能分区,则为*/

        char disk_name[32];

        struct hd_struct** part;/*磁盘上的分区信息*/

        struct block_device_operations* fops;/*块设备操作,block_device_operations*/

        struct request_queue* queue;/*请求队列,用于管理该设备IO请求队列的指针*/

        void* private_data;/*私有数据*/

        sector_t capacity;/*扇区数,512字节为个扇区,描述设备容量*/

        //......

    };

 关于gendisk的操作:

    /*分配一个gendisk结构体,此结构体是由内核动态分配的*/

    struct gendisk* alloc_disk(int minors);

    /*增加gendisk,来注册该设备,此动作应该在设备驱动初始化完毕,并能响应磁盘请求之后*/

    void add_disk(struct gendisk* gd);

    /*释放一个不再需要的磁盘*/

    /**

    ***gendisk引用计数器:gendisk包含一个kobject成员.通过get_disk()&put_disk()函数来操作引用

    ***计数,此操作不需要驱动亲自完成.通常调用del_gendisk()会去掉gendisk的最终引用计数,但不是必 

    ***须的.因此在del_gendisk()gendisk结构体可能继续存在.

    **/

    /*设置gendisk容量*/

    void set_capacity(struct gendisk* disk, sector_t size);

块设备中,最小的可寻址单元就扇区,常见扇区大小是512字节.扇区的大小是设备的物理属性,是所有块设备的基本单元,块设备无法对比扇区小的单元进行寻址和操作.不过许多块设备能够一次传输多个扇区.不管物理设备的真实扇区是多少,内核与块设备交互的扇区均以512字节为单位.所以set_capcity()函数以512字节为单位.

下一篇:Linux块设备驱动(2)--块驱动相关的结构体及相关操作

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