块设备的学习可以对照字符设备
字符设备:当应用程序调用open,read,write时,会调用到驱动程序的open,read,write函数,这样联系就建立起来啦
块设备:当应用程序调用open,read,write时,文件系统会转化成对扇区的读写请求,并且把请求优化后放入一个队列中,然后调用队列的处理函数用电梯调度算法从队列中取出请求进行处理。
驱动程序要做的事情就是,1.创建这个队列 2.构造这个处理函数 3.其他的参数
内核中已经把这三步的东西集中在了一个结构体中,我们只要
1.分配gendisk结构体
2.设置
3.add_disk
/* 参考:
* drivers\block\xd.c
* drivers\block\z2ram.c
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
struct block_device_operations ramblock_ops={
.owner = THIS_MODULE,
};
#define RAMBLOCK_SIZE (1024*1024)
static struct gendisk *ramblock_disk;
static unsigned int major;
static request_queue_t *ramblock_queue;
static DEFINE_SPINLOCK(ramblock_lock);
static unsigned char *ramblock_buf;
static void do_ramblock_request(request_queue_t *q)
{
struct request *req;
int r_cnt;
int w_cnt;
while ((req = elv_next_request(q)) != NULL) {
unsigned long offset = req->sector * 512;
unsigned long len = req->current_nr_sectors * 512;
if(rq_data_dir(req) == READ)
{
printk("read %d",++r_cnt);
memcpy(req->buffer, ramblock_buf+offset, len);
}
else
{
memcpy(ramblock_buf+offset, req->buffer, len);
printk("wirte %d",++w_cnt);
}
}
}
static int ramblock_init(void)
{
ramblock_disk = alloc_disk(16);
major = register_blkdev(0,"ramblock");
ramblock_disk->major = major;
ramblock_disk->first_minor = 0;
sprintf(ramblock_disk->disk_name, "ramblock");
ramblock_disk->fops = &ramblock_ops;
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
ramblock_disk->queue = ramblock_queue;
set_capacity(ramblock_disk, RAMBLOCK_SIZE/512);
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
add_disk(ramblock_disk);
return 0;
}
static void ramblock_exit(void)
{
put_disk(ramblock_disk);
blk_cleanup_queue(ramblock_queue);
unregister_blkdev( major, "ramblock" ) ;
del_gendisk(ramblock_disk);
kfree(ramblock_buf);
}
module_init(ramblock_init);
module_exit(ramblock_exit);
MODULE_LICENSE("GPL");