linux 高性能学习笔记9
同CUP管理一样,内存管理也是操作系统最核心的功能之。内存主要用来存储系统和应用程序的指令,数据,缓存等。
内存映射
- 通常说的8G内存指的是物理内存也成主存
- 进程是不可以直接访问物理内存,只有cpu可以直接访问物理内存
- 大多数的主存都是动态随机访问内存(DRAM)
- linux 为每个进程分配一个独立的虚拟地址空间,并且是连续的。
- 虚拟内存空间也被分为内核空间和用户空间。
- 根据cpu指令可以处理数据的最大长度32位和64位
- 32位cpu 最长寻址空间是4G 1G 系统空间 3G 用户空间
- 64位cpu 最长寻址空间是17179869184G
- 头128T 系统空间
- 位128T 用户空间
- 其他 其他空间
- 每个进程都有用户态和内核态,所有的虚拟内存加起来一定大于物理内存,所以并不是所有虚拟内存都分配物理内存,只有那些实际使用的虚拟内存才分配物理内存,并且分配后的物理内存,是通过 内存映射 来管理的。
- MMU(Memory Management Unit)内存管理单元,用于存储页表
- 每个进程都有一个对应的页表来做内存映射
- 当虚拟地址在页表种查找不到地址时 缺页异常 进入内核空间分配物理内存,更新进程页表,最后返回用户空间,恢复进程运行。
- MMU的最小单位是4KB称作页
- 由于页大小只有4KB,加入在32位系统中,就会有100多万的页表才能实现整个地址空间的映射。为了解决页表项过多的问题,linux提供两种机制
- 多级页表:吧内存分成区块来管理,讲原来的映射关系改成区块索引和区块内的偏移。由于虚拟内存空间通常只用很少一部分,那么多级页表就只保存这些使用中的区块,这样就可以大大地减少页表的项数
- 大页:不明思议就是更大的内存块,常见2MB和1GB,多用于使用大量内存的进程上,比如Oracle,DPDK等
虚拟内存空间的分布
- 从低到高分五种不同的内存段:
- 只读段,包括代码和常量等
- 数据段,包括全局变量等
- 堆,包括动态分配的内存,从低地址开始向上增长
- 文件映射段,包括动态库,共享内存等,从高地址开始向下增长
- 栈,包括局部变量和函数调用的上下文等。栈的大小是固定的,一般是8MB
内存分配与回收
- c语言使用malloc()方法分配内存
- brk() 在c 标准库中当分配的内存小于128K默认使用brk(),当使用完成后并不会直接释放,而是缓存起来继续使用
- 缺点:在系统繁忙时容易产生内存碎片
- 优点:可以减少缺页异常的发生
- mmap() 在大于128K使用mmap()分配内存
- 缺点:频繁的分配内存,容易产生缺页异常
- 优点:直接释放内存
- brk() 在c 标准库中当分配的内存小于128K默认使用brk(),当使用完成后并不会直接释放,而是缓存起来继续使用
- 对于内存来说,如果只分配而不释放,就会造成内存泄漏,甚至会耗尽内存。所有应用程序使用完内存后,还需要调用free()或unmap(),来释放这些不用的内存。
- 系统自身也不会任由应用程序的进程用完所有内存的,在发现内存紧张时,系统就会通过一系列机制来回收内存,比如下面这三种方式:
- 回收缓存,比如使用LRU算法,回收最近使用最少的内存页
- 回收不常访问的内存,把不常用的内存通过交换分区直接写到磁盘中(会使用交换分区Swap)
- 杀死进程,内存紧张时系统还会通过OOM(Out of Memory),直接杀掉占用大量内存的进程。
- 是一种内核保护机制
- 使用oom_score记录每个进程的使用内存评分
- 一个进程消耗的内存越大,oom_score就越大
- 一个进程运行占用的CPU越多,oom_score就越小
- 管理员可以手动设置oom_adj,oom_adj的范围[-17,15] 数值越大,表示进程越容易被OOM杀死,-17表示禁止OOM
如何查看内存使用情况
- free 查看内存使用情况
- total 是内存总大小
- used 已使用的内存的大小,包好了共享内存
- free 是未使用内存的大小
- shared 是共享内存的大小
- buff/cache 是缓存和缓冲区的大小
- available 是进程可用内存的大小
- top查看每个进程使用内存情况
- VIRT 是进程虚拟内存的大小
- RES 是常住内存的大小,进程实际使用物理内存的大小,不包含Swap和共享内存。
- SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
- %MEM 是进程使用物理内存占系统内存的百分比
Buffer 和 Cache
- 通常理解buffer是写入时合并写入,加快写入速度的
- 通常理解cache是读取磁盘文件的页缓存,加快速度读取的
linux 文件系统
- 在linux内所有一切皆文件
- 文件分为好多类型(ls -l /dev):
- -:普通文件
- d: 目录
- l:链接
- d: 块文件
- c: 字符串文件
- s: socket文件
- p: 管道文件
- 磁盘会分区块,系统在每个区块上建立文件系统,在文件系统下创建目录,在目录中创建文件。
- 普通文件就是目录中的文件,他的读写基于文件系统
- 块文件,就是磁盘空间,他的读写会跳过文件系统
- 对于以上的两种文件的读写,系统用了不同的优化方式
- 普通文件:cache
- 块文件:buffer
- 以上就是cache和buffer的本质区别。