操作系统的内存管理你知道吗
brk()的作用也只是通知Linux内核哪个范围的堆内存是可用的,真正的物理内存页是在进程实际读写内存的时候才会申请,而且是由内核根据写时复制/需求加载自动完成的,应用程序感知不到这点。 |
内存管理,是操作系统的主要功能。
操作系统从启动一直到创建0号进程(idle进程),运行的大部分代码都跟内存有关。
操作系统的内存管理,大概分这么几个层次:
1.物理内存管理
物理内存是电脑上的真实内存大小,这个数据可以通过BIOS获取。
在分页之后,物理内存的管理结构是个数组,每项表示1个物理内存页,每页4096字节。
如下图:
物理内存的管理结构
在一个简单的内核demo里,物理内存页的管理结构可以只有一项:
atomic_t refs;
即,物理内存页的引用计数:计数为0表示空闲,> 0表示正在使用,具体数字表示共享这一页的进程个数。
简单的内核demo一般是不支持SMP架构的,所以自旋锁(spinlock)也就省了。
在对称多处理器(SMP)的CPU上,因为全局数据结构会被多个CPU并发访问,所以要加自旋锁。
那么,物理内存页的管理结构至少有2项:
atomic_t spinlock; atomic_t refs;
自旋锁的作用,与应用程序里的锁(mutex)差不多,只是它在获取失败之后会不断地再次获取,直到成功。
void spin_lock(atomic_t* lock) { while (spin_trylock(lock) == 0); }
这就是给自旋锁加锁的函数,while循环直到成功,不成功时就自旋在那里一直转圈,所以叫自旋锁。
它在(对称多处理器)SMP环境里用于保护共享的数据结构:当一个CPU持有自旋锁时,另一个CPU没法访问共享数据。
如果是单个CPU的环境,没必要用自旋锁,直接关闭中断就行了。
单个CPU的情况下,关了中断就可以阻止内核的并发,共享数据也就不会被踩踏了。
但多个CPU必须使用自旋锁,因为关中断只能关闭当前CPU的,没法关其他CPU的:这时需要自旋锁保护共享数据。
物理内存的管理数组,是最重要的全局共享数据。
当需要给一个进程申请内存的时候,哪个内存页是空闲的,哪个已经被使用了,全靠查看这个数组。
加自旋锁的时候一定要先关中断,因为如果在加了锁之后、关中断之前、正好有个中断来了,而在中断处理函数里再次请求加同一个锁,那就会递归死锁了。
Linux内核的关中断加锁的函数叫:spin_lock_irqsave().
Linux内核的分配物理内存页的函数叫:get_free_pages(),它可以分配1页或连续的多页内存。
如果分配多页内存的话,起始地址是要按页数对齐的。
2.虚拟内存管理
虚拟内存都是通过进程的页表管理的。
为了节省物理内存,新创建的进程是与父进程共享同一套物理内存页的。
只有新进程要写某个内存页时,才会给它复制一份新的物理内存页,然后取消该页与父进程的共享,这就是写时复制。
写时复制的过程
写时复制的过程:
1)申请一个新内存页,
2)把老内存页的内容,复制到新内存页上,
3)把新内存页的地址填入子进程的页表,
4)把老内存页的引用计数减1。
所以,新进程刚被创建出来时,它的用户空间并没有自己的物理内存页,只有当运行需要时才一点点地通过写时复制添加,以让物理内存最大限度的空闲着。
另一个让物理内存最大限度空闲着的机制,就是需求加载:
1)当mmap一个文件时,操作系统并不会直接为这个文件分配内存,并且把它的内容加载到内存里,
2)而是当进程真去读这个文件的某一部分时,才给它申请物理内存页,并且把这一部分内容从磁盘读到内存。
copy on write,load on read.
不到火烧眉毛的时候,Linux系统是不会把物理内存给进程的
3.用户态的内存函数
以上的这些机制都是OS内核里的,应用程序的代码不需要管这些。
应用程序分配内存的最底层函数,就是brk()系统调用。
brk()是一个系统调用,它的作用就是修改应用程序的数据段的结尾,从而分配或回收应用程序的堆空间。
C库里的把它封装成了sbrk()和brk()两个函数,让它使用起来更符合人们的习惯:
sbrk()用于申请内存:void* sbrk(int increment);
brk()用于回收内存:int brk(void* addr);
实际上,Linux系统只有1个brk()系统调用,它既设置进程数据段的末尾,又会把这个值返回给应用程序。
Linux内核的头文件里,brk()系统调用的处理函数sys_brk()是这么定义的,如上图。
如果想直接使用系统调用,可以使用Linux的syscall()函数,依次传入调用号和参数列表,就可以看到哪些是真实的系统调用,哪些是C库的封装。
syscall()函数的声明是:long syscall(long number, ...);
它的参数是可变的,系统调用的参数最多只有6个,因为寄存器的个数有限。
在sbrk() 和 brk()的基础上再封装,就是人们经常使用的malloc() 和 free()了。
malloc() 申请的内存是一块块的,可以不按次序释放,而不影响使用。
brk() 和 sbrk() 申请的内存必须按次序释放,因为它会修改进程的数据段结尾:
数据段结尾(brk)之外的堆空间如果被使用,就属于段错误。
所以,Linux man手册里说明了,应用程序不要用sbrk()和brk()申请和释放内存。
brk()的作用也只是通知Linux内核哪个范围的堆内存是可用的,真正的物理内存页是在进程实际读写内存的时候才会申请,而且是由内核根据写时复制/需求加载自动完成的,应用程序感知不到这点。
Linux还会把不常用的物理内存页交换到磁盘上(即swap分区),以腾出更多的内存。
所以,在内存不足时,磁盘的读写频次也会升高。
操作系统的内存管理你知道吗相关推荐
- 操作系统的内存管理机制(连续分配管理、页式、段式、段页式、快表、二级页表)
来源:https://www.bilibili.com/video/BV1YE411D7nH 操作系统的内存管理机制(连续分配管理.页式.段式.段页式.快表.二级页表) 内存被分为系统区和用户区,系统 ...
- 操作系统的内存管理方式
操作系统的内存管理方式有三种:分段式.分页式.段页式. 首先介绍分段式: 概念:将地址空间进行分段,代码段/数据段/堆/栈/参数/环境变量.根据使用一个空间的性质,在不同的分段,分配虚拟地址,有助于编 ...
- 操作系统的内存管理算法
关注.星标公众号,不错过精彩内容 转自:LiteOS物联网操作系统 本文主要介绍内存的基本概念以及操作系统的内存管理算法. 一.内存的基本概念 内存是计算机系统中除了处理器以外最重要的资源,用于存储当 ...
- OS - 浅谈操作系统的内存管理
分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 简介 内存是计算机中最重要的资源之一,通常情况下,物 ...
- linux内存管理简介,Linux操作系统的内存管理特性简介 (3)
输出的第一行(Mem:)显示出物理内存的使用情况.总和(total)列中并没有显示出被内核使用的内存,它通常将近一兆字节.已用列(used column)显示出已用内存的总和(第二行没有把缓冲算进来) ...
- linux内存管理 简介,Linux操作系统的内存管理特性简介 (4)
高速缓冲 与访问(真正的)的内存相比,磁盘[3]的读写是很慢的.另外,在相应较短的时间内多次读磁盘同样的部分也是常有的事.例如,某人也许首先阅读了一段e-mail消息,然后为了答复又将这段消息读入编辑 ...
- 深入探讨PHP中的内存管理问题
一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改 ...
- iOS中引用计数内存管理机制分析
在 iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序. 操作系统的内存管理分成堆和 ...
- linux 内存管理 Transparent HugePages 透明大页 简介
1. 介绍 从RedHat6, RedHat7, OL6, OL7 SLES11 and UEK2 kernels开始,透明大页默认是被开启的以便去改善操作系统的内存管理.透明大页与之前版本的传统意义 ...
最新文章
- 修改oracle数据库密码
- 注册表文件修改打开程序的简单示例
- 计算机硬件部分可称为裸机,上财信管PPT第3章 计算机硬件与软件基础.ppt
- 【Scala谜题】继承
- 使用junit进行单元测试_使用JUnit5对DynamoDB应用程序进行单元测试
- iptables 配置后连接不上数据库_Linux服务器配置-VSFTP服务配置(三)
- 修复bug的12个关键步骤
- ASP.NET MVC 2 学习笔记二: 表单的灵活提交
- Microsoft PetShop 3.0 设计与实现 分析报告―――数据访问层
- cad2020安装1603错误_安装Autodesk 2020以及更高软件软件提示1603错误
- matlab运动背景位移矢量,位移云图三维位移矢量图
- java 快速删除文件夹_如何用Java删除文件夹里的所有文件?
- Error:(2, 0) Plugin with id 'com.github.dcendents.android-maven' not found
- python教程视频-有没有适合零基础小白学的python教程,视频或者书籍都可以?
- withRouter有什么用?干嘛用?为啥要用它啊???一分钟理解!
- saas mysql数据库设计_SaaS模式实现架构实例分析=数据库层的设计
- VC及esxi升级的必要性和步骤
- Windows自建虚拟机搭建kms激活服务器激活正版系统教程
- 2022.4.7学习笔记
- 2023年全国最新二级建造师精选真题及答案15