存储系统
words: 3.1k views: time: 11min存储器是计算机的核心部件之一,用于存储程序和数据。由于现代计算机对于存储器容量和速度的要求越来越高,使得存储器以及演变成了存储系统
存储器层次
在CPU内部有少量的寄存器可以存储正在执行的指令或者正在参加运算的数据,寄存器访问非常快,但数量少;
对于正在运行的程序的指令和数据存放在CPU可以直接访问的主存储器中,称为主存;
在主存之外,为了扩大存储容量会增加一些容量大但是访问较慢的辅助存储器,比如硬盘;CPU不能直接访问外存储器,外存储器的数据需要调用主存后才能由CPU访问;
随着技术发展,CPU和主存的工作速度都在提高,但CPU提高得更快,于是又在CPU和主存之间增加了一层高速缓存(cache),出于对性能的要求,高速缓存本身又可以分成三级,即L1、L2、L3。
因此,现在的存储系统一般分为三级,即由cache、主存和外存储器构成,其中cache主要用于提高访问速度,而外存储器用于提高存储容量问题。
虚存储器
在早期单用户但任务操作系统中(比如DOS),每台计算机只有一个用户,每次只运行一个,且程序不是很大,因此完全可以存储在主存中没问题。
随着多用户多任务系统的出现,以及程序占用存储越来越大,在程序设计时,程序所需的存储容量与计算机实际的主存容量之间往往存在矛盾。而在多用户多任务共享主存的场景下,这些同时运行的程序到底占用内存中哪一部分,在编制程序时是无法确定的,必须等到程序运行时才动态分配。
因此,希望在编制程序时能独立编址,既不考虑程序是否能在物理存储器中存放得下,也不考虑程序应该存放在什么物理位置。而在程序运行时,则分配每个程序一定的运行空间,由地址转换器将编程时的地址转换为实际内存的物理地址。这样,用户编制程序时使用的地址称为虚地址或逻辑地址,而内存中对应的地址称为物理地址。
- 访问过程
用户程序按照虚地址编程并存放在辅助存储器中,当运行时,由地址转换器依据当时分配给程序的实际地址空间把程序的一部分调入主存。
每次访问时,首先判断虚地址对应的部分在主存中是否存在,如果存在,则转换为对物理地址的访问,否则按照某种算法将辅存中的部分程序调入主存中,再按同样的方法访问主存。所以通常虚地址空间可以远大于实际地址空间,比如可以top -M看一下系统中的进程
有了虚存储机制后,应用程序就可以透明地使用整个虚地址空间,如果命中率很高,虚存的访问时间将接近于主存访问时间。由于虚存是在主存和辅存之外附加一些硬件和软件实现的,因此对于设计存储管理的系统程序员是不透明的,不过对于应用程序员而言仍然是透明地。
如果要实现虚存机制,至少要考虑以下问题:
- 调度问题:决定哪些程序和数据被调入主存;
- 地址映射问题:在访问主存时将虚地址转为主存的物理地址,以及在访问辅存时将虚地址转为辅存的物理地址,以便换页,此外还要解决主存分配、存储保护和程序再定位等问题;
- 替换问题:决定哪些程序和数据被调出主存;
- 更新问题:确保主存与辅存的一致性;
在操作系统的控制下,硬件和系统软件为用户解决了上述问题,从而使应用程序的编程大大简化。
页式虚拟存储器
页式虚拟存储系统中,虚地址和主存空间都被分成等长的页,分别称为逻辑页和物理页,至于地址则通过两个字段来描述,高字段为页号,低字段为页内偏移地址。
在大多数系统中,每个进程对应一个页表,页表中对应每一个虚存页面有一个表项,表项内容包含其对应的主存页面地址,以及表示该逻辑页是否已经调入主存的标识位。
但是每个进程所需的页数并不固定,有的进程可能需要很大的地址空间,因此页表可能很长,为了节约页表本身占用的主存空间,有的系统会采用二级分页,即每个进程有一个页目录表,其中的每个表项指向一个页表。
另外,由于页表本身存储在主存中,因而即使逻辑页已经在主存中,CPU也至少要访问两次主存才能获取一次数据,为了避免主存访问次数的增多,可以对页表本身实行二级缓存,把页表中活跃的部分放在高速缓存中,这个专门用于页表缓存的高速缓存通常称为转换后援缓冲器(TLB),也称为快表,而保存在主存中的完成页表则称为慢表,其目的是加快地址变换。
Linux内存管理
在Linux内存管理中,主要是通过调页Paging和交换Swapping来完成内存调度。调页算法是将内存中最近不常使用的页面换到磁盘上,把活动页面保留在内存中供进程使用。分页(Page)写入磁盘的过程被称作Page-Out,分页(Page)从磁盘重新回到内存的过程被称作Page-In。
当系统内核发现可运行内存变少时,就会通过Page-Out来释放一部分物理内存。如果Page-out频繁不断的发生,系统效能会急剧下降。这时的系统已经运行非常慢或进入暂停状态,这种状态也被称为thrashing(颠簸)。
- 命令:vmstat
vmstat是虚拟内存统计(Virtual Meomory Statistics)的缩写,可对操作系统的虚拟内存、进程、CPU活动进行监控。它提供了一种低开销的系统性能观察方式,即使在高负荷的服务器上也能查看并监控系统的健康情况,但它是对系统的整体情况进行统计,无法对某个进程进行深入分析。
格式:
1 | vmstat [-a] [-n] [-S unit] [delay [ count]] |
参数:
1 | -a: 显示活跃和非活跃内存 |
输出:
1 | r: 运行队列中进程数量(如果长期大于1的话,可能需要增加CPU) |
识别CPU瓶颈:当us + sy接近于100时,表示CPU正接近于满负荷工作,但CPU满负荷工作并不能说明什么,Linux总会试图让CPU尽可能的繁忙,以便任务的吞吐量最大化,最能确定CPU瓶颈的还是r,即队列中等待运行的进程数。
如果r长期大于CPU个数(可以通过cat /proc/cpuinfo|grep processor|wc -l查看CPU数),且id很低,则说明cpu的负荷很重,一般出现这种情况,应用程序的问题会比较大一些,比如一些sql语句不合理的情况。
识别RAM内存瓶颈:通过虚拟内存机制,可以将RAM移到SWAP磁盘上,这样会出现虚拟内存的页导出和页导入现象,页导出并不能说明RAM瓶颈,虚拟内存系统经常会进行页导出,但经常出现页导入操作就表明服务器需要更多的内存了,页导入需要从SWAP复制回RAM,导致服务器速度变慢。即如果si和so长期非零的话,则可能存在内存瓶颈。
wa表示CPU用于等待IO的时间,如果内存够大,可以修改文件/proc/sys/vm/swappiness中的值,它表示实际内存区和交换区进行数据交换的倾向性大小,默认60,设置小一点以降低数据交换次数。但如果交换区Swap本身就使用很少,那么修改也没有意义,可能进程本身就是偏IO类型的任务。
示例:
1 | procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- |
查看内存使用情况:
1 | 3863576 K total memory |
参考: