
通过电脑的日常使用,我们大概都知道,一台机器的一般结构是由CPU、内存、硬盘和外设组成的,Linux服务器也是如此。从上一章我们知道,我们平时关注的系统性能几乎就是这些地方。那么,我们的进程如何在Linux上运行呢?一、进程运行进程首先,我们的数据存储在磁盘/NAS等存储目录中。当我们需要使用这些数据时,要从磁盘中读取数据,经过内存再到三级缓存,然后进入CPU。如下图,数据是从底层的存储设备一步步送到CPU的。用来传输数据的方式:远程存储到本地二级存储采取网络通信的方式,本地存储数据进入内存,CPU采取总线的方式。
进程启动后,其数据从磁盘读入内存缓存,当CPU使用时,通过三级缓存发送给CPU执行。那么这个进程送到CPU运行的时候,能不能由一个人独占,直到完成?不,现代系统已经设计了一种上下文切换的模式。当每个进程运行时,它将被分配一个时间片。当这个时间片用完后,当前运行的进程会保持当前状态进入缓存,当轮到进程再次使用CPU时会从缓存中读取。通过这种反复切换,直到流程运行结束。但是我们在使用流程的时候,为什么没有流程切换的感觉呢?那是因为CPU的时间片工作在非常小的时间单位内,人们根本感觉不到它的切换频率。Linux系统有两个空间,一个是用户空间,一个是内核空间。用户空间是指用户可以操作和访问的空间。这个空间通常存储我们的用户写的数据,比如磁盘NAS。内核空间是由系统内核操作的空间。这个空间包含了系统内核的功能和接口,用户无法直接操作。当程序在用户空间运行时,我们把程序此时运行的这种状态称为用户状态,而当进程在内核空间执行时,这种状态称为内核状态。有三种方法可以将程序从用户模式切换到内核模式:1 .系统调用(软中断)2。异常(硬中断)3。外围设备中断(硬中断)。二、流程异常会发生什么情况?进程一开始不知道要用多少内存,在持续运行的过程中会不断向系统申请内存。当应用程序需要读写磁盘数据时,系统会将相关数据从磁盘读取到内存中。如果物理内存不足,它会将一些数据从内存导入到磁盘,从而将部分磁盘空间用作虚拟内存。这部分叫做互换。如果为所有应用程序分配了足够的内存,并且还有剩余的物理内存,Linux将通过将剩余的内存划分为缓存和缓冲区,尝试重用空闲的内存来提高整体I/O效率。如果系统在某个时刻需要更多的内存,就会擦除一部分缓存并将缓冲区的内容写入磁盘,然后将这两部分的空间释放给系统使用,但是当再次读取缓存的内容时,就需要再次从磁盘读取数据。下图显示了系统中存在的缓存。当系统需要内存时,它会被释放出来,然后用作内存。
1)页面缓存主要用作文件系统上的文件数据缓存,尤其是当进程对文件有读/写操作时。2)缓冲区缓存主要用于系统读写块设备的数据时进行缓存。3)使用目录cacha作为目录缓存,避免频繁的目录访问。4) iNode缓存可以加快文件访问速度。同一系统中的文档有一个惟一的标识符,这就是iNode号。在查找文件时,首先会查询文件的iNode号,然后根据iNode号定位文件位置。一般可以理解为buffer是在数据写入磁盘时作为缓冲区使用的。集中分散的写操作,减少磁盘碎片和硬盘重复寻道,从而提高系统性能。缓存通常用于磁盘I/O请求。如果多个进程访问一个文件,该文件将被用作缓存以方便下一次访问,这可以提高系统性能。
三、运行进程时系统内存不足会发生什么情况?
在工作中,我会遇到这样的场景:假设我的服务器只有32G内存,目前用了28G,但是现在我需要运行另一个需要10G内存的进程,那么会发生什么情况?
如果这个进程没有做任何优先级设置,那么这个进程就会触发OOM,然后就会被系统杀死。
OOM是什么?
OOM的全称是内存不足黑仔,也就是所谓的内存终结者。如果内存太低,操作系统会终止你的进程。当检测到内存不足时,OOM将被激活,然后选择一个进程来终止它。所选择的目标进程使用一组算法,这将在后面描述。
进程在运行过程中如何使用内存?Linux允许程序申请超过系统所能使用的内存。这种机制被称为过度承诺。这样做是出于优化系统的考虑,因为不是所有的程序在申请内存后都会立即使用。当他们开始使用的时候,系统可能已经回收了一些资源,但是在使用overcommit给的内存的时候,如果系统没有资源,这个时候就会触发OOM,然后进程就会被杀死。
有时候需要在系统内存不够的情况下运行一个重要的程序,那么如何防止这个程序被OOM杀死呢?
调整进程的oom_adj值:Linux下每个进程都有一个oom权重。在/proc/$pid/oom_adj中,值为-17~ 15。数值越高越容易被击杀。
OOM黑仔最终通过/proc/$pid/oom_score的值来决定终止哪个进程。该值由系统合成进程的内存消耗、CPU时间、存活时间和oom_adj计算得出。消耗的内存越多,分数越高,存活时间越长,分数越低。总之。一般的策略是丢失最少的工作,在不伤害使用大量内存的无辜进程的情况下释放最多的内存,并杀死尽可能少的进程。另外,Linux在计算进程的内存消耗时,会将子进程消耗的一半内存同时计算到父进程中,这样进程多的进程更容易被杀死。
如何在Linux中检查一个进程是否已经被OOM杀死?
运行dmesg来查找它,或者在/var/log/messages中检查它。从网上找到一张OOM的图片:









