这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » Linux内存系统:内存使用场景

共1条 1/1 1 跳转至

Linux内存系统:内存使用场景

专家
2020-08-25 07:40:56     打赏

out of memory 的时代过去了吗?no,内存再充足也不可任性使用。
1、内存的使用场景

· page 管理

· slabkmalloc、内存池)

· 用户态内存使用(mallocrelloc 文件映射、共享内存)

· 程序的内存 map(栈、堆、codedata

· 内核和用户态的数据传递(copy_from_usercopy_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—申请内存小于等于 128kbdo_map—申请内存大于 128kb

 

 


6、用户进程访问内存分析

· 用户态进程独占虚拟地址空间,两个进程的虚拟地址可相同

· 在访问用户态虚拟地址空间时,如果没有映射物理地址,通过系统调用发出缺页异常

· 缺页异常陷入内核,分配物理地址空间,与用户态虚拟地址建立映射

 

图片6.png 


7、共享内存
1)    原理

· 它允许多个不相关的进程去访问同一部分逻辑内存

· 两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案

· 两个运行中的进程共享数据,是进程间通信的高效方法,可有效减少数据拷贝的次数

 

图片5.png 


2)    Shm 接口

· shmget 创建共享内存

· shmat 启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间

· shmdt 将共享内存从当前进程中分离

Linux内存系统:五、 内存使用那些坑


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 等)、删除元素导致顺序容器迭代器失效


错误示例:删除当前迭代器,迭代器会失效 

图片4.png 


正确示例:迭代器 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_mapstd::unordered_sethash 实现的无序的容器,插入、删除和查找的时间复杂度都是 O(1),在不关注容器内元素顺序的场合,使用 unordered 的容器能获得更高的性能六、 如何查看内存

· 系统中内存使用情况:/proc/meminfo  

 

图片3.png 

· 进程的内存使用情况:/proc/28040/status

· 查询内存总使用率:free

 

图片2.png 

 

· 查询进程 cpu 和内存使用占比:top

· 虚拟内存统计:vmstat

 


图片1.png

 

· 进程消耗内存占比和排序: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

 

 





关键词: 内存     系统     使用     场景    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]