如何查看進程發生缺頁中斷的次數?函數
用ps -o majflt,minflt -C program命令查看。佈局
majflt表明major fault,中文名叫大錯誤,minflt表明minor fault,中文名叫小錯誤。spa
這兩個數值表示一個進程自啓動以來所發生的缺頁中斷的次數。操作系統
發成缺頁中斷後,執行了那些操做?3d
當一個進程發生缺頁中斷的時候,進程會陷入內核態,執行如下操做:
一、檢查要訪問的虛擬地址是否合法
二、查找/分配一個物理頁
三、填充物理頁內容(讀取磁盤,或者直接置0,或者啥也不幹)
四、創建映射關係(虛擬地址到物理地址)
從新執行發生缺頁中斷的那條指令
若是第3步,須要讀取磁盤,那麼此次缺頁中斷就是majflt,不然就是minflt。
指針
內存分配的原理blog
從操做系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk和mmap(不考慮共享內存)。進程
一、brk是將數據段(.data)的最高地址指針_edata往高地址推;內存
二、mmap是在進程的虛擬地址空間中(堆和棧中間,稱爲文件映射區域的地方)找一塊空閒的虛擬內存。it
這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操做系統負責分配物理內存,而後創建虛擬內存和物理內存之間的映射關係。
在標準C庫中,提供了malloc/free函數分配釋放內存,這兩個函數底層是由brk,mmap,munmap這些系統調用實現的。
下面以一個例子來講明內存分配的原理:
狀況1、malloc小於128k的內存,使用brk分配內存,將_edata往高地址推(只分配虛擬空間,不對應物理內存(所以沒有初始化),第一次讀/寫數據時,引發內核缺頁中斷,內核才分配對應的物理內存,而後虛擬地址空間創建映射關係),以下圖:
一、進程啓動的時候,其(虛擬)內存空間的初始佈局如圖1所示。
其中,mmap內存映射文件是在堆和棧的中間(例如libc-2.2.93.so,其它數據文件等),爲了簡單起見,
省略了內存映射文件。
_edata指針(glibc裏面定義)指向數據段的最高地址。
二、進程調用A=malloc(30K)之後,內存空間如圖2:
malloc函數會調用brk系統調用,將_edata指針往高地址推30K,就完成虛擬內存分配。
你可能會問:
只要把_edata+30K就完成內存分配了?
事實是這樣的,_edata+30K只是完成虛擬地址的分配,
A這塊內存如今仍是沒有物理頁與之對應的,
等到進程第一次讀寫A這塊內存的時候,發生缺頁中斷,這個時候,內核才分配A這塊內存對應的物理頁。
也就是說,若是用malloc分配了A這塊內容,而後歷來不訪問它,那麼,A對應的物理頁是不會被分配的。
三、進程調用B=malloc(40K)之後,內存空間如圖3。
狀況2、malloc大於128k的內存,使用mmap分配內存,在堆和棧之間找一塊空閒內存分配(對應獨立內存,並且初始化爲0),以下圖:
![](http://static.javashuo.com/static/loading.gif)
四、進程調用C=malloc(200K)之後,內存空間如圖4:
默認狀況下,malloc函數分配內存,若是請求內存大於128K(可由M_MMAP_THRESHOLD選項調節),那就不是去推_edata指針了,而是利用mmap系統調用,從堆和棧的中間分配一塊虛擬內存。
這樣子作主要是由於::
brk分配的內存須要等到高地址內存釋放之後才能釋放(例如,在B釋放以前,A是不可能釋放的,這就是內存碎片產生的緣由,何時緊縮看下面),而mmap分配的內存能夠單獨釋放。
固然,還有其它的好處,也有壞處,再具體下去,有興趣的同窗能夠去看glibc裏面malloc的代碼了。
五、進程調用D=malloc(100K)之後,內存空間如圖5;
六、進程調用free(C)之後,C對應的虛擬內存和物理內存一塊兒釋放。
七、進程調用free(B)之後,如圖7所示:
B對應的虛擬內存和物理內存都沒有釋放,由於只有一個_edata指針,若是往回推,那麼D這塊內存怎麼辦呢?
固然,B這塊內存,是能夠重用的,若是這個時候再來一個40K的請求,那麼malloc極可能就把B這塊內存返回回去了。
八、進程調用free(D)之後,如圖8所示:
B和D鏈接起來,變成一塊140K的空閒內存。
九、默認狀況下:
當最高地址空間的空閒內存超過128K(可由M_TRIM_THRESHOLD選項調節)時,執行內存緊縮操做(trim)。在上一個步驟free的時候,發現最高地址空閒內存超過128K,因而內存緊縮,變成圖9所示。