linux简单虚拟硬盘驱动分析报告_第1页
linux简单虚拟硬盘驱动分析报告_第2页
linux简单虚拟硬盘驱动分析报告_第3页
linux简单虚拟硬盘驱动分析报告_第4页
linux简单虚拟硬盘驱动分析报告_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、linux简单虚拟硬盘驱动分析2012-06-06 16:15122人阅读评论(0)收藏举报#include #include #include #include #include #include #include linux/fcntl#include #include #inckide #include linux/blkpg#include #define VHDD_DEV_NAME vhdd#define VHDD_DEV_MAJOR 220#define VHDD_MAX_DEVICE 2#define VHDD_MAX_PARTITONS 16/*vhdd可以进行分区,允许的分区

2、总共为15个,因此总分区数应为16勺/#define VHDD_DEVICE_SIZE (4*1024*1024)/*vhdd ram disk模拟了硬盘,因此要定义相应的内容。扇区大小为512字节,可以任意指定圆柱面(cylinder)书设定为256每个cylinder的扇区数设定为16磁头数(VHDD_HEADS)设为2一台设备容量为(扇区大小*圆柱面数*扇区数*磁头数),这里=4M,应为disk 提供的大小相一致*/#define VHDD_SECTOR_SIZE 512#define VHDD_SECTORS 16#define VHDD_HEADS 2#define VHDD_CYL

3、INDERS 256#define VHDD_SECTOR_TOTAL(VHDD_SECTORS*VHDD_HEADS*VHDD_CYLINDERS)#define VHDD_SIZE (VHDD_SECTOR_SIZE*VHDD_SECTOR_TOTAL)typedef struct unsigned char *datao struct request_queue *queueospinlock_t locko /*分别管理自己的 lock*/struct gendisk *gdo vhdd_deviceo/char *vdiskVHDD_MAX_DEVICE = NULL,。extern

4、 char *vdiskVHDD_MAX_DEVICE static vhdd_device deviceVHDD_MAX_DEVICE o/*vhdd为模拟硬盘的运行,使用内核定时器启动中断(interrupt)o为了使用内核 定时器,定义7 timerjist结构体变量vhdd_timer另外,为了处理请求函数的 重入定义了 vhdd_busy变量。该值不为0时,块设备驱动程序的请求处理函数 vhdd_request()就会处于运行状态。这不仅仅是中断的启动方式,也是必要的变量, 因为整体设备会因一个中断而运行*/static struct timerjist vhdd_timerosta

