这只是一个课程设计
要求写一个块设备的驱动,由于从来没有接触过这个方面,所以只能一点点儿的学习,但是,最后发现,我学习的资料跟现在的内核版本3.2.16有非常大的出入。原先的一些api都已经不存在了。
我只好在网上找了一个例子,参照着新内核的源码对所用的函数进行替换,但是问题却来了,编译好模块后插入内核会造成死机,没有任何响应。
下面是来自http://bbs.chinaunix.net/thread-2017377-1-1.html的代码。
- C/C++ code
#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR#define SIMP_BLKDEV_DISKNAME "simp_blkdev"#define SIMP_BLKDEV_BYTES (16*1024*1024)unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];static struct request_queue *simp_blkdev_queue;static struct gendisk *simp_blkdev_disk;static void simp_blkdev_do_request(struct request_queue *q);struct block_device_operations simp_blkdev_fops = { .owner = THIS_MODULE,};static void simp_blkdev_do_request(struct request_queue *q){ struct request *req; while ((req = elv_next_request(q)) != NULL) { if ((req->sector + req->current_nr_sectors) << 9 > SIMP_BLKDEV_BYTES) { printk(KERN_ERR SIMP_BLKDEV_DISKNAME ": bad request: block=%llu, count=%u\n", (unsigned long long)req->sector, req->current_nr_sectors); end_request(req, 0); continue; } switch (rq_data_dir(req)) { case READ: memcpy(req->buffer, simp_blkdev_data + (req->sector << 9), req->current_nr_sectors << 9); end_request(req, 1); break; case WRITE: memcpy(simp_blkdev_data + (req->sector << 9), req->buffer, req->current_nr_sectors << 9); end_request(req, 1); break; default: /* No default because rq_data_dir(req) is 1 bit */ break; } }}static int __init simp_blkdev_init(void){ int ret; simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL); if (!simp_blkdev_queue) { ret = -ENOMEM; goto err_init_queue; } simp_blkdev_disk = alloc_disk(1); if (!simp_blkdev_disk) { ret = -ENOMEM; goto err_alloc_disk; } 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_init_queue: return ret;}static void __exit simp_blkdev_exit(void){ del_gendisk(simp_blkdev_disk); put_disk(simp_blkdev_disk); blk_cleanup_queue(simp_blkdev_queue);}module_init(simp_blkdev_init);module_exit(simp_blkdev_exit);
我自己根据源码替代函数后的代码如下
- C/C++ code
#include <linux/blkdev.h>#include <linux/genhd.h>#include <linux/init.h>//#include <linux/config.h>新的内核已经不支持该头文件了#include <linux/module.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/proc_fs.h>#include <linux/ioctl.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <asm/system.h> /* cli(), *_flags */#include <asm/uaccess.h> /* copy_from/to_user */#define SIMP_BLKDEV_DEVICEMAJOR 60#define SIMP_BLKDEV_DISKNAME "simp_blkdev"#define SIMP_BLKDEV_BYTES (1024*1024)static struct request_queue *simp_blkdev_queue;static struct gendisk *simp_blkdev_disk;unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];static void simp_blkdev_do_request(struct request_queue *q){ struct request *req; while ((req = blk_fetch_request(q)) != NULL) { if (((req->__sector + req->__data_len) << 9) > SIMP_BLKDEV_BYTES) { printk(KERN_ERR SIMP_BLKDEV_DISKNAME": bad request: block=%llu, count=%u\n", (unsigned long long)req->__sector, req->__data_len); blk_end_request_all(req, 0); continue; } switch (rq_data_dir(req)) { case READ: memcpy(req->completion_data, simp_blkdev_data + (req->__sector << 9), req->__data_len << 9); blk_end_request_all(req, 1); break; case WRITE: memcpy(simp_blkdev_data + (req->__sector << 9), req->buffer, req->__data_len << 9); blk_end_request_all(req, 1); break; default: /* No default because rq_data_dir(req) is 1 bit */ break; } }}struct block_device_operations simp_blkdev_fops = { .owner = THIS_MODULE,};static int __init simp_blkdev_init(void){ int ret; simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL); if (!simp_blkdev_queue) { ret = -ENOMEM; goto err_init_queue; } simp_blkdev_disk = alloc_disk(1); if (!simp_blkdev_disk) { ret = -ENOMEM; goto err_alloc_disk; } 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); printk("<1>块设备驱动成功加载完成"); return 0;err_alloc_disk: blk_cleanup_queue(simp_blkdev_queue);err_init_queue: return ret;}static void __exit simp_blkdev_exit(void){ del_gendisk(simp_blkdev_disk); put_disk(simp_blkdev_disk); blk_cleanup_queue(simp_blkdev_queue); printk("<1>块设备卸载完毕");}module_init(simp_blkdev_init);module_exit(simp_blkdev_exit);