Linux内存技术分析(下)
Linux内存技术分析(下)
五、内存使用场景
out of memory 的时代过去了吗?no,内存再充足也不可任性使用。
1、内存的使用场景
- page 管理
- slab(kmalloc、内存池)
- 用户态内存使用(malloc、relloc 文件映射、共享内存)
- 程序的内存 map(栈、堆、code、data)
- 内核和用户态的数据传递(copy_from_user、copy_to_user)
- 内存映射(硬件寄存器、保留内存)
- DMA 内存
2、用户态内存分配函数
- alloca 是向栈申请内存,因此无需释放
- malloc 所分配的内存空间未被初始化,使用 malloc() 函数的程序开始时(内存空间还没有被重新分配) 能正常运行,但经过一段时间后(内存空间已被重新分配) 可能会出现问题
- calloc 会将所分配的内存空间中的每一位都初始化为零
- realloc 扩展现有内存空间大小
- a)如果当前连续内存块足够 realloc 的话,只是将 p 所指向的空间扩大,并返回 p 的指针地址。这个时候 q 和 p 指向的地址是一样的
- b)如果当前连续内存块不够长度,再找一个足够长的地方,分配一块新的内存,q,并将 p 指向的内容 copy 到 q,返回 q。并将 p 所指向的内存空间删除
3、内核态内存分配函数
函数分配原理最大内存其他_get_free_pages直接对页框进行操作4MB适用于分配较大量的连续物理内存kmem_cache_alloc基于 slab 机制实现128KB适合需要频繁申请释放相同大小内存块时使用kmalloc基于 kmem_cache_alloc 实现128KB最常见的分配方式,需要小于页框大小的内存时可以使用vmalloc建立非连续物理内存到虚拟地址的映射物理不连续,适合需要大内存,但是对地址连续性没有要求的场合dma_alloc_coherent基于_alloc_pages 实现4MB适用于 DMA 操作ioremap实现已知物理地址到虚拟地址的映射适用于物理地址已知的场合,如设备驱动alloc_bootmem在启动 kernel 时,预留一段内存,内核看不见小于物理内存大小,内存管理要求较高
4、malloc 申请内存
- 调用 malloc 函数时,它沿 free_chuck_list 连接表寻找一个大到足以满足用户请求所需要的内存块
- free_chuck_list 连接表的主要工作是维护一个空闲的堆空间缓冲区链表
- 如果空间缓冲区链表没有找到对应的节点,需要通过系统调用 sys_brk 延伸进程的栈空间
5、缺页异常
- 通过 get_free_pages 申请一个或多个物理页面
- 换算 addr 在进程 pdg 映射中所在的 pte 地址
- 将 addr 对应的 pte 设置为物理页面的首地址
- 系统调用:Brk—申请内存小于等于 128kb,do_map—申请内存大于 128kb
6、用户进程访问内存分析
- 用户态进程独占虚拟地址空间,两个进程的虚拟地址可相同
- 在访问用户态虚拟地址空间时,如果没有映射物理地址,通过系统调用发出缺页异常
- 缺页异常陷入内核,分配物理地址空间,与用户态虚拟地址建立映射
7、共享内存
1) 原理
- 它允许多个不相关的进程去访问同一部分逻辑内存
- 两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案
- 两个运行中的进程共享数据,是进程间通信的高效方法,可有效减少数据拷贝的次数
2) Shm 接口
- shmget 创建共享内存
- shmat 启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间
- shmdt 将共享内存从当前进程中分离
六、内存使用那些坑
1、C 内存泄露
- 在类的构造函数和析构函数中没有匹配地调用 new 和 delete 函数
- 没有正确地清除嵌套的对象指针
- 没有将基类的析构函数定义为虚函数
- 当基类的指针指向子类对象时,如果基类的析构函数不是 virtual,那么子类的析构函数将不会被调用,子类的资源没有得到正确释放,因此造成内存泄露
- 缺少拷贝构造函数,按值传递会调用(拷贝)构造函数,引用传递不会调用
- 指向对象的指针数组不等同于对象数组,数组中存放的是指向对象的指针,不仅要释放每个对象的空间,还要释放每个指针的空间
- 缺少重载赋值运算符,也是逐个成员拷贝的方式复制对象,如果这个类的大小是可变的,那么结果就是造成内存泄露
2、C 野指针
- 指针变量没有初始化
- 指针被 free 或 delete 后,没有设置为 NULL
- 指针操作超越了变量的作用范围,比如返回指向栈内存的指针就是野指针
- 访问空指针(需要做空判断)
- sizeof 无法获取数组的大小
- 试图修改常量,如:char p="1234";p=\'1\';
3、C 资源访问冲突
- 多线程共享变量没有用 valotile 修饰
- 多线程访问全局变量未加锁
- 全局变量仅对单进程有效
- 多进程写共享内存数据,未做同步处理
- mmap 内存映射,多进程不安全
4、STL 迭代器失效
- 被删除的迭代器失效
- 添加元素(insert/push_back 等)、删除元素导致顺序容器迭代器失效
错误示例:删除当前迭代器,迭代器会失效
正确示例:迭代器 erase 时,需保存下一个迭代器
5、C++ 11 智能指针
- auto_ptr 替换为 unique_ptr
- 使用 make_shared 初始化一个 shared_ptr
- weak_ptr 智能指针助手(1)原理分析:
(2)数据结构:
(3)使用方法:a. lock() 获取所管理的对象的强引用指针 b. expired() 检测所管理的对象是否已经释放 c. get() 访问智能指针对象
6、C++ 11 更小更快更安全
- std::atomic 原子数据类型 多线程安全
- std::array 定长数组开销比 array 小和 std::vector 不同的是 array 的长度是固定的,不能动态拓展
- std::vector vector 瘦身 shrink_to_fit():将 capacity 减少为于 size() 相同的大小
- td::forward_list
forward_list 是单链表(std::list 是双链表),只需要顺序遍历的场合,forward_list 能更加节省内存,插入和删除的性能高于 list
- std::unordered_map、std::unordered_set用 hash 实现的无序的容器,插入、删除和查找的时间复杂度都是 O(1),在不关注容器内元素顺序的场合,使用 unordered 的容器能获得更高的性能六、 如何查看内存
- 系统中内存使用情况:/proc/meminfo
- 进程的内存使用情况:/proc/28040/status
- 查询内存总使用率:free
- 查询进程 cpu 和内存使用占比:top
- 虚拟内存统计:vmstat
- 进程消耗内存占比和排序:ps aux –sort -rss
- 释放系统内存缓存:
/proc/sys/vm/drop_caches
- To free pagecache, use echo 1 > /proc/sys/vm/drop_caches
- To free dentries and inodes, use echo 2 > /proc/sys/vm/drop_caches
- To free pagecache, dentries and inodes, use echo 3 >/proc/sys/vm/drop_caches
Linux内存技术分析(下)的更多相关文章
- Linux内存技术分析(上)
Linux内存技术分析(上) 一.Linux存储器 限于存储介质的存取速率和成本,现代计算机的存储结构呈现为金字塔型.越往塔顶,存取效率越高.但成本也越高,所以容量也就越小.得益于程序访问的局部性原理 ...
- 性能分析 | Linux 内存占用分析
这篇博客主要介绍 linux 环境下,查看内存占用的两种方式:使用 ps,top等命令:查看/proc/[pid]/下的文件.文章简要介绍了命令的使用方法与一些参数意义,同时对/proc/[pid]/ ...
- linux内存负载分析
衡量内存负载的一个很重要的指标就是页面置换的频率.当linux系统频繁的对页进行换进换出 的时候,说明物理内存不过,不得不进行频繁的置换页面. 使用vmstat(virtual memory stat ...
- 利用Volatility对Linux内存取证分析-常用命令翻译
命令翻译 linux_apihooks - 检查用户名apihooks linux_arp - 打印ARP表 linux_aslr_shift - 自动检测Linux aslr改变 linux_ban ...
- linux内存占用分析
概述 想必在linux上写过程序的同学都有分析进程占用多少内存的经历,或者被问到这样的问题——你的程序在运行时占用了多少内存(物理内存)?通常我们可以通过top命令查看进程占用了多少内存.这里我们可以 ...
- linux 内存使用分析
查看当前内存使用情况,最常用的指令就是 [root@t ~]# free -m total used free shared buffers cached Mem: -/+ buffers/cac ...
- 转: 关于Linux与JVM的内存关系分析
转自: http://tech.meituan.com/linux-jvm-memory.html Linux与JVM的内存关系分析 葛吒2014-08-29 10:00 引言 在一些物理内存为8g的 ...
- Linux与JVM的内存关系分析
引言 在一些物理内存为8g的server上,主要执行一个Java服务,系统内存分配例如以下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约600m,Linux自身使用大约800m. 从表面 ...
- Linux与JVM的内存关系分析(转)
引言 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约600m,Linux自身使用大约800m.从表面上,物理内存 ...
随机推荐
- 从苏宁电器到卡巴斯基第24篇:难忘的三年硕士时光 II
没办法,还是先打好基础吧 其实在我知道自己面试失败后,第一个想法就是将面试官问我的问题都总结出来,然后通过查权威的资料,找出所有问题的答案,背下所有的答案,大概过一到两个月吧,再面试金山.当时我是这么 ...
- android dalvik浅析一:解释器及其执行
dalvik是android中使用的虚拟机,基于寄存器,分析基于android4.2源代码.本篇主要分析的是dalvik中的解释器部分,源码位于/dalvik/vm,主要代码在interp和mterp ...
- Access数据库及注入方法
目录 Access数据库 Access数据库中的函数 盲注Access数据库 Sqlmap注入Access数据库 Access数据库 Microsoft Office Access是由微软发布的关系数 ...
- Linux-鸟菜-2-主机规划与磁盘分区
Linux-鸟菜-2-主机规划与磁盘分区 开机流程: 1. BIOS:開機主動執行的韌體,會認識第一個可開機的裝置: 2. MBR:第一個可開機裝置的第一個磁區內的主要開機記錄區塊,內含開機管理程式: ...
- 『动善时』JMeter基础 — 8、JMeter主要元件介绍
目录 1.测试计划(Test Plan) 2.线程组 3.取样器(sampler) 4.逻辑控制器(Logic Controller) 5.配置元件(Config Element) 6.定时器(Tim ...
- C++基于文件流和armadillo读取mnist
发现网上大把都是用python读取mnist的,用C++大都是用opencv读取的,但我不怎么用opencv,因此自己摸索了个使用文件流读取mnist的方法,armadillo仅作为储存矩阵的一种方式 ...
- Yii2访问gii模块403
出现问题 访问Yii2的gii模块没有权限,403 找到原因 在Yii2-gii源码文件中(vendor/yiisoft/yii2-gii/src/Module.php)可以看到有一个配置项$allo ...
- Smss.exe加载win32k.sys过程总结
windows操作系统初始化 windows操作系统再初始化的过程中,当内核完全初始化而且各个组件也已经准备好后会加载一个个用户进程smss.exe(会话管理器),此进程会接着调用NtSetSyste ...
- 一文解决MySQL时区相关问题
前言: 在使用MySQL的过程中,你可能会遇到时区相关问题,比如说时间显示错误.时区不是东八区.程序取得的时间和数据库存储的时间不一致等等问题.其实,这些问题都与数据库时区设置有关,本篇文章将从数据库 ...
- [MySQL数据库之Navicat.pymysql模块、视图、触发器、存储过程、函数、流程控制]
[MySQL数据库之Navicat.pymysql模块.视图.触发器.存储过程.函数.流程控制] Navicat Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降 ...