下图为地址空间与内核其他部分的关联。
内核采用一种通用的地址空间方案,来建立缓存数据与其来源之间的关联。
1)内存中的页分配到每个地址空间。这些页的内容可以由用户进程或内核本身使用各式各样的方法操作。这些数据表示了缓存中的内容;
2)后备存储器structbacking_dev_info指定了填充地址空间中页的数据的来源。地址空间关联到处理器的虚拟地址空间,是由处理器在虚拟内存中管理的一个区域到设备device上对应位置之间的一个映射。
如果访问了虚拟内存中的某个位置,该位置没有关联到物理内存页,内核可根据地址空间结构来找到读取数据的来源。
为支持数据传输,每个地址空间都提供了一组操作,以容许地址空间所涉及双方面的交互。
地址空间是内核中最关键的数据结构之一,对该数据结构的管理,已经演变为内核面对的最关键的问题之一。页缓存的任务在于,获得一些物理内存页,以加速在块设备上按页为单位执行的操作。
内核使用了基数树来管理与一个地址空间相关的所有页,以便尽可能降低开销。对于基数树的理解在这里就不分析了,后面有空的时候再做分析。
地址空间操作
- struct address_space_operations {
-
-
- int (*writepage)(struct page *page, struct writeback_control *wbc);
-
- int (*readpage)(struct file *, struct page *);
-
- void (*sync_page)(struct page *);
-
-
- int (*writepages)(struct address_space *, struct writeback_control *);
-
-
- int (*set_page_dirty)(struct page *page);
-
- int (*readpages)(struct file *filp, struct address_space *mapping,
- struct list_head *pages, unsigned nr_pages);
-
- int (*write_begin)(struct file *, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata);
- int (*write_end)(struct file *, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *page, void *fsdata);
-
-
- sector_t (*bmap)(struct address_space *, sector_t);
- void (*invalidatepage) (struct page *, unsigned long);
- int (*releasepage) (struct page *, gfp_t);
- ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs);
- int (*get_xip_mem)(struct address_space *, pgoff_t, int,
- void **, unsigned long *);
-
- int (*migratepage) (struct address_space *,
- struct page *, struct page *);
- int (*launder_page) (struct page *);
- int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
- unsigned long);
- int (*error_remove_page)(struct address_space *, struct page *);
- };
|