首页 > 系统相关 >内存管理

内存管理

时间:2023-08-09 20:11:55浏览次数:32  
标签:调用 映射 管理 内存 进程 虚拟内存 内核

一、内存管理
用户层
STL 智能指针/容器 自动分配、释放 调用C++
C++ new/delete 调用C
C malloc/free 调用POSIX\Linux
POSIX brk/sbrk 调用内核
Linux mmap/munmap 调用内核
系统层
Kernal kmalloc/vmalloc 调用驱动
dirver get_free_page

二、进程映像
程序存储在磁盘上的可执行文件(脚本、二进制),当执行程序时,系统会把可执行文件加载到内存形成进程,一个程序可以同时加载出多个进程
进程在内存中的分布情况就是进程映像,从地地址到高地址依次是:
text 代码段: 二进制指令、常量(数值、"字符串字面值"、被const修饰过的原data的数据)
只读,强制修改会段错误
data 数据段: 初始化过的全局变量、初始化过的静态局部变量
bss 静态数据段:未初始化过的全局变量、未初始化过的静态局部变量
程序运行前会自动清0
heap 堆: 程序员手动管理的大量数据,管理麻烦、申请和释放受控,与指针配合使用,使用不当可能会内存泄漏、内存碎片
stack 栈: 局部变量、块变量
大小有限、自动申请、释放
environ 环境变量表:所有的环境变量
每个进程都有一份,修改不会影响系统真正的环境变量的值
argv 命令行参数:
程序执行时附带的参数
练习1:打印出各个内存段的数据的地址,与该进程的maps文件中记录的内存分布比较
查看maps:/proc/进程ID/maps
查看进程ID:
命令:ps -aux 函数:getpid()

三、虚拟内存
1、32位系统会给每个进程分配4G的虚拟内存空间
2、进程、用户只能使用访问虚拟内存,无法直接使用真实的物理内存
3、虚拟内存只有与物理内存进行映射后才能使用,否则会产生段错误
4、虚拟内存与物理内存的映射和对应使用都是由操作系统动态维护
5、虚拟内存技术一方面是为了让系统更加安全,可以不暴露真实的物理内存地址给用户,又可以让一个进程出错后不影响其他进程和系统的运行,另一方面可让进程使用比实际物理内存更大的空间
6、4G的虚拟内存地址分成两个部分
[0~3G) 用户空间
[3G~4G) 内核空间
7、当进程\线程运行在内核空间时,称该进程\线程处于内核态,当进程\线程运行在用户空间时,称该进程\线程处于用户态
8、在内核态下,进程运行在内核空间,此时CPU可以执行任何指令,此时运行的代码不受任何限制,可以自由访问任何有效的地址
9、在用户态下,进程运行在用户空间,此时进程不能直接访问内核空间的数据,可以通过系统调用(API 系统接口函数)的方式切换到内核态,间接地访问内核空间的数据
10、对虚拟内存越界访问(访问没有映射过的虚拟内存),导致段错误

四、映射虚拟内存与物理内存的函数
sbrk/brk/mmap/munmap
关于 malloc 获取虚拟内存实际调用POSIX还是Linux提供的函数受到操作系统、编译器、字节数的影响,大致逻辑:
1、如果申请小于128Kb调用sbrk\brk
2、如果申请大于128Kb调用mmap\munmap
注意:strace ./a.out 可以追踪程序的底层调用(用户层)
注意:系统内存映射是以页(1页=4096字节)为单位的

注意:sbrk、brk底层维护一个映射位置指针,该指针指向虚拟内存中映射过的内存的最后一个字节的下一个位置,可以通过移动该指针来实现映射内存和取消映射的效果
void *sbrk(intptr_t increment);
功能:通过增量increment来调整映射位置指针的位置,从而进行映射或取消映射
    increment:增量(字节为单位)
        0   获取映射位置指针的位置
        >0  映射内存
        <0  取消映射
返回值:映射指针原来的位置

int brk(void *addr);
功能:通过修改映射指针指向addr的地址,从而进行映射或取消映射
    addr:
        > 原来位置 映射
        < 原来位置 取消映射
返回值:成功返回0 失败返回-1

总结:sbrk、brk都属于POSIX标准中的内存映射函数,都是可以单独进行映射、取消映射,但是配合使用最方便(sbrk映射、brk取消映射)

练习2:计算2~1000之间的素数,存储在堆内存中,要求尽可能少地浪费内存       

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
功能:映射虚拟内存与物理内存
addr:映射内存的起始地址,可以自己指定,如果赋NULL则由操作系统指定
length:要映射的字节数
prot:映射后的权限
    PROT_EXEC   执行权限    PROT_EXEX | PROT_READ 
    PROT_READ   读权限
    PROT_WRITE  写权限
    PROT_NONE   没有权限
flags:映射标志
    MAP_FIXED  如果提供的addr无法映射,则直接失败
    MAP_ANONYMOUS 指定映射虚拟内存,不映射文件,fd、offset失效
    MAP_SHARED  对映射后的内存可以共享给其他进程
    MAP_PRIVATE 对映射后的内存只能当前进程使用 
        注意:flags中必须在MAP_SHARED、MAP_PRIVATE之间二选一
fd:文件描述符 可以让文件映射到物理内存,不需要映射文件直接写0
offset:文件的偏移位置,从该位置开始映射文件
返回值:成功返回映射后的内存首地址,失败返回(void*)-1

int munmap(void *addr, size_t length);
功能:取消映射
addr:映射的内存首地址
length:取消映射的字节数
返回值:成功返回0 失败返回-1

