我知道程序首次启动时,由于代码不在内存中,因此在开始时会出现大量页面错误,因此需要从磁盘加载代码.
程序退出后会发生什么?二进制文件是否留在内存中?该程序的后续调用是否会发现代码已经在内存中,因此没有页面错误(假设两者之间没有任何运行,并且页面填充到磁盘)?
在我的Linux机器上运行一些实验似乎没有答案.我一遍又一遍地运行一些程序,每次都观察到相同数量的页面错误.这是一个相对安静的机器,所以我怀疑东西是在调用之间被调出来的.那么,为什么呢?为什么可执行文件不能保留在内存中?
解决方法:
这里有两件事需要考虑:
1)可执行文件的内容可能保存在OS缓存(磁盘缓存)中.虽然该数据仍在操作系统缓存中,但该数据的每次读取都将到达缓存,操作系统将遵循该请求,而无需从磁盘重新读取该文件
2)当进程退出时,操作系统取消映射到文件的每个内存页面,释放任何内存(通常,释放进程分配的每个资源,包括其他资源,如套接字等).严格来说,物理内存可能已归零,但并不十分必需(仍然,操作系统的安全级别可能需要将不再使用的页面归零 – 可能是Windows NT,2K,XP等,请执行此操作 – 请参阅此Does Windows clear memory pages?).对同一个可执行文件的另一个调用将创建一个全新的进程,它将在内存中映射相同的文件,但是对这些页面的第一次访问仍然会触发页面错误,因为最终它是一个新进程,一个不同的内存映射.所以,是的,页面错误发生,但与第一个相比,它们相同的可执行文件的第二个实例便宜得多.
当然,这仅仅是可执行文件的只读部分(包含代码和只读数据的段/模块).
可以考虑另一种情况:分叉.在这种情况下,每个页面都标记为写时复制.当在每个存储器页面上发生第一次写入时,OS内存管理器触发并拦截硬件异常.操作系统确定是否允许写入相关页面(例如:如果它是堆栈,堆或任何可写页面),如果是,则在允许进程修改页面之前分配内存并复制原始内容 – 为了保留其他过程中的原始数据.是的,还有另一种情况 – 共享内存,其中确切的物理内存映射到两个或多个进程.在这种情况下,写时复制标志当然不在存储页面上设置.
希望这能澄清内存页面的内容.
标签:memory-management,linux,virtual-memory,paging
来源: https://codeday.me/bug/20190702/1360634.html