驅動的完成步驟: ~~~~ 1. 分配一個 gendisk 結構體 2. 註冊塊設備 3. 分配一個 request_queue 隊列 4. 配置 gendisk 5. 完成上一篇框架中提到的 "處理函數" 6. 添加磁碟 add_disk ~~~~ 初始化程式如下 ~~~~ static int ...
驅動的完成步驟:
1. 分配一個 gendisk 結構體
2. 註冊塊設備
3. 分配一個 request_queue 隊列
4. 配置 gendisk
5. 完成上一篇框架中提到的 "處理函數"
6. 添加磁碟 add_disk
初始化程式如下
static int ram_block_init(void)
{
int major;
struct request_queue *queue;
struct gendisk *ramdisk;
/* 分配 gendisk */
ramdisk = alloc_disk(1);
major = register_blkdev(0, DEVICE_NAME);
/* 分配隊列 */
queue = blk_init_queue(ram_block_request, &ramblock_lock);
/* 配置 gendisk */
ramdisk->queue = queue;
ramdisk->major = major;
ramdisk->first_minor = 0;
ramdisk->fops = &ram_block_fops;
sprintf(ramdisk->disk_name, "RamBlock");
/* 設置容量 */
set_capacity(ramdisk, RAMBLOCK_SIZE / 512);
/* 分配一段空間供傳輸使用 */
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
/* 添加磁碟 */
add_disk(ramdisk);
return 0;
}
module_init(ram_block_init);
ram_block_fops 及 ramblock_getgeo 函數
static struct block_device_operations ram_block_fops = {
.owner = THIS_MODULE,
.getgeo = ramblock_getgeo,
};
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 void ram_block_request(struct request_queue *q)
{
struct request *req;
/* 獲取到 request */
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);
/* 如果隊列沒有結束,獲取到下一個 request */
if (!__blk_end_request_cur(req, 0))
req = blk_fetch_request(q);
}
}
測試
1. 編譯並安裝驅動
2. 使用 mkdosfs 工具來格式化磁碟(mkdosfs /dev/RamBlock)
3. mount 磁碟至一個文件夾,例如 /tmp
4. 進入 /tmp 創建一個文件並寫入內容
5. umount 後再次 mount 查看文件內容
參考:
drivers\block\z2ram.c