linux简单虚拟硬盘驱动分析

上传人:博****1 文档编号:431725278 上传时间:2023-09-03 格式:DOC 页数:12 大小:228KB
返回 下载 相关 举报
linux简单虚拟硬盘驱动分析_第1页
第1页 / 共12页
linux简单虚拟硬盘驱动分析_第2页
第2页 / 共12页
linux简单虚拟硬盘驱动分析_第3页
第3页 / 共12页
linux简单虚拟硬盘驱动分析_第4页
第4页 / 共12页
linux简单虚拟硬盘驱动分析_第5页
第5页 / 共12页
点击查看更多>>
资源描述

《linux简单虚拟硬盘驱动分析》由会员分享,可在线阅读,更多相关《linux简单虚拟硬盘驱动分析(12页珍藏版)》请在金锄头文库上搜索。

1、作者:日期:linux简单虚拟硬盘驱动分析2012 06-06 16 : 15 122人阅读 评论(0)收藏 举报#inelude linux/init。h# in elude linu x/module。h# in elude # include linux/fs.h# include # include linux/fentl.h# include linux/vmalloc。h#include linux/hdreg.h #include linux/blkdev.h # include # include asm/uaccess.h# define VHDD_DEV_NAME vhdd

2、”# define VHDD_DEV_MAJOR 220#defi ne VHDD_MAX_DEVICE 2 #define VHDD_MAX_PARTITONS 16 /衣vhdd可以进行分区,允许的分区总共为15个,因此总分区数应为16* /#define VHDD_DEVICE_SIZE(4*1024 衣 1024)/*vhdd ram disk模拟了硬盘,因此要定义相应的内容。扇区大小为512字节,可以任意指定圆柱面(cylinder)书设定为256每个cylinder的扇区数设定为16磁头数(VHDD_HEADS )设为2一台设备容量为(扇区大小*圆柱面数*扇区数 *磁头数),这里=

3、4M,应为disk 提供的大小相一致衣/# define VHDD_SECTOR_SIZE 512#defi ne VHDD_SECTORS 16# define VHDD_HEADS 2#defi ne VHDD_CYLINDERS 256#define VHDD_SECTOR_TOTAL (VHDD_SECTORS 衣 VHDD_HEADS*VHDD_CYLINDERS )# define VHDD_SIZE (VHDD_SECTOR_SIZE 衣 VHDD_SECTOR_TOTAL)typedef structunsigned char * data;struct request_que

4、ue * queue;spinlock_t lock;/ *分别管理自己的 lock * /struct gen disk * gd; vhdd_device;/char *vdisk VHDD_MAX_DEVICE = NULL, ;extern char * vdiskVHDD_MAX_DEVICE ;static vhdd_device device VHDD_MAX_DEVICE;/ * vhdd为模拟硬盘的运行,使用内核定时器启动中断(interrupt)。为了使用内核 定时器,定义 了 timer_list结构体变量vhdd_timer。另外,为了处理请求函数的 重入定义了 vhd

