实验七:Linux块设备驱动.doc

上传人:工**** 文档编号:561666041 上传时间:2024-03-08 格式:DOC 页数:14 大小:113KB
返回 下载 相关 举报
实验七:Linux块设备驱动.doc_第1页
第1页 / 共14页
实验七:Linux块设备驱动.doc_第2页
第2页 / 共14页
实验七:Linux块设备驱动.doc_第3页
第3页 / 共14页
实验七:Linux块设备驱动.doc_第4页
第4页 / 共14页
实验七:Linux块设备驱动.doc_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《实验七:Linux块设备驱动.doc》由会员分享,可在线阅读,更多相关《实验七:Linux块设备驱动.doc(14页珍藏版)》请在金锄头文库上搜索。

1、实验七:Linux块设备驱动块设备是与字符设备并列的概念,这两类设备在Linux中驱动的结构有较大差异,总体而言,块设备驱动比字符设备驱动要复杂得多,在I/O操作上表现出极大的不同,缓冲、I/O调度、请求队列等都是与块设备驱动相关的概念。本章将详细讲解Linux块设备驱动的编程方法。1.块设备的I/O操作特点字符设备与块设备I/O操作的不同如下:(1)块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位。大多数设备是字符设备,因为它们不需要缓冲而且不以固定块大小进行操作。(2)块设备对于I/O请求有对应的缓冲区,因此它们可以选择以什么顺序进行响应,字符设备无须缓冲且被直接读写。对于

2、存储设备而言调整读写的顺序作用巨大,因为在读写连续的扇区比分离的扇区更快。(3)字符设备只能被顺序读写,而块设备可以随机访问。虽然块设备可随机访问,但是对于磁盘这类机械设备而言,顺序地组织块设备的访问可以提高性能。而对SD卡、RamDisk(RamDisk是通过使用软件将RAM模拟当做硬盘来使用的一种技术)等块设备而言,不存在机械上的原因,进行这样的调整没有必要。2.Linux块设备驱动结构2.1.block_device_operations结构体在块设备驱动中,有一个类似于字符设备驱动中file_operations结构体的block_device_operations结构体,它是对块设备

3、操作的集合,定义如代码清单1所示。代码清单1 block_device_operations结构体struct block_device_operationsint(*open)(struct inode *, struct file*); /打开int(*release)(struct inode *, struct file*); /释放int(*ioctl)(struct inode *, struct file *, unsigned, unsigned long);/ioctllong(*unlocked_ioctl)(struct file *, unsigned, unsigne

4、d 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 m

5、odule *owner; /模块拥有者;下面对其主要的成员函数进行分析。1打开和释放int (*open)(struct inode *inode, struct file *filp);int (*release)(struct inode *inode, struct file *filp);与字符设备驱动类似,当设备被打开和关闭时将调用它们。2IO控制int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);上述函数是ioctl()系统调用的实现,块设备包含大量的标

6、准请求,这些标准请求由Linux块设备层处理,因此大部分块设备驱动的ioctl()函数相当短。3介质改变int (*media_changed) (struct gendisk *gd);被内核调用来检查是否驱动器中的介质已经改变,如果是,则返回一个非0值,否则返回0。这个函数仅适用于支持可移动介质的驱动器,通常需要在驱动中增加一个表示介质状态是否改变的标志变量,非可移动设备的驱动不需要实现这个方法。4使介质有效int (*revalidate_disk) (struct gendisk *gd);revalidate_disk()被调用来响应一个介质改变,它给驱动一个机会来进行必要的工作以使

7、新介质准备好。5获得驱动器信息int (*getgeo)(struct block_device *, struct hd_geometry *);根据驱动器的几何信息填充一个hd_geometry结构体,hd_geometry结构体包含磁头、扇区、柱面等信息。6模块指针struct module *owner;一个指向拥有这个结构体的模块的指针,它通常被初始化为THIS_MODULE。2.2.gendisk结构体在Linux内核中,使用gendisk(通用磁盘)结构体来表示1个独立的磁盘设备(或分区),这个结构体的定义如代码清单2所示。代码清单2 gendisk结构体struct gendi

