1 塊設備的概述 linux支持的兩種重要的設備類型分別是字元設備和塊設備,塊設備可以隨機地以固定大小的塊傳送數據。與字元設備相比,塊設備有以下幾個特殊之處: (1)塊設備可以從數據的任何位置進行訪問 (2)塊數據總是以固定長度進行傳輸,即便請求的這是一個位元組 (3)對塊設備的訪問有大量的緩存。當進 ...
1 塊設備的概述
linux支持的兩種重要的設備類型分別是字元設備和塊設備,塊設備可以隨機地以固定大小的塊傳送數據。與字元設備相比,塊設備有以下幾個特殊之處:
(1)塊設備可以從數據的任何位置進行訪問
(2)塊數據總是以固定長度進行傳輸,即便請求的這是一個位元組
(3)對塊設備的訪問有大量的緩存。當進行讀時,如果已經緩存了,就直接使用緩存中的數據,而不再讀設備,對於寫也通過緩存來進行延遲處理。
在塊系統中,數據塊指的是固定大小的數據,該固定大小由內核規定,通常是4096個位元組。與數據塊對應的是扇區,它是由設備硬體所決定的一個塊,其大小取決於硬體,常見的硬體的扇區大多都是512個位元組。數據塊的大小都是扇區大小的整數倍。
2 對比之前的字元設備驅動程式的區別;
app:open read write
塊: drv_open drv_read drv_write
硬體
如果按照操作字元設備的那套方法來操作塊設備,效率低,且容易損壞儀器。
塊設備的框架:
app: open,read,write "1.txt"
--------------------------------------------- 文件的讀寫
文件系統: vfat, ext2, ext3, yaffs2, jffs2 (把文件的讀寫轉換為扇區的讀寫)
-----------------ll_rw_block----------------- 扇區的讀寫
1. 把"讀寫"放入隊列
2. 調用隊列的處理函數(優化/調順序/合併)
塊設備驅動程式
---------------------------------------------
硬體: 硬碟,flash
3 分析ll_rw_block函數
ll_rw_block
for (i = 0; i < nr; i++) {
struct buffer_head *bh = bhs[i];
submit_bh(rw, bh);
struct bio *bio; // 使用bh來構造bio (block input/output)
submit_bio(rw, bio);
// 通用的構造請求: 使用bio來構造請求(request)
generic_make_request(bio);
__generic_make_request(bio);
request_queue_t *q = bdev_get_queue(bio->bi_bdev); // 找到隊列
// 調用隊列的"構造請求函數"
ret = q->make_request_fn(q, bio);
// 預設的函數是__make_request
__make_request
// 先嘗試合併
elv_merge(q, &req, bio);
// 如果合併不成,使用bio構造請求
init_request_from_bio(req, bio);
// 把請求放入隊列
add_request(q, req);
// 執行隊列
__generic_unplug_device(q);
// 調用隊列的"處理函數"
q->request_fn(q);
4 怎麼寫塊設備驅動程式呢?
1. 分配gendisk: alloc_disk
2. 設置
2.1 分配/設置隊列: request_queue_t // 它提供讀寫能力
blk_init_queue
2.2 設置gendisk其他信息 // 它提供屬性: 比如容量
3. 註冊: add_disk
參考:drivers\block\xd.c和drivers\block\z2ram.c
--------------------------------------------------------------編輯於2017-01-13 01:03:00
1 /*參考:drivers\block\z2ram.c*/ 2 3 4 #include <linux/module.h> 5 #include <linux/errno.h> 6 #include <linux/interrupt.h> 7 #include <linux/mm.h> 8 #include <linux/fs.h> 9 #include <linux/kernel.h> 10 #include <linux/timer.h> 11 #include <linux/genhd.h> 12 #include <linux/hdreg.h> 13 #include <linux/ioport.h> 14 #include <linux/init.h> 15 #include <linux/wait.h> 16 #include <linux/blkdev.h> 17 #include <linux/blkpg.h> 18 #include <linux/delay.h> 19 #include <linux/io.h> 20 21 #include <asm/system.h> 22 #include <asm/uaccess.h> 23 #include <asm/dma.h> 24 25 26 #define RAMBLOCK_SIZE (1024*1024) 27 #define DEVICE_NAME "ramblock" 28 29 static DEFINE_SPINLOCK(ramblock_lock); 30 31 static struct gendisk *ramblock_gendisk; 32 static int major; 33 static struct request_queue *ramblock_queue; 34 static unsigned char *ramblock_buf; 35 36 static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo) 37 { 38 geo->heads = 2; 39 geo->cylinders = 32; 40 geo->sectors = RAMBLOCK_SIZE/2/32/512; 41 return 0; 42 } 43 44 45 static struct block_device_operations ramblock_fops = { 46 .owner = THIS_MODULE, 47 .getgeo = ramblock_getgeo, 48 }; 49 50 static void do_ramblock_request(request_queue_t *q) 51 { 52 struct request *req; 53 if((req = elv_next_request(q)) != NULL) 54 { 55 unsigned long offset = req->sector <<9; 56 unsigned long len = req->current_nr_sectors << 9; 57 58 if (rq_data_dir(req) == READ) 59 { 60 memcpy(req->buffer, ramblock_buf+offset, len); 61 } 62 else 63 { 64 memcpy(ramblock_buf+offset, req->buffer, len); 65 } 66 end_request(req, 1); 67 68 } 69 70 71 } 72 73 static int ramblock_init(void) 74 { 75 ramblock_gendisk = alloc_disk(16); 76 77 ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock); 78 ramblock_gendisk->queue = ramblock_queue; 79 80 81 major = register_blkdev(0, DEVICE_NAME); 82 ramblock_gendisk->major = major; 83 ramblock_gendisk->first_minor = 0; 84 ramblock_gendisk->fops = &ramblock_fops; 85 sprintf(ramblock_gendisk->disk_name, "ramblock"); 86 set_capacity(ramblock_gendisk, RAMBLOCK_SIZE / 512); 87 88 ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL); 89 add_disk(ramblock_gendisk); 90 91 92 return 0; 93 } 94 95 static void ramblock_exit(void) 96 { 97 unregister_blkdev(major, DEVICE_NAME); 98 del_gendisk(ramblock_gendisk); 99 put_disk(ramblock_gendisk); 100 blk_cleanup_queue(ramblock_queue); 101 102 kfree(ramblock_buf); 103 104 105 } 106 107 module_init(ramblock_init); 108 module_exit(ramblock_exit); 109 MODULE_LICENSE("GPL");ramblock.c
--------------------------------------------------------------編輯於2017-01-13 14:34:44