参考内核块设备驱动写:z2ram.c在内存中开辟一块空间来模拟成块设备


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/blkdev.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
/*参考内核块设备驱动写:z2ram.c在内存中开辟一块空间来模拟成块设备*/
/*转载请注明原文地址:http://blog.csdn.net/oyhb_1992
测试方法:
1 insmod
2 格式化 mkdosfs /dev/xxx
3 挂载块设备 mount  /dev/xxx  /mnt
4 读写块设备
*/
enum {
	SECTOR_SIZE = 512,//扇区大小
	DEVICE_SIZE = SECTOR_SIZE*2*1024*1, //设备容量1M
};
#define DEVICE_NAME "ldm_blk"
//static DEFINE_SPINLOCK(ldm_lock);//静态创建自旋锁
struct ldm_info{    //自定义结构体描述驱动
	struct gendisk *dev;    	//块设备描述结构体
	spinlock_t ldm_lock; //动态创建自旋锁
	struct block_device_operations ldm_fops;	//操作函数集
	void * addr;//在内存中开辟一块空间来模拟成块设备,
};

static struct ldm_info ldm;
//块设备的请求队列操作函数
static void ldm_request(struct request_queue *q)
{
	struct request *req;
	//从队列里取出一个请求
	req = blk_fetch_request(q);
	while (req) {
		unsigned long start = blk_rq_pos(req) * SECTOR_SIZE;  //扇区号*512= 从哪个字节开始访问,偏移量
		unsigned long len  = blk_rq_cur_bytes(req);  //这次请求需要操作多少个字节
		
			if (rq_data_dir(req) == READ)   //应用层要读数据
				{
					memcpy(req->buffer, (char *)ldm.addr+start, len);
					printk("read %d bytes from addr %d\n", start, len);//可观察到应用层发出请求后,块设备
					//驱动不一定马上响应,有一个缓存机制,可能会把几个请求合成为一个请求,减少请求次数,
					//存储设备只适合于大文件批量写入,
				}
			else		//应用层要写数据
				{
					memcpy((char *)ldm.addr+start, req->buffer, len);
					printk("write %d bytes from addr %d\n", start, len);
				}

	done:
		if (!__blk_end_request_cur(req, 0)){  //检查当前请求是否完成,
			//完成请求返回0,未完成返回1
			req = blk_fetch_request(q);   //获取下一个请求,请求处理完req = NULL
		}
	}
}

static int test_init(void)
{
	int ret;
	/*参考内核块设备驱动写:z2ram.c在内存中开辟一块空间来模拟成块设备*/
	printk("%s: %s \n", __FUNCTION__, __FILE__);
	//1:申请主设备号:参考内核源码Documentation/devices.txt查找空闲的块设备号,
	//或者由系统自动分配:添0就是自动分配
	/*ldm.dev->major = register_blkdev(0, DEVICE_NAME);
	if (ldm.dev->major)//申请块设备号
	{
		printk(KERN_ERR "register_blkdev failed\n");
		goto err;
	}*/
	if (register_blkdev(125, DEVICE_NAME))//申请块设备号
	{
		printk(KERN_ERR "register_blkdev failed\n");
		goto err;
	}
	//2:创建块设备主对象,参数是次设备号
	ldm.dev = alloc_disk(10);
    if (!ldm.dev)
	{
		ret = -ENOMEM;
		printk(KERN_ERR "alloc_disk failed\n");
		goto out_disk;
	}
	//3:初始化自旋锁spinlock.h
	spin_lock_init(&ldm.ldm_lock);
	//4:为块设备创建操作队列,当应用层操作当前块设备时,操作请求会被发送到请求队列中
	//,由驱动响应操作请求。
	ldm.dev->queue = blk_init_queue(ldm_request, &ldm.ldm_lock);
    if (!ldm.dev->queue)
	{
		printk(KERN_ERR "blk_init_queue failed\n");
		goto out_queue;
	}	
	//5:填充块设备主对象的成员
	//ldm.dev->major = Z2RAM_MAJOR;
    ldm.dev->first_minor = 0;
    ldm.dev->fops = &ldm.ldm_fops;
    sprintf(ldm.dev->disk_name, DEVICE_NAME);  //创建出的设备节点名字
	//strcpy(ldm.dev->disk_name, DEVICE_NAME);   //等价

	//6:设置块设备容量大小 >> 9 = /512 单位是扇区不是字节
	set_capacity(ldm.dev, DEVICE_SIZE/SECTOR_SIZE);
	//7:注册块设备
	add_disk(ldm.dev);
	//8:给设备分配存储空间,这里用内存来虚拟存储设备
	//vmalloc适合分配大块内存,在物理地址上不连续,在虚拟地址上是连续的,是
	//通过小块的内存碎片拼接而成
	//kmalloc分配的内存是物理地址上连续的,不适合分配大块内存
	ldm.addr = vmalloc(DEVICE_SIZE);//vzalloc分配空间并清零模拟块设备
	if(NULL == ldm.addr)
	{
		printk(KERN_ERR "vmalloc failed\n");
		ret = -ENOMEM;
		goto err_vmalloc;
	}
   // blk_register_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT, THIS_MODULE,
	//			z2_find, NULL, NULL);

    return 0;
err_vmalloc:
	blk_cleanup_queue(ldm.dev->queue);
out_queue:
    put_disk(ldm.dev);  //alloc_disk
out_disk:
    unregister_blkdev(0, DEVICE_NAME);
err:
    return ret;
}


