一個極簡單的 塊設備驅動 的編寫

目標平臺:loongson 1B

目標系統:1b-linux-3.0

目標開發板架構:mipsel架構

實現平臺:ubuntu 13.04 

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>

#define RAMDISK_SIZE (1024*1024)
static DEFINE_SPINLOCK(ramdisk_lock); // 申請自旋鎖

static int major;
static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static unsigned char *ram_buff;

static const struct block_device_operations ramdisk_fops = {
.owner = THIS_MODULE,
};

  // 關鍵:offset, len 
static void ramblock_do_request(struct request_queue * q)
{
 	 struct request *req;
	u16 offset;
	u16 len;
	printk("ramblock do request \n");
    // 從request_queue 隊列中獲取一個request 
        req = blk_fetch_request(q);
	while (req)
    	 {
 	   offset = blk_rq_pos(req)*512;  //獲取 ramdisk塊設備的偏移位置
   	   len = blk_rq_cur_bytes(req);// 想要寫入或讀ramdisk塊設備的大小
	
	    if (  rq_data_dir(req)== READ)    //
 	       memcpy(req->buffer, ram_buff+offset, len);
	   else
		memcpy(ram_buff+offset, req->buffer, len);

  	   if (!__blk_end_request_cur(req,0)) // 判斷ramdisk塊設備的讀寫是否完成。每個塊設備都有一個請求隊列
   	     req = blk_fetch_request(q);
        }


}

//關鍵: 塊設備的的初始化:
 1) 塊設備註冊
 2) 請求隊列的綁定
 3) 設置塊容量
 4) 註冊塊設備
static int simp_blkdev_init(void)
{
	/*獲得主設備號及 設備名*/
	major = register_blkdev(major, "ramdisk");

	/*1.1分配一個gendisk結構體*/
	ramblock_disk = alloc_disk(1);
	/*1.2設置其他信息*/
	ramblock_disk->major = major;
	ramblock_disk->first_minor = 0;
	sprintf(ramblock_disk->disk_name, "ramdisk");
	ramblock_disk->fops = &ramdisk_fops;

	/*2. 1 設置一個請求隊列*/
	ramblock_queue = blk_init_queue(ramblock_do_request, &ramdisk_lock);
	ramblock_disk->queue = ramblock_queue;

	//設置塊設備大小
	set_capacity(ramblock_disk, RAMDISK_SIZE);

	/*註冊*/
	 add_disk(ramblock_disk);

         ram_buff = kzalloc(RAMDISK_SIZE, GFP_KERNEL);
	printk("module simp_blkdev added.\n");
  	return  0;
}

關鍵:
1) 註銷設備號
2) 釋放ramblock所佔的內容
3)銷燬隊列
4)釋放內存
static void simp_blkdev_exit(void)
{
  
	unregister_blkdev(major, "ramdisk");
	del_gendisk(ramblock_disk);
	put_disk(ramblock_disk);   //對應於set_capacity
	blk_cleanup_queue(ramblock_queue);
	kfree(ram_buff); 
	printk("exit\n");
}
module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);
MODULE_AUTHOR("<hzg>");
MODULE_DESCRIPTION("block dev ");
MODULE_LICENSE("GPL");
之後的步驟如下:

    a)make 一下,生成ramdisk.ko;

    b)編譯好了之後,就可以安裝驅動了,在linux下是這麼做的,sudo insmod ramdisk.ko;

    c)安裝好了,利用ls /dev/ram*, 就會發現在/dev下有個新結點,即/dev/ramdisk;

    d)進行分區處理, sudo fdisk /dev/ramdisk,簡單處理的話就建立分區, 生成/dev/ramdisk;

    e)創建文件系統,sudo mkfs.ext3 /dev/ramdisk;

    f)有了上面的文件系統,就可以進行mount處理,不妨sudo mount /dev/ramdisk  /mnt;

    g)上面都弄好了,大家就可以copy、delete文件試試了,是不是很簡單。




發佈了25 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章