10 | 页中断:fork、mmap背后的保护神
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了操作系统内存管理中的重要机制——页中断,包括写保护中断和缺页中断。通过讲解fork的原理,介绍了写时复制机制和写保护中断的作用。文章还提到了mmap的功能和execve系统调用的作用。通过对页中断的讲解,读者能够了解到页中断的类型及其在内存管理中的重要性。在execve的执行步骤中,内核为可执行程序创建一个vma结构体实例,然后将它的vm_file属性设成待加载执行的文件,建立起了内存区域和文件的映射关系。在mmap的功能分析中,文章详细介绍了私有匿名映射、私有文件映射、共享文件映射和共享匿名映射的原理和实现方式。总的来说,本文通过深入的技术分析,帮助读者全面了解了页中断在内存管理中的重要作用,以及execve和mmap等系统调用的原理和实现机制。
《编程高手必学的内存知识》,新⼈⾸单¥59
全部留言(11)
- 最新
- 精选
- 🐮老师,建议对思考题进行分析下,验证我们分析过程; 父进程使用mmap申请私有匿名内存后,再使用fork创建子进程,这块内存会被子进程共享,同时系统会将这块内存设置为只读,当子进程使用sprintf去写数据时,会触发写时复制机制,拷贝一份内存区域,也就是说创建子进程后父子进程写的数据都不可见,他们都是操作自己特有内存空间;除非是在创建子进程前写入的数据,父子进程才可见;
作者回复: very good~
2021-11-205 - 小时候可鲜啦1、吊打面试官中,对于全局变量,映射方式应该是可读可写(而不是只读)吧。 2、对于共享库的映射,在第三课中将其归类到了私有文件映射。我觉得对于只读部分是不是应该归属于共享文件映射,而可读可写的部分才归属于私有文件映射。
作者回复: 不是这个意思哈。首先,共享库是被私有映射的,一开始设置为可读是为了当有进程对它进行写操作的时候可以触发页中断。页中断里会做写时复制。这是为了保证只有一个进程使用这个共享库时也不会更改全局变量的值。不管哪个进程去改写全局变量,操作系统都会弄一个副本给他,让他一边玩去。操作系统那里必须维护一份完全干净的版本。你先理解了这个机制,这两个问题,应该都能明白了,你再想想?
2021-12-112 - qinsi参考资料里的《Linux 内核设计与实现》似乎还是旧版的,新版(第三版)里已经提到了page cache从hash改为radix tree的理由,比如hash的冲突解决使用了链表,对于不存在的key需要遍历完整个链表才能知道不存在;又比如radix tree(又名压缩前缀树)可以压缩存储相同前缀的key,比hash更节省空间。
作者回复: very good~
2021-11-162 - Geek_347b1f作者能不能讲一下java零拷贝和直接内存用mmap怎么实现的
作者回复: DirectBuffer和FileChannel这里对吧?好,我先记下来,也许后面的答疑课程里可以写一下这个主题。
2021-12-031 - Samaritan.老师,请问一下,由于fork复制了父进程的task_struct,那么子进程就可以读取到父进程所有的信息了吧?这样是安全的吗?
作者回复: task_struct是内核态才能访问的。在内核态里只能执行linux kernel代码。而kernel代码是值得信任的。
2021-11-242 - linker思考题:后执行的进程应该会发生crash
作者回复: 哈哈,那你实验过没有?和你的猜想是否相符?
2021-11-17 - 费城的二鹏老师,私有文件映射,多个进程加载同一个文件,其中一个进程进行写入时会发生写时复制。那么,其它进程能否感知到这个文件的变化?
作者回复: 不能。主要是不需要。我写的时候,系统给我一个副本让我自己一边玩去了。别人不关心我拿走的副本是怎么样的,我也不关心除了我自己的副本之外的其他人是怎么处理的了。
2021-11-16 - 费城的二鹏吊打面试官中,共享库加载时设置为只读,代码段与全局变量都是只读的,在写入是会进行复制。系统如何保护代码段不会被写入的?这两种内容的只读标记是是相同的吗?
作者回复: 是一样的。代码段是用来执行的,运行时不允许修改。这个结论我们在第8节就介绍了,这是因为运行时修改代码段会带来安全风险,我们要避免这么做。再细一点说,编译型的语言就是这么规定的,编译器绝对不能产生运行时修改代码段的代码。
2021-11-162 - 大鑫仔Yeah作者能不能后续讲解下非自动管理内存的语言,比如 Swift
作者回复: 这就是引用计数嘛。我会在19,20节稍微提一下。
2021-11-15 - 郑童文你好老师, 从这一课中所学的内容来看,似乎mmap在分配内存时只是分配了虚拟内存,要等到进程访问这块虚拟内存时 才会被映射到物理内存页, 那既然内存分配都只是分配虚拟内存,虚拟内存非常大,我们为什么还需要考虑虚拟内存的内部碎片和外部碎片的问题呢?虚拟内存那么大浪费一些无所谓啊? 还请教老师一个关于伙伴系统的问题: 操作系统的教材上说伙伴系统被用于分配连续的物理页。我有些不明白我们为什么需要策略来管理物理内存的分配呢? 在我的理解中,物理内存应该是已经被划分成一页一页的了,当虚拟内存被分配以后,将虚拟内存直接映射到空闲的物理页就可以了,进程使用的是虚拟内存地址,它只需要连续的虚拟内存,而连续的虚拟内存完全可以映射到不连续的物理页啊?我们只需要记录哪些物理页已经被映射, 哪些物理页是未被映射的,这些物理页连不连续无所谓啊? 在需要物理页的时候找一个空闲的页来映射就可以了啊? 谢谢!2021-12-0813