一直有个疑惑,文件是放在磁盘中的,可是操做文件倒是在内存中,这二者是怎么关联的呢,虽然至今尚未找到更详细的答案,可是对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操做都是异步的,会经过特定的条件触发把内容从内存刷新到磁盘。