五、Linux内存管理总结
1、mmap\munmap底层不维护任何东西,直接在堆内存中选择合适的内存进行映射,返回映射成功后的内存首地址
2、sbrk\brk底层维护一个映射位置指针,该指针记录了通过sbrk\brk映射内存的末尾位置,通过改变该指针的位置来映射和取消映射
3、malloc\free底层调用了sbrk\brk 或者 mmap\munmap,虚拟内存必须与物理内存建立映射关系后才能使用
4、每个进程都有4G(32位)的虚拟内存空间
5、内存管理的重点是理解Linux对内存管理机制,而不是sbrk\brk\mmap\munmap函数的使用

六、系统调用(系统API、系统函数)
系统调用指的是由操作系统提供的一些功能给程序员调用,这些功能已经被封装成C语言函数的形式,但是它们不属于标准C的一部分,也不真正的函数
一般的应用进程工作运行在用户态(03G),使用系统调用时进程会转入到内核态(34G)
常用的C标准库函数的大部分时间都工作在用户态,当底层进行系统调用时会偶尔转入内核态工作
通过time命令查看进程在两种状态下的运行时间情况:
real 0m0.001s 总执行时间
user 0m0.001s 用户态执行时间
sys 0m0.000s 内核态执行时间
系统调用的代码是内核的一部分,其外部接口以C函数的形式存储在共享库中(linux-gate.so.1 、 /lib/ld-linux.so.2),当调用这些外部接口时进程会以软中断的方式进入内核态执行真正的系统调用函数

标签:调用,映射,管理,内存,进程,虚拟内存,内核
From: https://www.cnblogs.com/wangqiuji/p/17617893.html

相关文章

  • 简易的学生管理系统(go语言)
    简易的学生管理系统(go语言)首先,你需要安装github.com/go-sql-driver/mysql这个包来操作MySQL数据库。你可以使用以下命令来安装它:gogetgithub.com/go-sql-driver/mysqlpackagemainimport( "database/sql" "fmt" "os" "bufio" "strings" _"......
  • 物业管理APP开发在实际生活中能带来哪些便利?
    随着社会的不断发展和生活方式的变化,物业管理成为了一个日益重要的领域。为了更好地满足居民的需求,提升物业管理的效率和质量,物业管理APP的开发应运而生。这类移动应用程序不仅为物业公司提供了更便捷的管理工具,也为居民提供了更方便的服务和沟通渠道。在实际生活中,物业管理app开发......
  • Python潮流周刊#5:并发一百万个任务要用多少内存?
    你好,我是猫哥。这里记录每周值得分享的Python及通用技术内容,部分为英文,已在小标题注明。(标题取自其中一则分享,不代表全部内容都是该主题,特此声明。)文章&教程1、并发一百万个任务要用多少内存?(英文)文中测试了主流的编程语言(Rust、Go、Java、C#、Python、Node.js和Elixir),依次运行......
  • node版本管理神器nvm安装使用教程(Windows11版本)
    什么是nvm?当我们在同时在做几个需求不同的项目时,可能我们需要使用不一样的node.js版本,那么我们就需要在不同的node.js版本中进行切换,我们要在电脑上重复卸载安装多个不同版本的node,非常麻烦,这个时候,我们就可以使用nvm来管理我们安装的node,需要使用哪个就指定哪个即可。nvm,即nodeve......
  • 银行电子密码器也远程管理吗?操作步骤如下
    企业需要在不同办公地点管理多个资金账户,能不能远程点按读取银行电子密码器呢?三个字,很简单!可以用密码点按器!有了它就可以自动输入密码和读取验证码!第一步用双面胶把密码器固定在点按器上,一台点按器最多可以管理六个密码器,第二步打开朝天椒软件,给点按器录入不同密码按键的位置坐标。......
  • 江苏省发布雨水排放环境管理办法,这些重点值得关注!
    近日,江苏省深入打好污染防治攻坚战指挥部办公室正式印发了《江苏省重点行业工业企业雨水排放环境管理办法(试行)》,已于2023年5月15日正式施行。本办法所称重点行业工业企业,是指化工、电镀原料药制造、冶炼、印染行业(或含相关工序)的工业企业,以下简称“工业企业”。要求工业企业建......
  • Salesforce 助理认证和管理员认证有何区别?备考者应如何选择?
    随着Salesforce生态系统对专业人员的需求不断增长,获得相关认证对于寻求职业发展的从业者来说至关重要。对于刚接触Salesforce平台的人而言,Salesforce助理认证和Salesforce管理员认证是两个比较基础的认证。这两个认证有什么区别呢?从业者应该考哪个?本篇文章将探讨两种认证的主要......
  • wsgi uwsgi uWSGI,cgi,fastcgi 分别是什么?如何自定制上下文管理器;Python是值传递还是引
    WSGI/uWSGI/uwsgi/CGI/FastCGI分别是什么?如何自定制上下文管理器;Python是值传递还是引用传递WSGI/uWSGI/uwsgi/CGI/FastCGI分别是什么?#CGI:通用网关接口(CommonGatewayInterface/CGI)-CGI描述了服务器(nginx,apache)和请求处理程序(django,flask,springbootweb框架)之间......
  • Java源代码是如何编译,加载到内存中的?
    1.前言相信许多开发同学看过《深入理解java虚拟机》,也阅读过java虚拟机规范,书籍和文档给人的感觉不够直观,本文从一个简单的例子来看看jvm是如何工作的吧。本文所有操作均在mac上进行。2.示例代码示例代码采用最常见的双重检索单例模式:packageinterview.desginpattern.single......
  • CefSharp (铬) javascript增加内存限制
    https://stackoverflow.com/questions/55099372 好了,伙计们,我已经想出了一个解决方案。当您将这些参数传递给chrome可执行文件以将javascript内存限制设置为16it时,chrome会将其设置为3.5it。--js-flags="--max_old_space_size=16384"复制似乎将内存大小设置为3.5GB以上......