linux块设备驱动与其测试
1 驱动程序
#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> //块设备文件主设备号 72 #define BLOCK_DEVICEMAJOR COMPAQ_SMART2_MAJOR // 块设备名字 #define BLOCK_DISKNAME "queue_block" //块设备容量 #define BLOCK_DEV_BYTES (1*1024*1024) // 1M //请求队列指针 static struct request_queue *block_request_queue; // gendisk结构体指针变量 static struct gendisk *block_dev_disk; //模拟磁盘空间 unsigned char block_dev_data[BLOCK_DEV_BYTES]; //该函数不能由驱动自己调用 由系统调用 系统认为是时候调用的时候调用 static void block_dev_do_request(struct request_queue *q) { //获取请求队列第一个IO请求 struct request *req =blk_fetch_request(q); while ( req != NULL) { sector_t sector = blk_rq_pos(req); //获取扇区第一个位置 unsigned long nsector = blk_rq_cur_sectors(req);//获取扇区数目 //判断是否大于总容量 if ((sector + nsector)<<9 > BLOCK_DEV_BYTES) { printk(KERN_ERR BLOCK_DISKNAME ": bad request: block=%llu, count=%llu\n", (unsigned long long)sector, (unsigned long long)nsector); __blk_end_request_all(req, -EIO); continue; } //判断数据传输方向 switch (rq_data_dir(req)) { case READ: memcpy(req->buffer, block_dev_data + (sector<<9), nsector<<9); break; case WRITE: memcpy(block_dev_data + (sector<<9), req->buffer, nsector<<9); break; default: break; } //通知请求队列当前IO已经处理完毕 if ( ! __blk_end_request_cur(req, 0) ) { req = blk_fetch_request(q); //继续读取下一个IO请求 } } } static int block_dev_open (struct block_device *device, fmode_t mode) { printk("open %s\n", device->bd_disk->disk_name); return 0; } // 释放块设备 static int block_dev_release(struct gendisk *gendisk, fmode_t mode) { printk("release %s\n", gendisk->disk_name); return 0; } //类似字符设备 struct block_device_operations block_dev_fops = { .owner = THIS_MODULE,.open=block_dev_open, .release=block_dev_release }; static int __init block_dev_init(void) { int ret; //初始化请求队列 block_request_queue = blk_init_queue(block_dev_do_request, NULL); if (!block_request_queue) { ret = -ENOMEM; goto err_init_queue; } //分配磁盘 block_dev_disk = alloc_disk(1); if (!block_dev_disk) { ret = -ENOMEM; goto err_alloc_disk; } strcpy(block_dev_disk->disk_name, BLOCK_DISKNAME);//设备文件名 block_dev_disk->major = BLOCK_DEVICEMAJOR; block_dev_disk->first_minor = 0; block_dev_disk->fops = &block_dev_fops; block_dev_disk->queue = block_request_queue;//指定请求队列 set_capacity(block_dev_disk, BLOCK_DEV_BYTES>>9);//设置磁盘容量 add_disk(block_dev_disk);//添加磁盘 return 0; err_alloc_disk: blk_cleanup_queue(block_request_queue); err_init_queue: return ret; } static void __exit block_dev_exit(void) { del_gendisk(block_dev_disk);//删除磁盘 put_disk(block_dev_disk);//gendisk引用次数减一 blk_cleanup_queue(block_request_queue);//清除请求队列 } module_init(block_dev_init); module_exit(block_dev_exit);
测试:
第一步:编译安装驱动程序
makefile;
ifneq ($(KERNELRELEASE),)
obj-m :=queue_block.o
else
KERNELDIR :=/home/litingting/gec2440/linux-2.6.30.4
all:
make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.o *.ko *.mod.o *.mod.c *.symvers modul* *.*~
endif
接下来 insmod queue_block.ko
第二步:格式化块设备
例如将设备格式化为Ext2文件系统格式 mkfs.ext2 /dev/queue_block
第三步:挂载
mount /dev/queue_block /mnt/queue_block
关于挂载解释如下:
A
我把U盘插到USB口上了,下一步我该如何做才能查看U盘里的内容?
我不能确定你的Linux系统会不会自动加载。所以,你应该先去/media目录下查看一下,看看是不是已经自动加载上了。如果是的话,应该在/media里有一个目录,
名字类似于disk,你进入目录就等于进入你的U盘了。
如果/media没有你想要的东西,那就要自己mount了!
$mkdir /mnt/usb
$mount -t vfat /dev/sda /mnt/usb
这样就可以了,你去/mnt/usb目录看看,应该有你想要的了。如果mount命令不管用,那么你可以将/dev/sda改成/dev/sdb或者/dev/sdc试试!
-t选项用于设定文件系统类型,我假设你的U盘是fat32的。(因为大部分U盘都是这样的)如果是其他文件系统,你可以man mount来查看一下,方法类似。
B
我把光盘放到光驱里了,下一步咋办?
如果系统没有自动加载光驱的话,那么用下面命令一般有效:
$mkdir /mnt/cdrom
$mount -t iso9660 /dev/cdrom /mnt/cdrom
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。