整體過程:
1註冊register_blkdev;
2定義裝置結構體以及初始化結構圖sbull_dev;
3建立裝置請求佇列 dev->queue = blk_init_queue(sbull_request, &dev->lock);
4分配、初始化及安裝相應的gendisk結構dev->gd = alloc_disk(sbull_minors)。dev = ,,;
5設定佇列支援的扇區大小blk_queue_hardsect_size(dev->queue, hardset_size);
6實現操作函式,開啟,關閉
7處理請求操作
1、註冊:向核心註冊個塊裝置驅動,其實就是用主裝置號告訴核心這個代表塊裝置驅動
[cpp]view plain
copy
sbull_major = register_blkdev(sbull_major, "sbull");
if (0 >= sbull_major)
2、定義裝置結構體:
[cpp]view plain
copy
struct sbull_dev;
3、初始化裝置結構體:
[cpp]view plain
copy
memset(dev, 0, sizeof(struct sbull_dev));
dev->size = nsectors * hardsect_size;
dev->data = vmalloc(dev->size);
if (dev->data == null)
spin_lock_init(&dev->lock);//初始化自旋鎖,為了下一步的佇列分配
4、建立裝置的請求佇列:
dev->queue = blk_init_queue(sbull_request, &dev->lock);
5、分配、初始化及安裝相應的gendisk結構:
[cpp]view plain
copy
dev->gd = alloc_disk(sbull_minors);
if (!dev->gd)
dev->gd->major = sbull_major;
dev->gd->first_minor = which*sbull_minors;
dev->gd->fops = &sbull_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data= dev;
snprintf(dev->gd->disk_name, 32, "sbull%c", which + 'a');
set_capacity(dev->gd, nsectors*(hardsect_size/kernel_sector_size));//使用kernel_sector_size本地常量,進行核心512位元組扇區到實際使用的扇區大小轉換
add_disk(dev->gd);
sbull_minors是每個裝置所支援的次裝置號的數量,地乙個裝置名為 sbulla,第二個為sbullb.使用者空間可以新增分割槽,第二個裝置上的第三個分割槽可能是 /dev/sbullb3。
6、設定佇列支援的扇區大小
通知核心裝置所支援的扇區大小,硬體扇區大小作為乙個引數放在佇列中,而不是在gendisk中。當分配好佇列後就要馬上呼叫下面函式:
blk_queue_hardsect_size(dev->queue, hardset_size);
呼叫了上面的函式後,核心就會對我們的裝置使用設定的硬體扇區大小,所有的i/o請求毒定位在硬體扇區的開始位置,並且每個請求的大小都將是扇區大小的整數倍。記住:核心總是認為扇區大小是512位元組,因此必須將所有的扇區數進行轉換。
7、實現操作函式:
開啟裝置函式:
[cpp]view plain
copy
static int sbull_open(struct inode *inode, struct file *filp)
關閉裝置函式:
[cpp]view plain
copy
static int sbull_release(struct inode *inode, struct file *filp)
spin_unlock(&dev->lock);
return 0;
}
其他的函式也是一樣實現,和字元裝置驅動的類似。這裡就不寫了,接下來看看核心部分,對於乙個塊裝置驅動來說核心部分就是請求,幾乎所有的重心都在請求函式;
8、處理請求操作
[cpp]view plain
copy
dev->queue = blk_queue_init(&sbull_request, &dev->lock);
static void sbull_request(request_queue_t *q)
//sbull_transfer()函式是真正的處理塊裝置請求函式
sbull_transfer(dev, req->sector, req->current_nr_sectors, req->buffer, rq_data_dir(req));
end_request(req, 1);
} }
void end_request(struct request* req, int succeeded);
// sector開始扇區的索引號,指的是512位元組的扇區,如果是2048位元組的扇區,則要sector/4再傳遞
// nsect 表示要傳遞多少個扇區; buffer 資料快取的位址指標;write 表示資料傳遞的方向,即:read/write;
static void sbull_transfer(struct sbull_dev *dev, unsigned long sector, unsigned long nsect, char *buffer, int write)
if (write)
memcpy(dev->data + offset, buffer, nbytes);
else
memcpy(buffer, dev->data + offset, nbytes);
}
Linux塊裝置驅動
塊裝置提供塊裝置提供裝置的訪問,裝置的訪問,可以隨機的以固定大小的塊傳輸資料,例如我們最為常見的磁碟裝置,當然塊裝置和字元裝置有較大差別,塊裝置有自己的驅動介面。簡單來說,核心決定乙個塊是固定的4096 位元組,當然該值可以隨著依賴檔案系統的變化而改變。塊裝置驅動採用register blkdev向...
Linux塊裝置方式的nvram驅動例項
一般可以通過字元裝置驅動的方式訪問nvram,在這裡,通過塊裝置驅動方式去驅動nvram,以了解和熟悉塊裝置驅動編寫。測試系統 fedora7 nvram總可接大小 8k x 64頁 x 8片 4 m 位元組 測試硬體 intel板卡 include include include include ...
linux驅動之塊裝置驅動
塊裝置驅動的系統架構 塊裝置註冊過程 1,註冊裝置塊驅動程式 register blkdev 2,初始化請求佇列 blk init queue 3,指明扇區的大小 blk queue logical block size dev queue,sect size 4,申請乙個gendisk結構,初始化...