8、skint major; /* 主设备号 */int first_minor; /*第1个次设备号*/int minors; /* 最大的次设备数,如果不能分区,则为1*/char disk_name32; /* 设备名称 */struct hd_struct *part; /* 磁盘上的分区信息 */struct block_device_operations *fops; /*块设备操作结构体*/struct request_queue *queue; /*请求队列*/void *private_data; /*私有数据*/sector_t capacity; /*扇区数,512字节为1个

9、扇区*/int flags;char devfs_name64;int number;struct device *driverfs_dev;struct kobject kobj;struct timer_rand_state *random;int policy;atomic_t sync_io; /* RAID */unsigned long stamp;int in_flight;#ifdef CONFIG_SMPstruct disk_stats *dkstats;#elsestruct disk_stats dkstats;#endif;major、first_minor和mino

10、rs共同表征了磁盘的主、次设备号,同一个磁盘的各个分区共享一个主设备号,而次设备号则不同。fops为block_device_operations,即上节描述的块设备操作集合。queue是内核用来管理这个设备的I/O请求队列的指针。capacity表明设备的容量,以512个字节为单位。private_data可用于指向磁盘的任何私有数据,用法与字符设备驱动file结构体的private_data类似。Linux内核提供了一组函数来操作gendisk,如下所示:1分配gendiskgendisk结构体是一个动态分配的结构体,它需要特别的内核操作来初始化,驱动不能自己分配这个结构体,而应该使用下列

11、函数来分配gendisk:struct gendisk *alloc_disk(int minors);minors参数是这个磁盘使用的次设备号的数量,一般也就是磁盘分区的数量,此后minors不能被修改。2增加gendiskgendisk结构体被分配之后,系统还不能使用这个磁盘,需要调用如下函数来注册这个磁盘设备。void add_disk(struct gendisk *gd);特别要注意的是对add_disk()的调用必须发生在驱动程序的初始化工作完成并能响应磁盘的请求之后。3释放gendisk当不再需要一个磁盘时,应当使用如下函数释放gendisk。void del_gendisk(s

12、truct gendisk *gd);4设置gendisk容量void set_capacity(struct gendisk *disk, sector_t size);块设备中最小的可寻址单元是扇区,扇区大小一般是2的整数倍,最常见的大小是512字节。扇区的大小是设备的物理属性,扇区是所有块设备的基本单元,块设备无法对比它还小的单元进行寻址和操作,不过许多块设备能够一次就传输多个扇区。虽然大多数块设备的扇区大小都是512字节,不过其他大小的扇区也很常见,比如,很多CD-ROM盘的扇区都是2KB。不管物理设备的真实扇区大小是多少,内核与块设备驱动交互的扇区都以512字节为单位。因此,set_

13、capacity()函数也以512字节为单位。2.3. 请求结构体request在Linux块设备驱动中,使用request结构体来表征等待进行的I/O请求,这个结构体的定义如代码清单3所示。代码清单3 request结构体struct requeststruct list_head queuelist; /*链表结构*/unsigned long flags; /* REQ_ */sector_t sector; /* 要传送输的下一个扇区 */unsigned long nr_sectors; /*要传送的扇区数目*/unsigned int current_nr_sectors; /*当

14、前要传送的扇区数目*/sector_t hard_sector; /*要完成的下一个扇区*/unsigned long hard_nr_sectors; /*要被完成的扇区数目*/unsigned int hard_cur_sectors; /*当前要被完成的扇区数目*/struct bio *bio; /*请求的 bio 结构体的链表*/struct bio *biotail; /*请求的 bio 结构体的链表尾*/void *elevator_private;unsigned short ioprio;int rq_status;struct gendisk *rq_disk;int er

15、rors;unsigned long start_time;unsigned short nr_phys_segments; /*请求在物理内存中占据的不连续的段的数目,scatter/gather列表的尺寸*/unsigned short nr_hw_segments; /*与nr_phys_segments相同,但考虑了系统I/O MMU的remap */int tag;char *buffer; /*传送的缓冲,内核虚拟地址*/int ref_count; /* 引用计数 */.;request结构体的主要成员包括:sector_t hard_sector;unsigned long hard_nr_sectors;unsigned int hard_cur_sectors;上述3个成员标识还未完成的扇区,hard_sector是第一个尚未传输的扇区,hard_nr_sectors是尚待完成的扇区数,hard_cur_sectors是当前I/O操作中待完成的扇区数。这些成员只用于内核块设备层,驱动不应当使用它们,如下所示:sector_t sector;unsigned long nr_sectors;unsi

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号