通過日常使用電腦,我們大概都知道一個機器大概的結構由CPU、內存、硬盤以及外設構成,那么Linux服務器也一樣,從上一章內容知道,我們平常關注的系統性能差不多就是這些地方,那么,我們的進程是如何在Linux上運行的呢?一、進程運行過程首先,我們的數據是存放于磁盤/NAS等存儲目錄當中,當需要使用這些數據的時候,則要將數據從磁盤中讀取出來,經過內存再到三級緩存,然后進入到CPU中。如下圖,數據從底部的存儲設備一步一步的被送進入到CPU中。其用于傳輸數據的方式:遠程存儲到本地二級存儲走的是網絡通信的方式,而本地存儲的數據進入到內存、CPU走的是BUS總線的方式。
進程啟動以后,其數據被從磁盤中讀取到內存里緩存,當CPU使用到它的時候,再被通過三級高速緩存送入到CPU中執行。那么當這個進程被送入到CPU中運行,是不是就可以一個人獨占CPU資源,直到跑完為止呢?不是的,現代系統設計出了上下文切換的模式,每個進程運行的時候都會分配到了一個時間片,當這個時間片用完,那么當前正在運行的進程就會保留當前的狀態進入到緩存當中,當再次輪到該進程使用CPU的時候,才會從緩存當中被讀取出來。通過這樣反復的切換,直到進程運行結束。但是我們在使用進程時,為什么沒有進程切換的感覺呢?那是因為CPU的時間片以非常小的時間單位工作著,人們根本感受不到他的切換頻率。在Linux系統中存在著兩個空間,一個是用戶空間,另外一個就是內核空間。用戶空間指的是用戶可以操作和訪問的空間,這個空間通常存放我們用戶自己寫的數據等,比如磁盤NAS就是屬于用戶空間。內核空間就是系統內核來操作的一塊空間,這塊空間里面存放系統內核的函數、接口等,用戶是不能直接操作的。當程序在用戶空間下運行,我們把此時運行的程序的這種狀態稱為用戶態,而當進程執行在內核空間時,這種狀態稱為內核態。要想讓程序從用戶態切換到內核態,有3種方法:1.系統調用 (軟中斷)2.異常(硬中斷) 3.外圍設備的中斷(硬中斷)。二、進程異常會遇到什么?進程在運行過程中不是一開始就知道使用多少內存的,在持續的運行過程中,會不斷的向系統申請內存。當有應用需要讀寫磁盤數據時,由系統把相關數據從磁盤讀取到內存,如果物理內存不夠,則把內存中的部分數據導入到磁盤,從而把磁盤的部分空間當做虛擬內存使用,這部分被稱為swap。如果給所有應用分配足夠內存后,物理內存還有剩余,Linux會盡量再利用這些空閑內存,以提高整體I/O效率,方法是把這部分剩余內存再劃分為cache和buffer加以利用。如果某個時刻,系統需要更多的內存,則會把cache部分擦除,并把buffer中的內容寫入到磁盤中,然后把這兩部分的空間釋放給系統使用,但是再次讀取cache的內容時,就需要重新從磁盤讀取數據。下圖是系統中存在的緩存,當系統需要內存時,就會被釋放空間,然后充當內存使用。
1) Page cache主要用來作為文件系統上的文件數據緩存來用,尤其是對當進程對文件有read/write操作的時候。2) Buffer cache主要是用來在系統對塊設備進行讀寫的時候,對塊設備進行數據緩存來使用。3) directory cacha的作用是作為目錄緩存,避免經常訪問目錄慢。4) iNode cache則能夠加速訪問文件速度。同一系統內的文件具有唯一識別碼,這個就是iNode號。查找文件的時候會先查詢該文件的iNode號,再根據iNode號定位到文件位置。一般可以理解為buffer是為了作為數據寫入磁盤時的一個緩沖地帶。把分散的寫操作集中進行,減少磁盤碎片和硬盤的反復尋道,從而提高系統性能。而cache經常被用于磁盤的I/O請求上,如果多個進程都有訪問某個文件,于是該文件便被作為cache以方便下次被訪問,這樣可以提高系統性能。
三、當運行一個進程時系統內存不夠會怎么樣?
在工作中會遇到這樣的場景:假設我的服務器就只有32G內存,當前以及使用了28G,而現在需要再運行一個需要10G內存的進程,那么會發生什么呢?
如果這個進程沒有做什么優先級設定,那么這個進程會觸發OOM,然后被系統kill掉。
什么是OOM?
OOM的全稱是Out of memory Killer,叫內存終結者。在內存過低的情況下,OS(系統)會殺掉你的進程。當探測到內存使用不足的時候,OOM會被激活,然后挑選一個進程去終結掉。選擇的目標進程使用的是一套算法,后面會說。
進程在運行過程中是怎么使用內存的呢?Linux允許程序申請比系統可用內存更多的內存,這個機制叫做Overcommit。這樣做是處于優化系統考慮,因為不是所有的程序申請了內存就立刻使用的,當開始使用的時候,可能系統已經回收了一些資源,但是當使用overcommit給的內存時,系統還沒有資源的話,這個時候就會觸發OOM,然后干掉進程。
有的時候在系統內存不是很充足的情況下需要運行一個重要的程序,那么該如何避免此程序被OOM干掉呢?
調整進程的oom_adj值:Linux下每個進程都有個OOM權重,在/proc/$pid/oom_adj里面,取值-17~+15,取值越高,越容易被干掉。
OOM Killer最終是通過/proc/$pid/oom_score這個值來決定哪個進程被干掉。這個值是系統綜合進程的內存消耗量、CPU時間、存活時間和oom_adj計算出來的。消耗內存越多分越高,存活時間越長分越低。總之。總的策略就是:損失最少的工作,釋放最大的內存同時不傷及無辜的用來很大內存的進程,并且殺掉的進程數盡量少。另外,Linux在計算進程的內存消耗的時候,會將子進程所耗內存的一半同時計算到父進程中,這樣子進程較多的進程就越容易被殺掉。
在Linux中如何查看是否有進程被OOM干掉了呢?
運行dmesg即可查詢到,或者到/var/log/messages中查看。從網上找了個OOM的圖:
-
cpu
+關注
關注
68文章
11066瀏覽量
216620 -
Linux
+關注
關注
87文章
11499瀏覽量
213348 -
服務器
+關注
關注
13文章
9759瀏覽量
87652
發布評論請先 登錄
如何評價《Linux就該這么學》這本書?
3516 L1 Linux版本成功啟動!可以愉快地玩耍了~
到底是學STM32還是學嵌入式linux
什么是嵌入式Linux?
Linux到底是怎么樣來的?發展過程是如何的
Linux到底是如何收發網絡包的

評論