1. 程式人生 > >塊裝置驅動1—用記憶體模擬磁碟

塊裝置驅動1—用記憶體模擬磁碟

塊裝置驅動的引入

不能像字元裝置那樣直接進行讀寫操作,效率會很低。而是要
-
把讀寫放入佇列

-         優化後再執行

塊裝置驅動的框架

app:        open    read    write  "test.text"
---------------------------------------------------------------- 
檔案的讀寫檔案系統:        vfat, ext2, yaffs
---------------------------------------------------------------- 
扇區的讀寫塊裝置驅動程式


----------------------------------------------------------------  
     
硬體:硬碟, flash

思路:
      -
(把檔案的讀寫轉化成扇區的讀寫)(電梯排程演算法)
      -  
把讀寫放入佇列

      -  呼叫佇列的處理函式(優化/調順序/合併/

塊裝置驅動程式編寫:

1. 分配gendisk:alloc_disk
2.
設定
      2.1
分配/設定佇列: blk_int_queue request_queuet         //提供讀寫能力

2.2 設定gendisk其它資訊                                                    //

提供屬性
3.
註冊:add_disk

舉例:使用記憶體模擬硬碟塊裝置操作   (參考xd.c  z2ran.c)

1.  修改/drivers/block/Kconfig,增加以下內容

             config RAM_BLOCK_YE

                   tristate"YE Test Ram Block"

2.  修改/drivers/block/Makefile,增加以下內容

    obj-$(CONFIG_RAM_BLOCK_YE)    += ramblock.o

3.  配置make menuconfig,選擇為M

4.  生成驅動模組, makeM=drivers/block

注:以下是測試步驟,但目前驅動有問題,不能全部實現以下功能。

測試1

1. 安裝驅動:   insmod ramblock.ko    

2. 格式化:    mk -> mkdosfs /dev/ramblock

3. 掛接:         cd/tmp -> mount/dev/ramblock /tmp/

4. 讀寫檔案:   cd /tmp -> vi test.txt

5. 退出後,再掛接,檢視是否有上次建立的檔案:

                      umount /tmp/

                         mount /dev/ramblock /tmp/

6. 掛接到PC上:cat /dev/ramblock > /mnt/ramblock.bin

                    sudo mount -o loop ramblock.bin /mnt

7. 分割槽:    fd->  fdisk /dev/ramblock

附程式碼:

static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static int major;

static DEFINE_SPINLOCK(ramblock_lock);

#define RAMBLOCK_SIZE (1024*1024)
static unsigned char *ramblock_buf;

static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
     /* 容量=heads*cylinders*sectors*512 */
    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(struct request_queue * q)
{
    struct request *req;

    req = blk_fetch_request(q);
    while (req) {
        unsigned long offset = blk_rq_pos(req) << 9;
        unsigned long len = blk_rq_cur_bytes(req);

        if (rq_data_dir(req) == READ)
        {
            memcpy(req->buffer, ramblock_buf+offset, len);
        }
        else
        {
            memcpy(ramblock_buf+offset, req->buffer, len);
        }

    __blk_end_request_cur(req, 1);
    }
}

static int ramblock_init(void)
{
    /* 1. 申請裝置號 */
    major = register_blkdev(0, "ramblock");

   /* 2. 分配gendisk結構體 */
    ramblock_disk = alloc_disk(16);

    /* 3. 分配請求佇列,繫結請求佇列和請求函式 */
    ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);

    /* 4. 給gendisk成員賦值 */
    ramblock_disk->major = major;
    ramblock_disk->first_minor = 0;
    ramblock_disk->fops = &ramblock_fops;
    sprintf(ramblock_disk->disk_name, "ramblock");
    ramblock_disk->queue = ramblock_queue;
    
    /* 5. 註冊 */
    add_disk(ramblock_disk);
    //blk_register_region(MKDEV(major, 0), 8, THIS_MODULE,z2_find, NULL, NULL);

    return 0;
}

static void ramblock_exit(void)
{
    //blk_unregister_region(MKDEV(major, 0), 8);
    unregister_blkdev(major, "ramblock");
    del_gendisk(ramblock_disk);
    put_disk(ramblock_disk);
    blk_cleanup_queue(ramblock_queue);
    kfree(ramblock_buf);
}

module_init(ramblock_init);
module_exit(ramblock_exit);

MODULE_LICENSE("GPL");