自己学习网上的相关资料,做了少量修改。不知道为什么这个块驱动不能够mount。ext3格式化是正常的。
/*********************************************************
File Name: simp_blkdev.c
Version: v0.1 2013-08-29
Description: Driver of a ** block device.
*********************************************************/
#include <linux/genhd.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#define MYRAMDISK_MAJOR 0 /*主设备号为0,动态生成设备号*/
#define MYRAMDISK_NAME "han_ramdisk" /*设备名称*/
#define MYRAMDISK_SIZE (16*1024*1024) /*虚拟磁盘大小,共16M*/
static int gendisk_major = MYRAMDISK_MAJOR; /*用来保存动态生成的设备号*/
//unsigned char array_data[MYRAMDISK_SIZE]; /*全局数组,表示本设备*/
unsigned char* array_data = NULL;
struct gendisk* my_gendiskp; /*定义一个磁盘*/
struct request_queue* my_request_queuep;/*定义一个与设备关联的请求队列*/
//static struct class* my_classp; /*定义一个设备类*/
static DEFINE_SPINLOCK(lock); /*全局变量,内核访问请求队列的自旋锁*/
/*块设备驱动操作结构体*/
static struct block_device_operations my_operations = {
.owner = THIS_MODULE,
};
static void sbd_transfer(sector_t sector, unsigned long nsect, char* buffer, int write)
{
unsigned long offset = (sector<<9);
unsigned long nbytes = (nsect<<9);
if((offset + nbytes) > MYRAMDISK_SIZE){
printk(KERN_NOTICE "sbd: Beyond-end write(%ld %ld)\n", offset, nbytes);
return;
}
if(write)
memcpy(array_data + offset, buffer, nbytes);
else
memcpy(buffer, array_data + offset, nbytes);
}
/*请求队列处理函数*/
static void my_process_on_request_queue(struct request_queue* q)
{
struct request *req;
req = blk_fetch_request(q);
while(req != NULL){
if(req->cmd_type != REQ_TYPE_FS){
printk(KERN_NOTICE "Skip non-CMD request\n");
__blk_end_request_all(req, -EIO);
continue;
}
sbd_transfer(blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
if(!__blk_end_request_cur(req, 0)){
req = blk_fetch_request(q);
}
}
}
/*驱动模块加载函数*/
static int __init my_init(void)
{
int ret; /*存放返回值*/
array_data = (char*)vmalloc(MYRAMDISK_SIZE);
/*1.块设备驱动注册,注意这个块设备驱动的注册函数在2.6内核中是可选的。改函数由内核提供,这里使用是为了生成一个动态生成的主设备号*/
gendisk_major = register_blkdev(gendisk_major, MYRAMDISK_NAME);
if(gendisk_major <= 0){
printk(KERN_WARNING "no major number\n");
return gendisk_major;
}
/*4.动态生成一个设备节点,跟字符设备一样*/ //这一点和cdev字符设备不同,不可以加否则模块加载和
/*my_classp = class_create(THIS_MODULE, MYRAMDISK_NAME);
if(IS_ERR(my_classp)){
ret = -1;
goto err_class;
}
device_create(my_classp, NULL, MKDEV(gendisk_major, 0), NULL, MYRAMDISK_NAME);*/
/*2.每个设备关联一个请求队列,我们在这里申请1个。需要注意的是:1)每个请求队列都对应一个“请求队列处理函数”,这个是设备相关的。2)每次分配一个请求队列的时候,必须提供一个自旋锁来控制对请求队列的访问,我们先不考虑并发访问*/
//spin_lock_init(&lock);
my_request_queuep = blk_init_queue(my_process_on_request_queue, &lock);
if(NULL == my_request_queuep){
printk("request queue error\n");
ret = -ENOMEM;
goto error_queue;
}
/*3.为代表本设备的结构体申请内存,这里的参数是本磁盘,使用的是次设备号的数目,一经申请,这个数字就不能改变。使用申请的资源为gendisk赋值。注册gendisk*/
my_gendiskp = alloc_disk(1);
if(NULL == my_gendiskp){
printk(KERN_NOTICE "alloc gendisk failure\n");
ret = - ENOMEM;
goto error_disk;
}
my_gendiskp->major = gendisk_major;
my_gendiskp->first_minor = 0;
my_gendiskp->fops = &my_operations;
my_gendiskp->queue = my_request_queuep;
sprintf(my_gendiskp->disk_name, MYRAMDISK_NAME);
//设置块设备的大小,
set_capacity(my_gendiskp, (MYRAMDISK_SIZE>>9));
add_disk(my_gendiskp);
return 0;
error_disk:
blk_cleanup_queue(my_request_queuep);
error_queue:
//device_destroy(my_classp, MKDEV(gendisk_major, 0));
//class_destroy(my_classp);
//err_class:
unregister_blkdev(gendisk_major, MYRAMDISK_NAME);
return ret;
}
/*驱动模块卸载函数*/
static void __exit my_exit(void)
{
//device_destroy(my_classp, MKDEV(gendisk_major, 0));
//class_destroy(my_classp);
del_gendisk(my_gendiskp);
blk_cleanup_queue(my_request_queuep);
unregister_blkdev(gendisk_major, MYRAMDISK_NAME);
put_disk(my_gendiskp);
vfree(array_data);
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
以下是结果信息:
[root@FORLINX6410]# insmod /usr/mydriver/simp_blkdev.ko
[root@FORLINX6410]# ls dev/
audio tty tty46
console tty0 tty47
cpu_dma_latency tty1 tty48
device tty10 tty49
dsp tty11 tty5
fb0 tty12 tty50
fb1 tty13 tty51
fb2 tty14 tty52
fb3 tty15 tty53
full tty16 tty54
han_ramdisk tty17 tty55
i2c tty18 tty56
input tty19 tty57
kmsg tty2 tty58
leds tty20 tty59
log tty21 tty6
mem tty22 tty60
mixer tty23 tty61
mtd0 tty24 tty62
mtd0ro tty25 tty63
mtd1 tty26 tty7
mtd1ro tty27 tty8
mtd2 tty28 tty9
mtd2ro tty29 ttySAC0
mtd3 tty3 ttySAC1
mtd3ro tty30 ttySAC2
mtdblock0 tty31 ttySAC3
mtdblock1 tty32 urandom
mtdblock2 tty33 usbdev1.1
mtdblock3 tty34 vcs
network_latency tty35 vcs1
network_throughput tty36 vcs2
null tty37 vcs3
ppp tty38 vcs4
ptmx tty39 vcsa
pts tty4 vcsa1
pwm tty40 vcsa2
random tty41 vcsa3
rtc tty42 vcsa4
rtc0 tty43 video0
shm tty44 video1
snd tty45 zero
[root@FORLINX6410]# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound/mixer
14 sound/dsp
14 sound/audio
21 sg
29 fb
81 video4linux
89 i2c
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
180 usb
188 ttyUSB
189 usb_device
204 s3c2410_serial
253 BaseRemoteCtl
254 rtc
Block devices:
259 blkext
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
254 han_ramdisk
[root@FORLINX6410]# lsmod
simp_blkdev 1482 0 - Live 0xbf000000
[root@FORLINX6410]# mkfs.ext3 /dev/han_ramdisk
mke2fs 1.42.8 (20-Jun-2013)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
4096 inodes, 16384 blocks
819 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=16777216
2 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
[root@FORLINX6410]# mount /dev/han_ramdisk /usr/mountpoint/
yaffs: dev is 266338304 name is "han_ramdisk" rw
yaffs: passed flags ""
yaffs: dev is 266338304 name is "han_ramdisk" rw
yaffs: passed flags ""
mount: mounting /dev/han_ramdisk on /usr/mountpoint/ failed: Invalid argument
[root@FORLINX6410]#
/*********************************************************
File Name: simp_blkdev.c
Version: v0.1 2013-08-29
Description: Driver of a ** block device.
*********************************************************/
#include <linux/genhd.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#define MYRAMDISK_MAJOR 0 /*主设备号为0,动态生成设备号*/
#define MYRAMDISK_NAME "han_ramdisk" /*设备名称*/
#define MYRAMDISK_SIZE (16*1024*1024) /*虚拟磁盘大小,共16M*/
static int gendisk_major = MYRAMDISK_MAJOR; /*用来保存动态生成的设备号*/
//unsigned char array_data[MYRAMDISK_SIZE]; /*全局数组,表示本设备*/
unsigned char* array_data = NULL;
struct gendisk* my_gendiskp; /*定义一个磁盘*/
struct request_queue* my_request_queuep;/*定义一个与设备关联的请求队列*/
//static struct class* my_classp; /*定义一个设备类*/
static DEFINE_SPINLOCK(lock); /*全局变量,内核访问请求队列的自旋锁*/
/*块设备驱动操作结构体*/
static struct block_device_operations my_operations = {
.owner = THIS_MODULE,
};
static void sbd_transfer(sector_t sector, unsigned long nsect, char* buffer, int write)
{
unsigned long offset = (sector<<9);
unsigned long nbytes = (nsect<<9);
if((offset + nbytes) > MYRAMDISK_SIZE){
printk(KERN_NOTICE "sbd: Beyond-end write(%ld %ld)\n", offset, nbytes);
return;
}
if(write)
memcpy(array_data + offset, buffer, nbytes);
else
memcpy(buffer, array_data + offset, nbytes);
}
/*请求队列处理函数*/
static void my_process_on_request_queue(struct request_queue* q)
{
struct request *req;
req = blk_fetch_request(q);
while(req != NULL){
if(req->cmd_type != REQ_TYPE_FS){
printk(KERN_NOTICE "Skip non-CMD request\n");
__blk_end_request_all(req, -EIO);
continue;
}
sbd_transfer(blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
if(!__blk_end_request_cur(req, 0)){
req = blk_fetch_request(q);
}
}
}
/*驱动模块加载函数*/
static int __init my_init(void)
{
int ret; /*存放返回值*/
array_data = (char*)vmalloc(MYRAMDISK_SIZE);
/*1.块设备驱动注册,注意这个块设备驱动的注册函数在2.6内核中是可选的。改函数由内核提供,这里使用是为了生成一个动态生成的主设备号*/
gendisk_major = register_blkdev(gendisk_major, MYRAMDISK_NAME);
if(gendisk_major <= 0){
printk(KERN_WARNING "no major number\n");
return gendisk_major;
}
/*4.动态生成一个设备节点,跟字符设备一样*/ //这一点和cdev字符设备不同,不可以加否则模块加载和
/*my_classp = class_create(THIS_MODULE, MYRAMDISK_NAME);
if(IS_ERR(my_classp)){
ret = -1;
goto err_class;
}
device_create(my_classp, NULL, MKDEV(gendisk_major, 0), NULL, MYRAMDISK_NAME);*/
/*2.每个设备关联一个请求队列,我们在这里申请1个。需要注意的是:1)每个请求队列都对应一个“请求队列处理函数”,这个是设备相关的。2)每次分配一个请求队列的时候,必须提供一个自旋锁来控制对请求队列的访问,我们先不考虑并发访问*/
//spin_lock_init(&lock);
my_request_queuep = blk_init_queue(my_process_on_request_queue, &lock);
if(NULL == my_request_queuep){
printk("request queue error\n");
ret = -ENOMEM;
goto error_queue;
}
/*3.为代表本设备的结构体申请内存,这里的参数是本磁盘,使用的是次设备号的数目,一经申请,这个数字就不能改变。使用申请的资源为gendisk赋值。注册gendisk*/
my_gendiskp = alloc_disk(1);
if(NULL == my_gendiskp){
printk(KERN_NOTICE "alloc gendisk failure\n");
ret = - ENOMEM;
goto error_disk;
}
my_gendiskp->major = gendisk_major;
my_gendiskp->first_minor = 0;
my_gendiskp->fops = &my_operations;
my_gendiskp->queue = my_request_queuep;
sprintf(my_gendiskp->disk_name, MYRAMDISK_NAME);
//设置块设备的大小,
set_capacity(my_gendiskp, (MYRAMDISK_SIZE>>9));
add_disk(my_gendiskp);
return 0;
error_disk:
blk_cleanup_queue(my_request_queuep);
error_queue:
//device_destroy(my_classp, MKDEV(gendisk_major, 0));
//class_destroy(my_classp);
//err_class:
unregister_blkdev(gendisk_major, MYRAMDISK_NAME);
return ret;
}
/*驱动模块卸载函数*/
static void __exit my_exit(void)
{
//device_destroy(my_classp, MKDEV(gendisk_major, 0));
//class_destroy(my_classp);
del_gendisk(my_gendiskp);
blk_cleanup_queue(my_request_queuep);
unregister_blkdev(gendisk_major, MYRAMDISK_NAME);
put_disk(my_gendiskp);
vfree(array_data);
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
以下是结果信息:
[root@FORLINX6410]# insmod /usr/mydriver/simp_blkdev.ko
[root@FORLINX6410]# ls dev/
audio tty tty46
console tty0 tty47
cpu_dma_latency tty1 tty48
device tty10 tty49
dsp tty11 tty5
fb0 tty12 tty50
fb1 tty13 tty51
fb2 tty14 tty52
fb3 tty15 tty53
full tty16 tty54
han_ramdisk tty17 tty55
i2c tty18 tty56
input tty19 tty57
kmsg tty2 tty58
leds tty20 tty59
log tty21 tty6
mem tty22 tty60
mixer tty23 tty61
mtd0 tty24 tty62
mtd0ro tty25 tty63
mtd1 tty26 tty7
mtd1ro tty27 tty8
mtd2 tty28 tty9
mtd2ro tty29 ttySAC0
mtd3 tty3 ttySAC1
mtd3ro tty30 ttySAC2
mtdblock0 tty31 ttySAC3
mtdblock1 tty32 urandom
mtdblock2 tty33 usbdev1.1
mtdblock3 tty34 vcs
network_latency tty35 vcs1
network_throughput tty36 vcs2
null tty37 vcs3
ppp tty38 vcs4
ptmx tty39 vcsa
pts tty4 vcsa1
pwm tty40 vcsa2
random tty41 vcsa3
rtc tty42 vcsa4
rtc0 tty43 video0
shm tty44 video1
snd tty45 zero
[root@FORLINX6410]# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound/mixer
14 sound/dsp
14 sound/audio
21 sg
29 fb
81 video4linux
89 i2c
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
180 usb
188 ttyUSB
189 usb_device
204 s3c2410_serial
253 BaseRemoteCtl
254 rtc
Block devices:
259 blkext
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
254 han_ramdisk
[root@FORLINX6410]# lsmod
simp_blkdev 1482 0 - Live 0xbf000000
[root@FORLINX6410]# mkfs.ext3 /dev/han_ramdisk
mke2fs 1.42.8 (20-Jun-2013)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
4096 inodes, 16384 blocks
819 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=16777216
2 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
[root@FORLINX6410]# mount /dev/han_ramdisk /usr/mountpoint/
yaffs: dev is 266338304 name is "han_ramdisk" rw
yaffs: passed flags ""
yaffs: dev is 266338304 name is "han_ramdisk" rw
yaffs: passed flags ""
mount: mounting /dev/han_ramdisk on /usr/mountpoint/ failed: Invalid argument
[root@FORLINX6410]#