5、d_busy变量.该值不为0时,块设备驱动程序的请求处理函数 vhdd_request)就会处于运行状态。这不仅仅是中断的启动方式,也是必要的变 量,因为整体设备会因一个中断而运行* /static struct timer_list vhdd_timer;static int vhdd_busy=0;static void vhdd_request( struct request_queue *q)vhdd_device * pdevice;struct request * vhdd_req;char * pData;int size;if (vhdd_busy) return; /*先检查

6、当前块设备是否处于处理请求的状态,如果 处于处理状态,就立即终止函数。这是因为处理中断的过程中还会调用 vhdd_request 函数 */while ( 1)vhdd_req = elv_next_request(q ;if (! vhdd_req) return; /* vhdd_request函数反复执行,知道处理完等待中的所 有请求。使用elv_next_request函数获得处理请求。若处理请求的request结构体地址返回NULL时,表明没有处理请求,因此结束函数*/pdevice = (vhdd_device *) vhdd_reqrq_disk-private_data;pDa

7、ta = pdevice-data + (vhdd_reqsector) * VHDD_SECTOR_SIZE ;/ * vhdd_req-current_nr_sectors包含处理扇区数,如果超出范围,想内核同志出错, 调用end_request(vhdd_req, 0)想内核通知出错,并处理下一个请求*/if (vhdd_req-sector + vhdd_reqcurrent_nr_sectorsget_capacity (vhdd_req-rq_disk)en d_request(vhdd_req 0);con ti nue;size = vhdd_reqcurrent_nr_sec

8、tors * VHDD_SECTOR_SIZE;switch (rq_data_dir (vhdd_req)case READ:memcpy(vhdd_req-buffer, pData, size);break;case WRITE:memcpy (pData, vhdd_req buffer, size);break;defaultnd_request(vhdd_req, 0); continue;/*普通的硬盘在读取数据的时候,先把将要读取的扇区信息传递到硬盘上,并等待 中断。确认发生了中断,并正常处理后,读取硬盘上的数据。相反,在向硬盘上 写入数据时,先要传递写入扇区的信息和数据,再等

9、待中断结束处理后发生中断。 这里使用内核的定时器模拟结束处理的中断.本例子中,vhdd进以简单的ram模拟硬盘,并在vhdd_request处理数据后,使 用内核的定时器模拟结束处理的中断。在使用 vhdd_timer内核定时器时,经一段 时间后,调用作为中断函数的 vhdd_interrupt函数,为了表示块设备驱动程序的 运行状态,把vhdd_busy设为1,然后结束函数。如前所述,该值就是用于忽略数 据处理过程中内核调用的vhdd_request函数*/vhdd_timer。expires = jiffies + 2 ;vhdd_timer。data = ( unsigned long)

10、 pdevice;add_timer (& vhdd_timer);vhdd_busy = 1;return;void vhdd_i nterrupt( un sig ned long data)vhdd_device * pdevice;struct request * vhdd_req;pdevice = (vhdd_device *) data;vhdd_req = elv_ next_request(pdevice- queue);end_request(vhdd_req 1);vhdd_busy = 0;vhdd_request (pdevice-queue ;int vhdd_op

11、en (struct inode * inode, struct file * filp)return 0;int vhdd_release (struct inode *inode struct file * filp)return 0;/ * vhdd模拟硬盘,因此只需要能处理ioctl磁盘结构的HDIO_GETGEO,其余军返 回 ENOTTYHDIO_GETGEO是fdisk等分区处理程序,适用于获取设备的磁盘结构信息的命 令,为了执行该命令,在hd_geometry结构体变量上传递cylinder数,扇区数,head 数及实际扇区的起始值。与2。4内核不同的是,2。6内核中可以直接代

12、如扇区的 起始值,也可以使用get_start_sect函数处理该值.内核源代码中支持的大多数设 备驱动程序都使用get_start_sect处理扇区值。* /int vhddoctl(struct inode * inode, struct file * filp , unsigned int cmd,un sig ned long argint err;struct hd_geometry geo;switch(cmd)case HDIO_GETGEO:err = !access_ok(VERIFY_WRITE, arg, sizeof (geo);if(err) return EFAUL

13、T ;geoo cylinders = VHDD_CYLINDERS;geo.heads = VHDD_HEADS;geo.sectors = VHDD_SECTORS;geco start = get_start_sect(inodi_bdev);if (copy_to_user( (void * )arg, &geo, sizeof(geo) return -EFAULT ;return 0;return ENOTTY;static struct block_device_operatio ns vhdd_fops =。owner = THIS_MODULE,。open = vhdd_op

14、en.release = vhdd_release,。ioctl = vhdd_ioctl ,;int vhdd_i nit(void)int lp;/vdisk 0 = vmalloc(VHDD_DEVICE_SIZE );vdisk1 = vmalloc(VHDD_DEVICE_SIZE);memset(vdiskO , 0, VHDD_DEVICE_SIZE);/memset (vdisk1, 0, VHDD_DEVICE_SIZE);/ *使用下面的函数初始化内核定时器结构题vhdd_timer变量后,把由定时器而启动的 vhdd_interrupt()函数注册到 vhdd_timer

15、。function 函数中.vhdd_timer.function()函数用于模拟硬盘的中断* / init_timer (& (vhdd_timer);vhdd_timer.f un cti on = vhdd_i nterrupt;register_blkdev(VHDD_DEV_MAJOR , VHDD_DEV_NAME )for(lp = 0; lp VHDD_MAX_DEVICE; lp+) devicelp.data = vdisk lp ; /*定义此data,使vdisk所获得的内存地址能够用 在request ()函数上* / / *分配gen disk结构体,而gen disk结构体是注册块设备的信息结构体。vh

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

当前位置:首页 > 医学/心理学 > 基础医学

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