Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1851334
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2388
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(184)

文章存档

2021年(26)

2020年(56)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-09-21 12:33:15

文件的内存映射可以认为是两个不同的地址空间之间的映射,以简化程序员的工作。一个地址空间是用户进程的虚拟地址空间,另一个是文件系统所在的地址空间。


在内核创建一个映射时,必须建立两个地址空间之间的关联,以支持二者以读写请求的形式通信。vm_operations_struct结构即用于完成此项工作,它提供了一个操作,读取已经映射到虚拟地址空间,但是内容尚未进入物理内存的页。
但是该结构不了解映射类型,或性质的相关信息,只能算是一个通用接口,具体实现还需要内核描述打开文件的file结构体当中的成员变量address_space结构体来详细说明数据源。

点击(此处)折叠或打开

  1. struct address_space {
  2.     struct inode        *host;        /* owner: inode, block_device */
  3.     struct radix_tree_root    page_tree;    /* radix tree of all pages */
  4.     spinlock_t        tree_lock;    /* and lock protecting it */
  5.     atomic_t        i_mmap_writable;/* count VM_SHARED mappings */
  6.     struct rb_root_cached    i_mmap;        /* tree of private and shared mappings */
  7.     struct rw_semaphore    i_mmap_rwsem;    /* protect tree, count, list */
  8.     /* Protected by tree_lock together with the radix tree */
  9.     unsigned long        nrpages;    /* number of total pages */
  10.     /* number of shadow or DAX exceptional entries */
  11.     unsigned long        nrexceptional;
  12.     pgoff_t            writeback_index;/* writeback starts here */
  13.     const struct address_space_operations *a_ops;    /* methods */
  14.     unsigned long        flags;        /* error bits */
  15.     spinlock_t        private_lock;    /* for use by the address_space */
  16.     gfp_t            gfp_mask;    /* implicit gfp mask for allocations */
  17.     struct list_head    private_list;    /* for use by the address_space */
  18.     void            *private_data;    /* ditto */
  19.     errseq_t        wb_err;
  20. } __attribute__((aligned(sizeof(long)))) __randomize_layout;

  21. struct address_space_operations {
  22.     int (*writepage)(struct page *page, struct writeback_control *wbc);
  23.     int (*readpage)(struct file *, struct page *);

  24.     /* Write back some dirty pages from this mapping. */
  25.     int (*writepages)(struct address_space *, struct writeback_control *);

  26.     /* Set a page dirty. Return true if this dirtied it */
  27.     int (*set_page_dirty)(struct page *page);

  28.     int (*readpages)(struct file *filp, struct address_space *mapping,
  29.             struct list_head *pages, unsigned nr_pages);

  30.     int (*write_begin)(struct file *, struct address_space *mapping,
  31.                 loff_t pos, unsigned len, unsigned flags,
  32.                 struct page **pagep, void **fsdata);
  33.     int (*write_end)(struct file *, struct address_space *mapping,
  34.                 loff_t pos, unsigned len, unsigned copied,
  35.                 struct page *page, void *fsdata);

  36.     /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
  37.     sector_t (*bmap)(struct address_space *, sector_t);
  38.     void (*invalidatepage) (struct page *, unsigned int, unsigned int);
  39.     int (*releasepage) (struct page *, gfp_t);
  40.     void (*freepage)(struct page *);
  41.     ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
  42.     /*
  43.      * migrate the contents of a page to the specified target. If
  44.      * migrate_mode is MIGRATE_ASYNC, it must not block.
  45.      */
  46.     int (*migratepage) (struct address_space *,
  47.             struct page *, struct page *, enum migrate_mode);
  48.     bool (*isolate_page)(struct page *, isolate_mode_t);
  49.     void (*putback_page)(struct page *);
  50.     int (*launder_page) (struct page *);
  51.     int (*is_partially_uptodate) (struct page *, unsigned long,
  52.                     unsigned long);
  53.     void (*is_dirty_writeback) (struct page *, bool *, bool *);
  54.     int (*error_remove_page)(struct address_space *, struct page *);

  55.     /* swapfile support */
  56.     int (*swap_activate)(struct swap_info_struct *sis, struct file *file,
  57.                 sector_t *span);
  58.     void (*swap_deactivate)(struct file *file);
  59. };
这样每个address_space都有一组相关操作,保存在自己的a_ops指针当中
当建立内存映射的时候,内核分配完新的vm_area_struct实例之后,就会用特定于文件的函数file->f_op->mmap创建映射,vm_area_struct当中的vm_operations_struct和address_space之间就会建立联系(vm_operations_struct 的指针最后指向的是generic_file_vm_ops,里面的fault函数指向filemap_fault,这个函数就会调用上

点击(此处)折叠或打开

  1. address_space_operations当中的readpage函数)
  2. const struct vm_operations_struct generic_file_vm_ops = {
  3.     .fault        = filemap_fault,
  4.     .map_pages    = filemap_map_pages,
  5.     .page_mkwrite    = filemap_page_mkwrite,
  6. };
  7. int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
  8. {
  9.     struct address_space *mapping = file->f_mapping;

  10.     if (!mapping->a_ops->readpage)
  11.         return -ENOEXEC;
  12.     file_accessed(file);
  13.     vma->vm_ops = &generic_file_vm_ops;
  14.     return 0;
  15. }


阅读(7626) | 评论(0) | 转发(1) |
0

上一篇:Linux内核锁机制

下一篇:c++中的cast碎碎念

给主人留下些什么吧!~~