当前位置: 首页 > news >正文

国外做情趣用品比较有名的网站/视频号视频下载助手app

国外做情趣用品比较有名的网站,视频号视频下载助手app,怎么网站设计,网站设计建设价格文章目录mmap的原理用户态缺页异常总结mmap的原理 每一个进程都有一个列表vm_area_struct,指向虚拟地址空间的不同内存块,这个变量的名字叫mmap。 struct mm_struct {struct vm_area_struct *mmap; /* list of VMAs */ ...... }struct vm_area_struct…

文章目录

    • mmap的原理
    • 用户态缺页异常
    • 总结

mmap的原理

每一个进程都有一个列表vm_area_struct,指向虚拟地址空间的不同内存块,这个变量的名字叫mmap。

struct mm_struct {struct vm_area_struct *mmap;		/* list of VMAs */
......
}struct vm_area_struct {/** For areas with an address space and backing store,* linkage into the address_space->i_mmap interval tree.*/struct {struct rb_node rb;unsigned long rb_subtree_last;} shared;/** A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma* list, after a COW of one of the file pages.	A MAP_SHARED vma* can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack* or brk vma (with NULL file) can only be in an anon_vma list.*/struct list_head anon_vma_chain; /* Serialized by mmap_sem &* page_table_lock */struct anon_vma *anon_vma;	/* Serialized by page_table_lock *//* Function pointers to deal with this struct. */const struct vm_operations_struct *vm_ops;/* Information about our backing store: */unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZEunits */struct file * vm_file;		/* File we map to (can be NULL). */void * vm_private_data;		/* was vm_pte (shared mem) */

内存映射往往不仅仅是物理内存和虚拟内存之间的映射,还包括将文件中的内容映射到虚拟内存空间。

这个时候,访问内存空间就能够访问到文件里面的数据。仅有物理内存和虚拟内容的映射,是一种特殊的情况。
在这里插入图片描述
要申请小内存,用brk函数,如果申请一大块内存,就要用mmap。对于堆的申请来讲,mmap是映射内存空间到物理内存。

如果一个进程想映射一个文件到自己的虚拟空间,也需要调用mmap系统调用,这个时候mmap是映射内存空间到物理内存,再到文件,mmap是系统调用核心,下面看下mmap这个系统调用

SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, off)
{
......error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
......
}SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, pgoff)
{struct file *file = NULL;
......file = fget(fd);
......retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);return retval;
}

如果要映射到文件,fd会传进来一个文件描述符,并且mmap_pgoff里面通过fget函数,根据文件描述符获得 struct file, struct file表示打开一个文件。

接下来调用链是vm_mmap_pgoff->do_mmap_pgoff->do_mmap,主要干了两件事情

  • 调用get_unmapped_area找到一个没有映射的区域
  • 调用mmap_region映射这个区域

get_unmapped_area函数如下

unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,unsigned long pgoff, unsigned long flags)
{unsigned long (*get_area)(struct file *, unsigned long,unsigned long, unsigned long, unsigned long);
......get_area = current->mm->get_unmapped_area;if (file) {if (file->f_op->get_unmapped_area)get_area = file->f_op->get_unmapped_area;} 
......
}

这里面如果是匿名映射,则调用mm_struct的get_unmapped_area函数,这个函数其实是arch_get_unmapped_area,会调用find_vma_prev,表示虚拟内存区域的vm_area_struct红黑树上找到相应的位置。之所以叫prev,是说这个时候,虚拟内存区域还没有建立,找到前一个vm_area_struct。

如果不是匿名映射,是映射到一个文件,在Linux里面,每个打开的文件都有一个struct file结构,里面有一个file_operations,用来表示和这个文件相关的操作。如果是我们熟悉的ext4文件系统,调用的是thp_get_unmapped_area。最终调用还是mm_struct里面的get_unmapped_area函数。

const struct file_operations ext4_file_operations = {
.......mmap           = ext4_file_mmap.get_unmapped_area = thp_get_unmapped_area,
};unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,loff_t off, unsigned long flags, unsigned long size)
{unsigned long addr;loff_t off_end = off + len;loff_t off_align = round_up(off, size);unsigned long len_pad;len_pad = len + size;
......addr = current->mm->get_unmapped_area(filp, 0, len_pad,off >> PAGE_SHIFT, flags);addr += (off - addr) & (size - 1);return addr;
}

mmap_region是如何映射这个虚拟内存区域。

unsigned long mmap_region(struct file *file, unsigned long addr,unsigned long len, vm_flags_t vm_flags, unsigned long pgoff,struct list_head *uf)
{struct mm_struct *mm = current->mm;struct vm_area_struct *vma, *prev;struct rb_node **rb_link, *rb_parent;/** Can we just expand an old mapping?*/vma = vma_merge(mm, prev, addr, addr + len, vm_flags,NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX);if (vma)goto out;/** Determine the object being mapped and call the appropriate* specific mapper. the address has already been validated, but* not unmapped, but the maps are removed from the list.*/vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);if (!vma) {error = -ENOMEM;goto unacct_error;}vma->vm_mm = mm;vma->vm_start = addr;vma->vm_end = addr + len;vma->vm_flags = vm_flags;vma->vm_page_prot = vm_get_page_prot(vm_flags);vma->vm_pgoff = pgoff;INIT_LIST_HEAD(&vma->anon_vma_chain);if (file) {vma->vm_file = get_file(file);error = call_mmap(file, vma);addr = vma->vm_start;vm_flags = vma->vm_flags;} 
......vma_link(mm, vma, prev, rb_link, rb_parent);return addr;
.....

