一直有個疑惑,文件是放在磁盤中的,可是操做文件倒是在內存中,這二者是怎麼關聯的呢,雖然至今尚未找到更詳細的答案,可是對linux底層數據結構進行梳理後,發現了其中的一些線索,與你們分享。node
在編程語言裏面,打開一個文件通常的操做須要創建一個文件描述符fd:linux
int fd = open(...);
fd是一個int型,實際上是一個數組的下標,前三個0,1,2被輸入,輸出,錯誤佔用了算法
新建新的fd的時候,首先分配一個file對象,而後放到數組裏面,返回這個數組的下標,就是fd了編程
struct file{ file_operations *fop; path *f_path; loff_t f_pos; }
file結構中有一個f_path指針,指向path結構,其中f_pos還保存了文件的位置數組
struct path{ dentry *dentry ... }
path鏈接着一個dentry結構數據結構
struct dentry{ inode *d_inode; ... }
dentry結構鏈接着inode結構app
struct inode{ address_space *i_mapping; address_space *i_data; }
inode結構鏈接着address_space結構異步
struct address_space{ radix_tree_root page_tree; }
page_tree是一個基樹,節點中存放着page節點,page就是系統中的頁,因此address_space鏈接着page結構。編程語言
struct page{ void *private; }
private指向buffer_headspa
struct buffer_head{ sector_t block_nr; // 邏輯塊號 block_device *b_bdev; // 磁盤設備號 }
block_nr存放的數據的邏輯塊號,經過邏輯塊號,就能夠和磁盤關聯起來了。
struct bio{ bio_vec *bi_io_vec; // 鏈表 sector_t bi_sector; // 磁盤上相關的扇區 struct block_device *bi_bdev; // 相關的塊設備 }
一個bio鏈接着n個bio_vec結構,用於表示page中內容的位置
struct bio_vec{ page *bv_page; // 指向包含的頁 int bv_len; // 長度 int bv_offset; //頁中的偏移 }
struct task_struct{ struct bio *bio_list; // 指向bio的鏈表頭 }
file中的file_operations是一個操做結構,裏面包含對文件的read,write等操做,全部對文件的操做,都會轉移到該文件file->f_op->read/write等操做。
linux2.6以後,使用了bio的結構來描述IO操做,因爲效率的緣由,因此buffer_head使用場景變少了,用bio結構描述一個讀/寫操做,而後使用IO調度算法進行調度。
經過以上結構體,能夠得出一條線索:
fd->file->path->dentry->inode->address_space->page->buffer_head->磁盤塊號
或者
task_struct->bio->磁盤塊號
磁盤的IO操做都是異步的,會經過特定的條件觸發把內容從內存刷新到磁盤。