linux塊裝置驅動之例項

2021-09-08 19:48:17 字數 3491 閱讀 7289

整體過程:

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結構,初始化...