歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux I/O Block--塊設備的表示

Linux I/O Block--塊設備的表示

日期:2017/3/1 10:05:53   编辑:Linux編程

塊設備的特點是其平均訪問時間較長,因此為了提高塊設備的訪問效率,Linux內核用了很多的筆墨來設計和塊設備相關的部分,這樣一來,從代碼的角度來看,訪問一個文件的過程變得尤其的漫長……整個路徑包含的過程基本可以概括為虛擬文件系統-->塊設備實際文件系統-->通用塊層-->I/O scheduler-->塊設備驅動程序。為了提高塊設備的訪問效率,內核主要是在兩個方面下功夫:

1.引入緩存,當用戶空間要訪問文件時,內核不可能每次都去訪問塊設備,內核會將塊設備的內容讀取到內存中,以便下次訪問時可以直接在內存中找到相應的內容,這其中又涉及到了預讀等相關的問題,當然這不是現在關注的重點……

2.對於I/O請求的重排列,I/O請求並不會立即被響應,而是會放在一個隊列裡進行一段延遲,以期能夠和後來的I/O請求進行合並或者進行排序。因為像磁盤這樣的塊設備,其耗時主要是因為磁頭的定位,因此內核會盡量保證磁頭只往一個方向移動,而不是來回移動(可以和電梯的運作進行對比),簡而言之,就是將存儲介質上相鄰的數據請求安排在一起,對於I/O請求的處理主要包括合並和排序,具體如何處理,由I/O scheduler決定。

首先,我們先來了解一個塊設備是如何表示的。描述塊設備的數據結構有兩個,一個是struct block_device,用來描述一個塊設備或者塊設備的一個分區;另一個是struct gendisk,用來描述整個塊設備的特性。對於一個包含多個分區的塊設備,struct block_device結構有多個,而struct gendisk結構永遠只有一個。

struct block_device {
dev_t bd_dev; /* not a kdev_t - it's a search key */
struct inode * bd_inode; /* will die */
struct super_block * bd_super;
int bd_openers;
struct mutex bd_mutex; /* open/close mutex */
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
#ifdef CONFIG_SYSFS
struct list_head bd_holder_list;
#endif
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
/* number of times partitions within this device have been opened. */
unsigned bd_part_count;
int bd_invalidated;
struct gendisk * bd_disk;
struct list_head bd_list;
/*
* Private data. You must have bd_claim'ed the block_device
* to use this. NOTE: bd_claim allows an owner to claim
* the same device multiple times, the owner must take special
* care to not mess up bd_private for that case.
*/
unsigned long bd_private;

/* The counter of freeze processes */
int bd_fsfreeze_count;
/* Mutex for freeze */
struct mutex bd_fsfreeze_mutex;
};

bd_dev:該設備(分區)的設備號

bd_inode:指向該設備文件的inode

bd_openers:一個引用計數,記錄了該塊設備打開的次數,或者說有多少個進程打開了該設備

bd_contains:如果該block_device描述的是一個分區,則該變量指向描述主塊設備的block_device,反之,其指向本身

bd_part:如果該block_device描述的是一個分區,則該變量指向分區的信息

bd_part_count:如果是分區,該變量記錄了分區被打開的次數,在進行分區的重新掃描前,要保證該計數值為0

bd_disk:指向描述整個設備的gendisk結構

struct gendisk {
/* major, first_minor and minors are input parameters only,
* don't use directly. Use disk_devt() and disk_max_parts().
*/
int major; /* major number of driver */
int first_minor;
int minors; /* maximum number of minors, =1 for
* disks that can't be partitioned. */

char disk_name[DISK_NAME_LEN]; /* name of major driver */
char *(*devnode)(struct gendisk *gd, mode_t *mode);
/* Array of pointers to partitions indexed by partno.
* Protected with matching bdev lock but stat and other
* non-critical accesses use RCU. Always access through
* helpers.
*/
struct disk_part_tbl *part_tbl;
struct hd_struct part0;

const struct block_device_operations *fops;
struct request_queue *queue;
void *private_data;

int flags;
struct device *driverfs_dev; // FIXME: remove
struct kobject *slave_dir;

struct timer_rand_state *random;

atomic_t sync_io; /* RAID */
struct work_struct async_notify;
#ifdef CONFIG_BLK_DEV_INTEGRITY
struct blk_integrity *integrity;
#endif
int node_id;
};

major:塊設備的主設備號

first_minor:起始次設備號

minors:描述了該塊設備有多少個次設備號,或者說有多少個分區,如果minors為1,則表示該塊設備沒有分區

part_tbl:整個塊設備的分區信息都包含在裡面,其核心結構是一個struct hd_struct的指針數組,每一項都指向一個描述分區的hd_struct結構

fops:指向特定於設備的底層操作函數集

queue:塊設備的請求隊列,所有針對該設備的請求都會放入該請求隊列中,經過I/O scheduler的處理再進行提交

Copyright © Linux教程網 All Rights Reserved