5、tic int vhdd_busy=O。static void vhdd_request(struct request_queue *q)vhdd_device *pdeviceostruct request *vhdd_reqochar *pDataoint sizeoif(vhdd_busy) returno /*先检查、l前块设备是否处于处理请求的状态,如果处于处 理状态,就立即终止函数。这是因为处理中断的过程中还会调用Vhdd-request 函数*/while(l)vhdd_req = elviext_request(q)oif(!vhdd_req) returno /*vhdd_r

6、equest函数反复执行,知道处理完等待中的所有请 求。使用elv_next_request函数获得处理请求。若处理请求的request结构体地址 返回NULL时,表明没有处理请求,因此结束函数*/pdevice = (vhdd_device *)vhdd_req-rq_disk-private_dataopData = pdevice-data + (vhdd_req-sector) * VHDD_SECTOR_SIZEo/*vhdd_req-current_nr_sectors包含处理扇区数,如果超出范圉,想内核同志出 错,调用end_request(vhdd_req, 0)想内核通知出错

7、,并处理下一个请求*/if(vhdd_req-sector + vhdd_req-current_nr_sectors get_capacity(vhdd_req-rq_disk)end_request(vhdd_req, 0)。continueosize = vhdd_req-current_nr_sectors * VHDD_SECTOR_SIZE。switch(rq_data_dir(vhdd_req) case READ: memcpy(vhdd_req-buffer, pData, size)。breakocase WRITE:memcpy(pData, vhdd_reqbiiffe

8、size)。breakodefault:end_request(vhdd_req, 0)。continue/*普通的硬盘在读取数据的时候,先把将要读取的扇区信息传递到硬盘上,并等 待中断。确认发生了中断,并正常处理后,读取硬盘上的数据。相反,在向硬盘 上写入数据时,先要传递写入扇区的信息和数据,再等待中断。结束处理后发生 中断。这里使用内核的定时器模拟结束处理的中断。本例子中,vhdd进以简单的rain模拟硕盘,并在vhdd_request处理数据后,使 用内核的定时器模拟结束处理的中断。在使用vhdd.timer内核定时器时,经一 段时间后,调用作为中断函数的vhddjnternipt函数,

9、为了表示块设备驱动程序 的运行状态,把vhdd_busy设为1,然后结束函数。如前所述,该值就是用于忽 略数据处理过程中内核调用的vhdd.request函数*/vhdd_timer.expires = jiffies + 2。vhdd_timer.data = (unsigned long)pdeviceoadd_timer(&vhdd_timer)。vhdd_busy = 1。return ovoid vhdd_interrupt(unsigned long data) vhdd_device *pdeviceostruct request *vhdd_reqopdevice = (vhd

10、d_device *)data。vhdci_req = elv_next_request(pdevice-queue)oend_request(vhdd_req, 1)。vhdd_busy = 0。vhdd_request(pdevice-queue) int vhdd_open(struct inode *inode, struct file *filp) return 0。int vhdd_release (struct inode 水inode, stiuct file *filp) return 0。/*vhdd模拟硬盘,因此只需要能处理ioctl磁盘结构的HDIOGETGEO,其余军

11、返 回 ENOTTYHDIO_GETGEO是fdisk等分区处理程序,适用于获取设备的磁盘结构信息的命 令,为了执行该命令,在hd_geometry结构体变量上传递cylinder数,扇区数, head数及实际扇区的起始值。与2.4内核不同的是,2.6内核中可以直接代如扇 区的起始值,也可以使用get_start_sect函数处理该值。内核源代码中支持的大多 数设备驱动程序都使用get_start_sect处理扇区值。*/int vhdd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,unsigned long a

12、rg)int errostruct hd_geometry geo。switch(cmd)case HDIO_GETGEO:err = !access_ok(VERIFY_WRITE, arg, sizeof(geo)oif(err) return -EFAULTgeo.cylinders = VHDD_CYLINDERS。geo.heads = VHDD_HEADS。geo.sectors = VHDD_SECTORS ogeo.start = get_start_sect(inode-i_bdev) oif(copy_to_user(void*)arg, &geo, sizeof(geo)

13、 return -EFAULT。return 0。return -ENOTTYo static struct block_device_operations vhdd_fops.owner = THIS_MODULE,.open = vhdd_open,.release = vhdd_release,.ioctl = vhdd_ioctl,) int vhdd_init(void)int lpo/vdisk0 = vmalloc(VHDD_DEVICE_SIZE)o/vdisk 1 = vmalloc(VHDD_DEVICE_SIZE)omemset(vdisk0, 0, VHDD_DEVIC

14、E_SIZE)。/memset(vdiskl, 0, VHDD_DEVICE_SIZE)。/*使用下面的函数初始化内核定时器结构题vhdd_timer变量后,把山定时器而启 动的 vhdd_interrupt()函数注册到 vhdd_timer.funotion 函数中 ovhdd_timer.function() 函数用于模拟硬盘的中断*/init_timer(&(vhdd_timer)。vhdd_timer.function = vhdd_interruptoregister_blkdev(VHDD_DEV_MAJOR, VHDD_DEV_NAME)。for(Ip = 0o lp VHDD

15、_MAX_DEVICEo lp+) devicelp.data = vdiskIpo /*定义此data,使vdisk所获得的内存地址能够用在 request()函数上 */*分配gendisk结构体,而gendisk结构体是注册块设备的信息结构体。vhdd共 处理15个分区,因此,变量上代入16。在内核里该值大于2时,确定存在内存 分区,并执行分区处理*/devicelp.gd = alloc_disk( VHDD.M AX_PARTITONS) o/*使用blk_init_queue函数注册内核和块设备驱动程丿了的实际输入输出路径 vhdd_request函数,在device! Ip.qu

16、eue上设置生成的请求队列。对于blk_init_queue 函数,除了 request()函数外,为了管理等待队列的Lock,需要使用spinlock_t结构 体,因此,下面初始化lock变量,并代如到blk_init_queue函数中*/spin_lock_init (&devicelp.lock)odevicelp.queue = blk_init_queue(vhdd_request, &devicelp.lock)devicelp.gd-major = VHDD_DEV_MAJORodevicelp.gd-firsOninor = lp*VHDD_MAX_PARTITONS。devi

17、celp.gd-fops = &vhdd_fops。devicelp.gd-queue = device lp .queue。devicelp.gd-private_data = & devicelpo/*为了在proc和sysfs文件系统中表示分区及块设备,在deviceflp.gd-disk_name 上分别代入vhdda”,”vhddb”,然后使用set_capacity函数设置各台块设备的扇区 数*/sprintf(devicelp.gd-disk_name, Hvhdd%cH , ,a,+lp)oset_capacity(devicelp.gd.VHDD_SECTOR_TOTAL)o/*为了检索分区并注册块设备,调用add_disk()函数。调用该函数后,内核会在 内核内部注册各台块设备,需要检索分区时,在gendisk结构体的内部设置分区 处理变量*/add_disk(devicelp.gd)。return 0。) void vhdd_exit(void)int lp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论