最新消息: 关于Git&GitHub 版本控制你了解多少?
您现在的位置是:群英 > 开发技术 > 编程语言 >
Linux如何实现内存映射文件?
IT168发表于 2020-11-26 11:26 次浏览
由于项目需要,所以学习了一下Linux下内存映射文件的用法,在这里共享一下自己的收获,希望大家提出宝贵意见,进行交流。

在内核创建一个映射时,必须建立两个地址空间之间的关联,以支持二者以读写请求的形式通信。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.  
  22. struct address_space_operations {
  23.     int (*writepage)(struct page *page, struct writeback_control *wbc);
  24.     int (*readpage)(struct file *, struct page *);
  25.  
  26.     /* Write back some dirty pages from this mapping. */
  27.     int (*writepages)(struct address_space *, struct writeback_control *);
  28.  
  29.     /* Set a page dirty. Return true if this dirtied it */
  30.     int (*set_page_dirty)(struct page *page);
  31.  
  32.     int (*readpages)(struct file *filp, struct address_space *mapping,
  33.             struct list_head *pages, unsigned nr_pages);
  34.  
  35.     int (*write_begin)(struct file *, struct address_space *mapping,
  36.                 loff_t pos, unsigned len, unsigned flags,
  37.                 struct page **pagep, void **fsdata);
  38.     int (*write_end)(struct file *, struct address_space *mapping,
  39.                 loff_t pos, unsigned len, unsigned copied,
  40.                 struct page *page, void *fsdata);
  41.  
  42.     /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
  43.     sector_t (*bmap)(struct address_space *, sector_t);
  44.     void (*invalidatepage) (struct page *, unsigned int, unsigned int);
  45.     int (*releasepage) (struct page *, gfp_t);
  46.     void (*freepage)(struct page *);
  47.     ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
  48.     /*
  49.      * migrate the contents of a page to the specified target. If
  50.      * migrate_mode is MIGRATE_ASYNC, it must not block.
  51.      */
  52.     int (*migratepage) (struct address_space *,
  53.             struct page *, struct page *, enum migrate_mode);
  54.     bool (*isolate_page)(struct page *, isolate_mode_t);
  55.     void (*putback_page)(struct page *);
  56.     int (*launder_page) (struct page *);
  57.     int (*is_partially_uptodate) (struct page *, unsigned long,
  58.                     unsigned long);
  59.     void (*is_dirty_writeback) (struct page *, bool *, bool *);
  60.     int (*error_remove_page)(struct address_space *, struct page *);
  61.  
  62.     /* swapfile support */
  63.     int (*swap_activate)(struct swap_info_struct *sis, struct file *file,
  64.                 sector_t *span);
  65.     void (*swap_deactivate)(struct file *file);
  66. };
这样每个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.  
  11.     if (!mapping->a_ops->readpage)
  12.         return -ENOEXEC;
  13.     file_accessed(file);
  14.     vma->vm_ops = &generic_file_vm_ops;
  15.     return 0;
  16. }
  17.  

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
相关信息推荐
2020-09-08 17:49:49 关键词:linux常用命令
摘要:管理服务器时我们经常需要写一些监测脚本,然后在出问题的时候通过邮件来通知,接下来我们为大家介绍用最简单的方式来实现Linux mail命令的使用 linux mail 命令参数: 使用mail发邮件..