总览 
本文使用 linux-2.6.22.6 内核, 使用jz2440开发板.
块设备的驱动框架 驱动框架 
ll_rw_block: Low Level Read/Write block devicesubmit_bh: submit Buffer Headsubmit_bio: submit Block IO (Input/Output)elv_merge: elevator merge. 用电梯算法合并数据 
硬盘基础概念 块设备为了兼容机械结构的硬盘, 使用了一些硬盘特有的概念.
存储容量 = 磁头数 x 柱面数 x 扇区数 x 512(扇区字节数)存储容量 = 柱面大小 x 柱面数柱面大小 = 磁头数 x 扇区数 x 512(扇区字节数) 
英语 
中文 
说明 
 
 
Disk 
磁盘 
就是硬盘 
 
Platter 
圆盘 
硬盘的盘片 
 
Head 
磁头 
盘片有2面: 2磁头/圆盘 
 
Track 
磁道 
圆盘被分割为多个同心圆, 即磁道 
 
Sector 
扇区 
磁道被分割后的扇形区域 
 
Cylinder 
柱面 
由多个圆盘的同一磁道构成 
 
Partition 
分区 
软件概念, 以柱面为单位 
 
参考资料 
块设备驱动范例 块设备驱动的实现更为简单. Linux内核做掉了大部分工作, 驱动层只需要专注于硬件的块读写功能.
可以参考内核里的两个文件
drivers\block\xd.c 用于 XT hard disk.drivers\block\z2ram.c ram disk.给出的源码没有做返回值判断, 实际使用时务必参考上面的范例实现错误处理 . 
 
基本步骤如下:
分配gendisk: alloc_disk 
设置blk_init_queue 
硬件初始化操作 
注册: add_disk 
 
ramblock.c #include  <linux/major.h>  #include  <linux/vmalloc.h>  #include  <linux/init.h>  #include  <linux/module.h>  #include  <linux/blkdev.h>  #include  <linux/hdreg.h>  MODULE_LICENSE("GPL" ); MODULE_AUTHOR("DRAAPHO" ); #define  DEVICE_NAME "RAMDISK"  #define  RAMBLOCK_SIZE (1024*1024) static  int  major;static  struct  gendisk  *ramblock_disk ;static  request_queue_t  *ramblock_queue;static  DEFINE_SPINLOCK (ramblock_lock) static  unsigned  char  *ramblock_buf;static  int  ramblock_getgeo (struct block_device *bdev, struct hd_geometry *geo)     geo->heads     = 2 ;                                          geo->cylinders = 32 ;                                         geo->sectors   = RAMBLOCK_SIZE/2 /32 /512 ;                     return  0 ; } static  struct  block_device_operations  ramblock_fops  =    .owner  = THIS_MODULE,     .getgeo = ramblock_getgeo, }; static  void  do_ramblock_request (request_queue_t  * q)     static  int  r_cnt = 0 ;     static  int  w_cnt = 0 ;     struct  request  *req ;     while  ((req = elv_next_request(q)) != NULL ) {                    unsigned  long  offset = req->sector*512 ;                      unsigned  long  len = req->current_nr_sectors*512 ;             if  (rq_data_dir(req) == READ) {                                  printk("do_ramblock_request read %d\n" , ++r_cnt);             memcpy (req->buffer, ramblock_buf+offset, len);           } else  {                                                         printk("do_ramblock_request write %d\n" , ++w_cnt);             memcpy (ramblock_buf+offset, req->buffer, len);           }         end_request(req, 1 );                                     } } static  int  ramblock_init (void )          ramblock_disk = alloc_disk(16 );                                        ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);     ramblock_disk->queue  = ramblock_queue;          major = register_blkdev(0 , DEVICE_NAME);                     ramblock_disk->major       = major;                          ramblock_disk->first_minor = 0 ;                              sprintf (ramblock_disk->disk_name, "ramblock" );     ramblock_disk->fops        = &ramblock_fops;     set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512 );                 ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);          add_disk(ramblock_disk);     return  0 ; } static  void  ramblock_exit (void )     del_gendisk(ramblock_disk);                          put_disk(ramblock_disk);                             blk_cleanup_queue(ramblock_queue);                   unregister_blkdev(major, DEVICE_NAME);               kfree(ramblock_buf);                             } module_init(ramblock_init); module_exit(ramblock_exit); 
Makefile obj-m       := ramblock.o KERN_SRC    := /home/draapho/share/jz2440/kernel/linux-2.6.22.6/ PWD         := $(shell  pwd)  modules:     make -C $(KERN_SRC)  M=$(PWD)  modules clean:     make -C $(KERN_SRC)  M=$(PWD)  clean 
测试 $ make modules                                   $ insmod ramblock.ko  ramblock:do_ramblock_request read  1  unknown partition table                         $ ls /dev/ramblock*                              $ cat /proc/devices 254 RAMDISK                                      $ mkdosfs /dev/ramblock                          $ mount /dev/ramblock /tmp                       $ vi /tmp/test                                    do_ramblock_request read  43                      $ sync                                           do_ramblock_request write 6 do_ramblock_request write 7 ...... $ cp ramblock.c /tmp/                            $ sync                                           do_ramblock_request write 11 do_ramblock_request write 12 ...... $ ls /tmp                                        ramblock.c  test  $ umount /tmp                                    do_ramblock_request write 16 ......              $ ls /tmp                                        $cat  /dev/ramblock > ./ramblock.bin             do_ramblock_request read  ...... $ sudo mount -o loop ramblock.bin /mnt           $ ls /mnt                                        ramblock.c  test  $ sudo umount /mnt $ mkdir /ramdisk $ mount /dev/ramblock /ramdisk                   $ ls /ramdisk                                    ramblock.c  test  $ df                                             Filesystem           1k-blocks      Used Available Use% Mounted on /dev/ramblock             1004         6       998   1% /ramdisk $ umount /ramdisk                                $ rmdir /ramdisk $ rmmod ramblock                                 $ insmod ramblock.ko $ ls /dev/ramblock*                              /dev/ramblock                                    $ fdisk /dev/ramblock m                                                n p Partition number: 1 cylinder value: 1-8      n p Partition number: 2 cylinder value: 9-32     p                                                w                                                $ ls /dev/ramblock* -l                           brw-rw----    1 0        0        254,   0 Jan  1 00:01 /dev/ramblock    brw-rw----    1 0        0        254,   1 Jan  1 00:01 /dev/ramblock1   brw-rw----    1 0        0        254,   2 Jan  1 00:01 /dev/ramblock2   $ mkdosfs /dev/ramblock1                         $ mkdosfs /dev/ramblock2 $ mkdir /mnt/ramdisk1                            $ mkdir /mnt/ramdisk2 $ mount /dev/ramblock1 /mnt/ramdisk1             $ mount /dev/ramblock2 /mnt/ramdisk2 $ mkdosfs /dev/ramblock                          $ umount /mnt/ramdisk1 $ umount /mnt/ramdisk2 $ rmdir /mnt/ramdisk1 $ rmdir /mnt/ramdisk2 
原创于 DRA&PHO