Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98107
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 384
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-06 16:52
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-12 23:00:49

目的:把内存当作块设备使用
可以参考/driver/block/z2ram.c这个驱动程序

块设备驱动程序:
1. 分配gendisk: alloc_disk
2. 设置
2.1 分配/设置队列: request_queue_t  // 它提供读写能力
    blk_init_queue
2.2 设置gendisk其他信息             // 它提供属性: 比如容量
3. 注册: add_disk

代码如下

点击(此处)折叠或打开

  1. /* 参考:
  2.  * drivers\block\xd.c
  3.  * drivers\block\z2ram.c
  4.  */
  5. #include <linux/module.h>
  6. #include <linux/errno.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/mm.h>
  9. #include <linux/fs.h>
  10. #include <linux/kernel.h>
  11. #include <linux/timer.h>
  12. #include <linux/genhd.h>
  13. #include <linux/hdreg.h>
  14. #include <linux/ioport.h>
  15. #include <linux/init.h>
  16. #include <linux/wait.h>
  17. #include <linux/blkdev.h>
  18. #include <linux/mutex.h>
  19. #include <linux/blkpg.h>
  20. #include <linux/delay.h>
  21. #include <linux/io.h>
  22. #include <linux/gfp.h>
  23. #include <linux/vmalloc.h>

  24. #include <asm/uaccess.h>
  25. #include <asm/dma.h>

  26. #define RAMBLOCK_SIZE 0x100000

  27. static int major;
  28. static struct gendisk *ramblock_disk;
  29. static struct request_queue *ramblock_queue;
  30. static unsigned char *ramblock_buf;

  31. static DEFINE_SPINLOCK(ramblock_lock);//自旋锁

  32. static int ramblock_getgeo(struct block_device *dev, struct hd_geometry *geo)//分区时要用到
  33. {
  34.     /* 数值为模拟数值,可以随便设 */
  35.     /* 容量 = heads * cylinders * sectors *512 */
  36.     geo->heads = 2;//有多少面
  37.     geo->cylinders = 128;//有多少柱面
  38.     geo->sectors = RAMBLOCK_SIZE / 2 / 128 / 512;//有多少扇区
  39.     return 0;
  40. }

  41. static struct block_device_operations ramblock_fops =
  42. {
  43.     .owner        = THIS_MODULE,
  44.     .getgeo = ramblock_getgeo,
  45. };

  46. static void do_ramblock_request(struct request_queue *q)
  47. {
  48.     static int r_cnt = 0;
  49.     static int w_cnt = 0;
  50.     struct request *req;
  51.     
  52.     req = blk_fetch_request(q);
  53.     while ( req ) {
  54.         /* 数据传输3要素:,目的,长度 */
  55.         /*/目的 */
  56.         unsigned long offset = blk_rq_pos(req) * 512;

  57.         /* 目的/: req->buffer */

  58.         /* 长度 */
  59.         unsigned long len = blk_rq_cur_bytes(req);

  60.         if (rq_data_dir(req) == READ)
  61.         {
  62.             printk("do_ramblock_request read %d\n", ++r_cnt);
  63.             memcpy(req->buffer, ramblock_buf+offset, len);
  64.         }
  65.         else
  66.         {
  67.             printk("do_ramblock_request write %d\n", ++w_cnt);
  68.             memcpy(ramblock_buf+offset, req->buffer, len);
  69.         }
  70.     
  71.         if (!__blk_end_request_cur(req, 0))
  72.             req = blk_fetch_request(q);
  73.     }
  74. }

  75. static int ramblock_init(void)
  76. {
  77.     /* 0. 注册块设备,register_blkdev : cat /proc/devices */
  78.     major = register_blkdev(0, "ramblock");
  79.     
  80.     /* 1. 分配gendisk */
  81.     ramblock_disk = alloc_disk(2); /* 次设备号个数:分区个数2 */

  82.     /* 2. 设置 */
  83.     /* 2.1 设置队列: 提供读写的能力 */
  84.     ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);
  85.     ramblock_disk->queue = ramblock_queue;

  86.     /* 2.2 设置属性: 比如容量,主设备号,第1个次设备号,操作函数等 */
  87.     ramblock_disk->major = major;//主设备号
  88.     ramblock_disk->first_minor = 0; /* 第一个次设备号,(major,0),(major,1) */
  89.     ramblock_disk->fops = &ramblock_fops;
  90.     set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);//设置容量,以扇区为单位,对于内存,永远认为扇区容量为512字节
  91.     sprintf(ramblock_disk->disk_name, "ramblock");

  92.     /* 3. 硬件相关操作 */
  93.     ramblock_buf = vmalloc(RAMBLOCK_SIZE);

  94.     /* 4. 注册 */
  95.     add_disk(ramblock_disk);
  96.     
  97.     return 0;
  98. }

  99. static void ramblock_exit(void)
  100. {
  101.     unregister_blkdev(major, "ramblock");
  102.     del_gendisk(ramblock_disk);
  103.     put_disk(ramblock_disk);
  104.     blk_cleanup_queue(ramblock_queue);
  105. }

  106. module_init(ramblock_init);
  107. module_exit(ramblock_exit);

  108. MODULE_LICENSE("GPL");

测试:
在开发板上:
1. 加载驱动: insmod ramblock.ko
2. 格式化: mkdosfs /dev/ramblock
3. 挂载到/tmp目录: mount /dev/ramblock /tmp/
4. 读写文件: cd /tmp, 在里面vi文件,如1.txt
5. 解除挂载:cd /; umount /tmp/
6. 重新挂载到/tmp目录: mount /dev/ramblock /tmp/,发现刚刚创建的文件依然存在
7.把ramblock里的内容导出为二进制文件: cat /dev/ramblock > /mnt/ramblock.bin
8. 在PC上查看ramblock.bin:sudo mount -o loop ramblock.bin /mnt,在ubuntu的/mnt下看到了在开发板上创建的那个文件
9. ramblock分区:fdisk /dev/ramblock,根据帮助提示完成分区
10.查看分区: ls /dev/ramblock* -l  ,发现有了新分区,次设备号0代表整个ramblock



阅读(1420) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~