【Tiny6410 And Linux】—(5.2)—RamDisk 驱动实现(自己绑定 make_request_fn() )——代码
来源:互联网 发布:梦幻西游mac补丁 编辑:程序博客网 时间:2024/05/02 01:21
直接来吧!
1、驱动程序
①、blk.c
#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h>/* printk() */#include <linux/slab.h>/* kmalloc() */#include <linux/fs.h>/* everything... */#include <linux/errno.h>/* error codes */#include <linux/timer.h>#include <linux/types.h>/* size_t */#include <linux/fcntl.h>/* O_ACCMODE */#include <linux/hdreg.h>/* HDIO_GETGEO */#include <linux/kdev_t.h>#include <linux/vmalloc.h>#include <linux/genhd.h>#include <linux/blkdev.h>#include <linux/buffer_head.h>/* invalidate_bdev */#include <linux/bio.h>#include <linux/major.h>#include <linux/version.h>#define SIMP_BLKDEV_DEVICEMAJORCOMPAQ_SMART2_MAJOR#define SIMP_BLKDEV_DISKNAME "_Justin"#define SIMP_BLKDEV_BYTES (16 * 1024 * 1024)static struct request_queue *simp_blkdev_queue;static struct gendisk *simp_blkdev_disk;unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];/* * simp_blkdev_make_request */static int simp_blkdev_make_request(struct request_queue *q, struct bio *bio){ struct bio_vec *bvec; int i; void *dsk_mem;/* 判断 IO 请求是否超出实际 RanDisk 大小 */ if((bio->bi_sector << 9) + bio->bi_size > SIMP_BLKDEV_BYTES) { printk(KERN_ERR SIMP_BLKDEV_DISKNAME ": bad request: block=%llu, count=%u\n", (unsigned long long)bio->bi_sector, bio->bi_size);/* 条件编译,对于 2.4 内核之后的变量多了一个,伤不起阿! */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) /* 返回这个对 bio 请求的处理结果,-EIO 表示出错 */ bio_endio(bio, 0, -EIO);#else bio_endio(bio, -EIO);#endif return 0; } dsk_mem = simp_blkdev_data + (bio->bi_sector << 9); /* 遍历 bio 中所有的 bvec */ bio_for_each_segment(bvec, bio, i) { void *iovec_mem; switch(bio_rw(bio)) { case READ: case READA: /* 读和预读都进行同样的处理 */ /* 用 kmalloc 将请求页映射到非线性映射区域进行 * 访问,这种方法主要是为了兼容高端内存, * (bvec->bv_page 可能源于高端内存) */ iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset; memcpy(iovec_mem, dsk_mem, bvec->bv_len); kunmap(bvec->bv_page); break; case WRITE: iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset; memcpy(dsk_mem, iovec_mem, bvec->bv_len); kunmap(bvec->bv_page); break; default: printk(KERN_ERR SIMP_BLKDEV_DISKNAME ":Unknown value of bio_rw: %lu\n", bio_rw(bio));#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) bio_endio(bio, 0, -EIO);#else bio_endio(bio, -EIO);#endif return 0; } dsk_mem += bvec->bv_len; }/* 返回这个对 bio 请求的处理结果,0 表示正常 */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) bio_endio(bio, 0, 0);#else bio_endio(bio, 0);#endif return 0;}/* * block_device_operations */struct block_device_operations simp_blkdev_fops = { .owner = THIS_MODULE,};/* * simp_blkdev_init */static int __init simp_blkdev_init(void){ int ret;/* 分配一个请求队列 */ simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL); if(!simp_blkdev_queue) { ret = -ENOMEM; goto err_alloc_queue; }/* 为请求队列绑定 make_request_fn 方法 */ blk_queue_make_request(simp_blkdev_queue, simp_blkdev_make_request);/* 分配一个 gendisk 结构 */ simp_blkdev_disk = alloc_disk(1); if(!simp_blkdev_disk) { ret = -ENOMEM; goto err_alloc_disk; }/* 填充 gendisk 主要结构成员 */ strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME); simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR; simp_blkdev_disk->first_minor = 0; simp_blkdev_disk->fops = &simp_blkdev_fops; simp_blkdev_disk->queue = simp_blkdev_queue; set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES >> 9);/* 向内核注册块设备驱动 */ add_disk(simp_blkdev_disk); return 0;err_alloc_disk: blk_cleanup_queue(simp_blkdev_queue);err_alloc_queue: return ret;}/* * simp_blkdev_exit */static void __exit simp_blkdev_exit(void){ del_gendisk(simp_blkdev_disk);/* 删除 gendisk 结构 */ put_disk(simp_blkdev_disk);/* 释放一个该对象的引用 */ blk_cleanup_queue(simp_blkdev_queue);/* 清理请求队列 */}module_init(simp_blkdev_init);module_exit(simp_blkdev_exit);
②、Makefile
ifneq ($(KERNELRELEASE),)obj-m := blk.oelseKDIR := /lib/modules/2.6.27.62/buildall:make -C $(KDIR) M=$(PWD) modules clean:rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*endif
2、实验结果
- 【Tiny6410 And Linux】—(5.2)—RamDisk 驱动实现(自己绑定 make_request_fn() )——代码
- 【Tiny6410 And Linux】—(5.2)—RamDisk 驱动实现(自己绑定 make_request_fn() )——原理
- 【Tiny6410 And Linux】—(5.1)—RamDisk 驱动实现(内核缺省的处理函数 __make_request())——代码
- 【Tiny6410 And Linux】—(5.1)—RamDisk 驱动实现(内核缺省的处理函数 __make_request())——原理
- 【Tiny6410 And Linux】—(2.4)—实现 input 模型按键驱动——代码
- 【Tiny6410 And Linux】—(2.1)—platform 总线、设备、驱动——代码
- 【Tiny6410 And Linux】—(6.1)—LCD 驱动测试程序——代码
- 【Tiny6410 And Linux】—(2.4)—实现 input 模型按键驱动——原理
- 【Tiny6410 And Linux】—(6.2)—LCD 驱动测试程序(BMP 显示位图)——代码
- 【Tiny6410 And Linux】——基于 platform 总线的按键驱动——代码
- 【Tiny6410 And Linux】—(2.1)—platform 总线、设备、驱动——原理
- 【Tiny6410 And Linux】—(6.1)—LCD 驱动测试程序——原理
- 【Tiny6410 And Linux】—(1.1)—kobject——代码
- 【Tiny6410 And Linux】—(1.2)—kset——代码
- 【Tiny6410 And Linux】—(1.3)—bus 设备模型——代码
- 【Tiny6410 And Linux】—(1.4)—device 设备模型——代码
- 【Tiny6410 And Linux】—(1.5)—driver 设备模型——代码
- 【Tiny6410 And Linux】—(2.3)—使用工作队列处理按键中断——代码
- 解决android退出整个应用方法
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part7
- mini2440网卡驱动DM9000之dm9000_start_xmit
- 获得应用程序路径
- InkCanvas 保存图片
- 【Tiny6410 And Linux】—(5.2)—RamDisk 驱动实现(自己绑定 make_request_fn() )——代码
- ajax以form表单来提交
- 一致性HASH算法的JAVA实现
- Linux 查看系统信息命令
- 补充 OSGI bundle的知识
- CouchDB与MySQL的选择
- android view的setVisibility方法值的意思
- JSP中文验证码
- sicily--1317(深度优先搜索)