static void __exit test_exit(void)
{
	printk("%s: %s \n", __FUNCTION__, __FILE__);
	del_gendisk(ldm.dev);   //和test_init注册时相反
	vfree(ldm.addr);
	blk_cleanup_queue(ldm.dev->queue);  
    unregister_blkdev(ldm.dev->major, DEVICE_NAME);
    put_disk(ldm.dev);
   
    return;
} 
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");



















安装模块后,在响应块设备请求时mencpy出现了段错误!原因正在查找


# insmod ldm_blk.ko 
test_init: /home/S5-driver/lesson8/ldm_blk/ldm_blk.c 
------------[ cut here ]------------
WARNING: at block/genhd.c:526 add_disk+0x78/0x150()
Modules linked in: ldm_blk(+)
Backtrace: 
[<c0035228>] (dump_backtrace+0x0/0x10c) from [<c0337810>] (dump_stack+0x18/0x1c)
 r7:00000000 r6:c0145e1c r5:c03fea8c r4:0000020e
[<c03377f8>] (dump_stack+0x0/0x1c) from [<c0049ef0>] (warn_slowpath_common+0x4c/0x80)
[<c0049ea4>] (warn_slowpath_common+0x0/0x80) from [<c0049f3c>] (warn_slowpath_null+0x18/0x1c)
 r7:bf0002f0 r6:bf0004bc r5:c3948a00 r4:c3948a00
[<c0049f24>] (warn_slowpath_null+0x0/0x1c) from [<c0145e1c>] (add_disk+0x78/0x150)
[<c0145da4>] (add_disk+0x0/0x150) from [<bf000098>] (test_init+0x98/0x130 [ldm_blk])
 r5:bf0004b8 r4:c3948a00
[<bf000000>] (test_init+0x0/0x130 [ldm_blk]) from [<c003032c>] (do_one_initcall+0x3c/0x1c8)
 r9:00000000 r8:c048b040 r7:c39c2000 r6:bf000398 r5:001c85fd
r4:00000f50
[<c00302f0>] (do_one_initcall+0x0/0x1c8) from [<c0070144>] (sys_init_module+0xd0/0x204)
[<c0070074>] (sys_init_module+0x0/0x204) from [<c0030f20>] (ret_fast_syscall+0x0/0x28)
 r7:00000080 r6:beab1eb8 r5:00000000 r4:00000000
---[ end trace d6d69c142c6be93f ]---
 ldm_blk:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c39d8000
