#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h> /* size_t */
#include <linux/fcntl.h> /* O_ACCMODE */
#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/hdreg.h>
#include<linux/slab.h>
#define MY_BLOCK_NAME "demo2_blodev"//需要设置块设备的名称,添加宏定义:
#define MY_DEVICE_MAJOR COMPAQ_SMART2_MAJOR//设置主从驱动号,这里使用的是操作系统已存在的驱动号,添加宏定义:
#define MY_BLOCK_CAPACITY (512*1024)//设置块设备的磁盘容量,添加宏定义:
struct block_device_operations blodev_fops={//设置块设备的文件操作函数,添加一个结构体:
.owner=THIS_MODULE
};
static unsigned int do_request(struct request_queue *q,struct bio * bio);//设置io请求队列,请求队列的处理函数便是这个驱动的核心内容,这里采用的无队列和全局变量存储的方式。
static struct request_queue *blodev_queue;//定义一个全局的块设备
unsigned char blodev_data[MY_BLOCK_CAPACITY];//全局数据存储数组
static struct gendisk *blodev;
static int __init my_init(void){
int ret;
blodev_queue=blk_alloc_queue(GFP_KERNEL);
blk_queue_make_request(blodev_queue,do_request);
if(!blodev_queue){
ret=-ENOMEM;
return ret;
}
blodev = alloc_disk(1); //为这个块设备申请资源、配置、加入系统
if(!blodev){
ret=-ENOMEM;
blk_cleanup_queue(blodev_queue);
return ret;
}
strcpy(blodev->disk_name,MY_BLOCK_NAME);
blodev->major=MY_DEVICE_MAJOR;
blodev->first_minor=0;
blodev->fops=&blodev_fops;
blodev->queue=blodev_queue;
set_capacity(blodev,MY_BLOCK_CAPACITY>>9);
add_disk(blodev);
return 0;
}
static void __exit my_exit(void){
put_disk(blodev);
//del_gentrcpy(blodev->disk_name,MY_BLOCK_NAME);
blodev->major=MY_DEVICE_MAJOR;
blodev->first_minor=0;
blodev->fops=&blodev_fops;
blodev->queue=blodev_queue;
set_capacity(blodev,MY_BLOCK_CAPACITY>>9);
//isk(blodev);
blk_cleanup_queue(blodev_queue);
}
static unsigned int do_request(struct request_queue *q,struct bio*bio){
unsigned long offset=bio->bi_iter.bi_sector << 9;
char *buffer;
struct bio_vec bvec;
struct bvec_iter iter;
int ret=0;
bio_for_each_segment(bvec,bio,iter){
if(((iter.bi_sector << 9) + iter.bi_size ) > MY_BLOCK_CAPACITY ){
printk("Beyond-end write (%ld %d)\n",offset,iter.bi_size);
ret=-EIO;
return ret;
}
buffer=kmap(bvec.bv_page) + bvec.bv_offset;
if(bio_data_dir(bio)==READ){
memcpy(buffer,blodev_data+offset,bvec.bv_len);
flush_dcache_page(bvec.bv_page);
}else if(bio_data_dir(bio)==WRITE){
flush_dcache_page(bvec.bv_page);
memcpy(blodev_data+offset,buffer,bvec.bv_len);
}else{
kunmap(bvec.bv_page);
goto out;
}
kunmap(bvec.bv_page);
offset += bvec.bv_len;
}
out:
bio_endio(bio);
return 0;
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lvbin");
MODULE_DESCRIPTION("this is a ostest demo2");
添加块设备文件
为块设备建立文件系统
说明文件读取成功。