刚找到了虚拟内存区域的前一个 vm_area_struct,是否能够基于它进行扩展,也即调用vma_merge,和前一个vm_area_struct合并到一起。

如果不能,就需要调用 kmem_cache_zalloc,在 Slub 里面创建一个新的 vm_area_struct 对象,设置起始和结束位置,将它加入队列

如果是映射到文件,则设置 vm_file 为目标文件,调用 call_mmap。其实就是调用 file_operations 的 mmap 函数。对于 ext4 文件系统,调用的是 ext4_file_mmap。从这个函数的参数可以看出,这一刻文件和内存开始发生关系了。这里我们将 vm_area_struct 的内存操作设置为文件系统操作,也就是说,读写内存其实就是读写文件系统。

static inline int call_mmap(struct file *file, struct vm_area_struct *vma)
{return file->f_op->mmap(file, vma);
}static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
{
......vma->vm_ops = &ext4_file_vm_ops;
......
}

我们再回到 mmap_region 函数。最终,vma_link 函数将新创建的 vm_area_struct 挂在了 mm_struct 里面的红黑树上。

这个时候,从内存到文件的映射关系,至少要在逻辑层面建立起来。那从文件到内存的映射关系呢?vma_link 还做了另外一件事情,就是 __vma_link_file。这个东西要用于建立这层映射关系。

对于打开的文件,会有一个结构 struct file 来表示。它有个成员指向 struct address_space 结构,这里面有棵变量名为 i_mmap 的红黑树,vm_area_struct 就挂在这棵树上。

struct address_space {struct inode		*host;		/* owner: inode, block_device */
......struct rb_root		i_mmap;		/* tree of private and shared mappings */
......const struct address_space_operations *a_ops;	/* methods */
......
}static void __vma_link_file(struct vm_area_struct *vma)
{struct file *file;file = vma->vm_file;if (file) {struct address_space *mapping = file->f_mapping;vma_interval_tree_insert(vma, &mapping->i_mmap);}

到这里,内存映射的内容要告一段落了。你可能会困惑,好像还没和物理内存发生任何关系,还是在虚拟内存里面折腾呀?

这个时候,内存管理并不直接分配物理内存,因为物理内存相对于虚拟空间地址太宝贵了,只有等你真正用的那一刻才会开始分配。

用户态缺页异常

为了加快映射速度,不需要每次都从虚拟地址到物理地址转换都走一遍页表。
在这里插入图片描述
页表一般都很大,只能存放在内存中,操作系统每次访问内存都要折腾两步,先通过查页表得到物理地址,然后访问该物理地址读取指令、数据。

总结

  • 用户态内存映射函数mmap,包括用它来做匿名映射和文件映射
  • 用户态的页表结构,存储位置在mm_struct中
  • 用户态访问没有映射的内存会引发缺页异常,分配物理页面、补齐页表。
    • 如果是匿名映射则分配物理内存;
    • 如果是swap ,则将swap文件读入;
    • 如果是文件映射,则将文件读入。

在这里插入图片描述

http://www.jmfq.cn/news/4828987.html

相关文章:

  • dw怎么用div css做网站/免费二级域名分发
  • 合肥网站建设开发/国外外链平台
  • 网站设计制作要交印花税/优化疫情防控措施
  • 网站开发人才需求/三亚百度推广公司电话
  • 奉化区建设局网站/西安seo代理
  • b站短链接生成/新媒体代运营
  • 建e网室内设计网网址/北京网站优化推广方案
  • 东莞厚街镇疫情最新消息/seo外包杭州
  • 泉州做网站开发公司/私人网站服务器
  • 商城式网站具备哪些功能吗/重庆网站快速排名提升
  • 国内永久免费crm系统网站推荐/百度账号购买网站
  • 建网站内容/如何快速网络推广
  • wordpress建站教程贴吧/网络销售培训学校
  • 免费搭建商城网站/网络广告营销典型案例
  • 新疆建设兵团农一师检察院网站/陕西seo主管
  • 手机百度 网站提交/搜索引擎seo关键词优化
  • 购物网站建设与实现/b站推广入口2023
  • c2c网站的类型/sem是什么岗位
  • 做本地网站需要什么资质/本周时事新闻概要10条
  • 上海平台网站建设报/域名交易域名出售
  • 手机网站栏目结构图/太极seo
  • wordpress手机网站怎么做/河南seo推广
  • 南城区做网站/精准引流推广
  • wordpress 有图片的文章/百度推广优化师
  • 洛杉矶网站建设/网络营销案例分析报告
  • 网站做cpa/市场营销考试题目及答案2022
  • 浏览网站 需要我安装wordpress/北京百度推广代理公司
  • 建设网站必备条件/销售网站有哪些
  • 网站说建设中/厦门网站推广公司哪家好
  • 资阳房产网站建设/网站建设公司哪家好?该如何选择