[00000000] *pgd=339d4031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
last sysfs file: /sys/devices/platform/soc-audio/sound/card0/mixer/dev
Modules linked in: ldm_blk(+)
CPU: 0    Tainted: G        W   (2.6.32.2-FriendlyARM #8)
PC is at memcpy+0x28/0x29c
LR is at ldm_request+0x78/0xe0 [ldm_blk]
pc : [<c01493e8>]    lr : [<bf0001a8>]    psr: 20000093
sp : c39c3c1c  ip : 00000000  fp : c39c3c5c
r10: c0075d0c  r9 : 00000001  r8 : c39168c8
r7 : bf0004b8  r6 : 00000000  r5 : 00001000  r4 : c38b1640
r3 : 01082420  r2 : 00000fe0  r1 : 00000000  r0 : c39e0000
Flags: nzCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 339d8000  DAC: 00000015
Process insmod (pid: 637, stack limit = 0xc39c2270)
Stack: (0xc39c3c1c to 0xc39c4000)
3c00:                                                                00001000
3c20: 00000000 bf0004b8 c39168c8 c39e0000 c38b1640 bf0001a8 c39168c8 c39c3d08
3c40: c39c3cfc c0540168 00000002 00000001 c39c3c74 c39c3c60 c013fcdc bf000140
3c60: c39c3cf4 c39c3d08 c39c3c84 c39c3c78 c013fd08 c013fcac c39c3c94 c39c3c88
3c80: c013de68 c013fcf0 c39c3ca4 c39c3c98 c013de80 c013de58 c39c3cb4 c39c3ca8
3ca0: c00be68c c013de7c c39c3cc4 c39c3cb8 c0075d48 c00be658 c39c3cec c39c3cc8
3cc0: c03386ec c0075d1c 00000000 c39c3d08 c3894f00 00000000 00000000 c00c5f68
3ce0: c39c3d2c c39c3cf0 c0075ce0 c0338698 c00760d4 c0533c00 00000000 00000001
3d00: c3894f00 c005f198 c0540168 c0540168 c39c3d2c c0533c00 00000000 c3402280
3d20: c39c3d54 c39c3d30 c0076404 c0075c3c 00000000 c39c3dd4 c393b000 c00df474
3d40: c3402180 c393b000 c39c3d6c c39c3d58 c00764ac c0076340 00000000 c39c3dd4
3d60: c39c3d84 c39c3d70 c00de8f8 c00764ac 00000000 c3948a00 c39c3e04 c39c3d88
3d80: c00df4c0 c00de8d8 ffffffff ffffffff c3948a50 c3402180 c3948a00 c393b000
3da0: 00000000 c3402180 c39c3e6c 00000000 c39c3dd4 00000000 c3948a00 c393b000
3dc0: c3402190 c3402180 c39c3e6c 00000000 c39c3df4 c39c3de0 c033796c 00000000
3de0: c3948a00 c393b000 c00df474 c3402180 c393b020 00000000 c39c3e5c c39c3e08
3e00: c00df16c c00df484 c3948a50 00000000 c39c3e34 c39c3e20 c014bba0 00000000
3e20: c3948a00 00000000 00000001 00000002 c0185068 c3402180 00000000 c3948a00
3e40: c3402190 00000000 c39c3e6c 00000001 c39c3e9c c39c3e60 c00c6578 c00df028
3e60: c014ba44 00000000 c00c5c98 00000000 c39c3e7c c3948a00 00000001 c3948a50
3e80: c3402180 00000000 00000000 bf000000 c39c3eac c39c3ea0 c00c6758 c00c642c
3ea0: c39c3edc c39c3eb0 c00dea8c c00c6754 c3948a00 c3948a00 c3948a00 bf0004bc
3ec0: c3948a00 c3948a00 bf0004bc bf0002f0 c39c3f0c c39c3ee0 c0145e8c c00de960
3ee0: c0145300 c0145840 c3948a00 bf000000 c39c3f0c 00000000 c3948a00 bf0004b8
3f00: c39c3f34 c39c3f10 bf000098 c0145db4 00000f50 001c85fd bf000398 c39c2000
3f20: c048b040 00000000 c39c3f7c c39c3f38 c003032c bf000010 00000000 00000000
3f40: 00000000 00000f50 001c85fd bf000398 00000000 00000f50 001c85fd bf000398
3f60: 00000000 c00310c8 c39c2000 00000000 c39c3fa4 c39c3f80 c0070144 c0030300
3f80: c009b118 c009b008 00000000 00000000 beab1eb8 00000080 00000000 c39c3fa8
3fa0: c0030f20 c0070084 00000000 00000000 001e0fd8 00000f50 001c85fd 00000000
3fc0: 00000000 00000000 beab1eb8 00000080 beab1eb4 beab1eb8 00000001 beab1eb4
3fe0: 00000069 beab1b7c 0002bf44 000094b4 60000010 001e0fd8 30542031 30542431
Backtrace: 
[<bf000130>] (ldm_request+0x0/0xe0 [ldm_blk]) from [<c013fcdc>] (__generic_unplug_device+0x40/0x44)
 r9:00000001 r8:00000002 r7:c0540168 r6:c39c3cfc r5:c39c3d08
r4:c39168c8
[<c013fc9c>] (__generic_unplug_device+0x0/0x44) from [<c013fd08>] (generic_unplug_device+0x28/0x38)
 r5:c39c3d08 r4:c39c3cf4
[<c013fce0>] (generic_unplug_device+0x0/0x38) from [<c013de68>] (blk_unplug+0x20/0x24)
[<c013de48>] (blk_unplug+0x0/0x24) from [<c013de80>] (blk_backing_dev_unplug+0x14/0x18)
[<c013de6c>] (blk_backing_dev_unplug+0x0/0x18) from [<c00be68c>] (block_sync_page+0x44/0x48)
[<c00be648>] (block_sync_page+0x0/0x48) from [<c0075d48>] (sync_page+0x3c/0x48)
[<c0075d0c>] (sync_page+0x0/0x48) from [<c03386ec>] (__wait_on_bit_lock+0x64/0xb0)
[<c0338688>] (__wait_on_bit_lock+0x0/0xb0) from [<c0075ce0>] (__lock_page+0xb4/0xc8)
[<c0075c2c>] (__lock_page+0x0/0xc8) from [<c0076404>] (read_cache_page_async+0xd4/0x16c)
 r6:c3402280 r5:00000000 r4:c0533c00
[<c0076330>] (read_cache_page_async+0x0/0x16c) from [<c00764ac>] (read_cache_page+0x10/0x68)
[<c007649c>] (read_cache_page+0x0/0x68) from [<c00de8f8>] (read_dev_sector+0x30/0x88)
 r5:c39c3dd4 r4:00000000
[<c00de8c8>] (read_dev_sector+0x0/0x88) from [<c00df4c0>] (msdos_partition+0x4c/0x750)
 r5:c3948a00 r4:00000000
[<c00df474>] (msdos_partition+0x0/0x750) from [<c00df16c>] (rescan_partitions+0x154/0x3d8)
[<c00df018>] (rescan_partitions+0x0/0x3d8) from [<c00c6578>] (__blkdev_get+0x15c/0x328)
[<c00c641c>] (__blkdev_get+0x0/0x328) from [<c00c6758>] (blkdev_get+0x14/0x18)
[<c00c6744>] (blkdev_get+0x0/0x18) from [<c00dea8c>] (register_disk+0x13c/0x160)
[<c00de950>] (register_disk+0x0/0x160) from [<c0145e8c>] (add_disk+0xe8/0x150)
 r7:bf0002f0 r6:bf0004bc r5:c3948a00 r4:c3948a00
[<c0145da4>] (add_disk+0x0/0x150) from [<bf000098>] (test_init+0x98/0x130 [ldm_blk])
 r5:bf0004b8 r4:c3948a00
[<bf000000>] (test_init+0x0/0x130 [ldm_blk]) from [<c003032c>] (do_one_initcall+0x3c/0x1c8)
 r9:00000000 r8:c048b040 r7:c39c2000 r6:bf000398 r5:001c85fd
r4:00000f50
[<c00302f0>] (do_one_initcall+0x0/0x1c8) from [<c0070144>] (sys_init_module+0xd0/0x204)
[<c0070074>] (sys_init_module+0x0/0x204) from [<c0030f20>] (ret_fast_syscall+0x0/0x28)
 r7:00000080 r6:beab1eb8 r5:00000000 r4:00000000
Code: 1a000031 e252201c e92d01e0 ba000003 (e8b151f8) 
---[ end trace 2c6be940c048b8b0 ]---
Segmentation fault
# s3c2410fb: blank(mode=1, info=c3872800)
s3c2410fb: setting TPAL to output 0x000000
lk.ko 








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值