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分区),以腾出更多的内存。

所以,在内存不足时,磁盘的读写频次也会升高。

操作系统的内存管理你知道吗相关推荐

  1. 操作系统的内存管理机制(连续分配管理、页式、段式、段页式、快表、二级页表)

    来源:https://www.bilibili.com/video/BV1YE411D7nH 操作系统的内存管理机制(连续分配管理.页式.段式.段页式.快表.二级页表) 内存被分为系统区和用户区,系统 ...

  2. 操作系统的内存管理方式

    操作系统的内存管理方式有三种:分段式.分页式.段页式. 首先介绍分段式: 概念:将地址空间进行分段,代码段/数据段/堆/栈/参数/环境变量.根据使用一个空间的性质,在不同的分段,分配虚拟地址,有助于编 ...

  3. 操作系统的内存管理算法

    关注.星标公众号,不错过精彩内容 转自:LiteOS物联网操作系统 本文主要介绍内存的基本概念以及操作系统的内存管理算法. 一.内存的基本概念 内存是计算机系统中除了处理器以外最重要的资源,用于存储当 ...

  4. OS - 浅谈操作系统的内存管理

    分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 简介 内存是计算机中最重要的资源之一,通常情况下,物 ...

  5. linux内存管理简介,Linux操作系统的内存管理特性简介 (3)

    输出的第一行(Mem:)显示出物理内存的使用情况.总和(total)列中并没有显示出被内核使用的内存,它通常将近一兆字节.已用列(used column)显示出已用内存的总和(第二行没有把缓冲算进来) ...

  6. linux内存管理 简介,Linux操作系统的内存管理特性简介 (4)

    高速缓冲 与访问(真正的)的内存相比,磁盘[3]的读写是很慢的.另外,在相应较短的时间内多次读磁盘同样的部分也是常有的事.例如,某人也许首先阅读了一段e-mail消息,然后为了答复又将这段消息读入编辑 ...

  7. 深入探讨PHP中的内存管理问题

    一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改 ...

  8. iOS中引用计数内存管理机制分析

    在 iOS 中引用计数是内存的管理方式,虽然在 iOS5 版本中,已经支持了自动引用计数管理模式,但理解它的运行方式有助于我们了解程序的运行原理,有助于 debug 程序. 操作系统的内存管理分成堆和 ...

  9. linux 内存管理 Transparent HugePages 透明大页 简介

    1. 介绍 从RedHat6, RedHat7, OL6, OL7 SLES11 and UEK2 kernels开始,透明大页默认是被开启的以便去改善操作系统的内存管理.透明大页与之前版本的传统意义 ...

最新文章

  1. 修改oracle数据库密码
  2. 注册表文件修改打开程序的简单示例
  3. 计算机硬件部分可称为裸机,上财信管PPT第3章 计算机硬件与软件基础.ppt
  4. 【Scala谜题】继承
  5. 使用junit进行单元测试_使用JUnit5对DynamoDB应用程序进行单元测试
  6. iptables 配置后连接不上数据库_Linux服务器配置-VSFTP服务配置(三)
  7. 修复bug的12个关键步骤
  8. ASP.NET MVC 2 学习笔记二: 表单的灵活提交
  9. Microsoft PetShop 3.0 设计与实现 分析报告―――数据访问层
  10. cad2020安装1603错误_安装Autodesk 2020以及更高软件软件提示1603错误
  11. matlab运动背景位移矢量,位移云图三维位移矢量图
  12. java 快速删除文件夹_如何用Java删除文件夹里的所有文件?
  13. Error:(2, 0) Plugin with id 'com.github.dcendents.android-maven' not found
  14. python教程视频-有没有适合零基础小白学的python教程,视频或者书籍都可以?
  15. withRouter有什么用?干嘛用?为啥要用它啊???一分钟理解!
  16. saas mysql数据库设计_SaaS模式实现架构实例分析=数据库层的设计
  17. VC及esxi升级的必要性和步骤
  18. Windows自建虚拟机搭建kms激活服务器激活正版系统教程
  19. 2022.4.7学习笔记
  20. 2023年全国最新二级建造师精选真题及答案15

热门文章

  1. 服务器护卫神怎么上传文件,护卫神备份文件的方法
  2. 公众号怎么关联小程序?
  3. Android Gnss信息获取 绘制卫星图
  4. 程序员如何在“小公司成长”和“大公司学习”
  5. VBA加载宏制作攻略
  6. Android自定义优惠券解析
  7. 四大游戏编程网站,边玩边学Python
  8. gtk界面学习——显示中文提示框
  9. 计算机考试手册:IT认证全攻略
  10. FastReport 循环打印表格数据