Linux 內(nèi)核給每個進程都提供了一個獨立的虛擬地址空間,并且這個地址空間是連續(xù)的。這樣進程就可以很方便地訪問內(nèi)存,更確切地說是訪問虛擬內(nèi)存。
1、什么是虛擬內(nèi)存假設(shè)某個進程需要100MB的空間,而內(nèi)存假設(shè)是16MB的,如果進程直接使用物理地址,就會因為內(nèi)存不足而無法運行。
既然進程不是直接訪問物理內(nèi)存,那么進程中涉及的內(nèi)存地址當然也不是物理內(nèi)存地址。而是虛擬的內(nèi)存地址,虛擬的內(nèi)存地址和物理的內(nèi)存地址之間保持一種映射關(guān)系,這種關(guān)系由內(nèi)存管理單元(MMU)進行管理。
內(nèi)存管理單元(Memory Management Unit,MMU),將物理內(nèi)存分割成多個pages,MMU管理進程的虛擬地址空間中的page和物理內(nèi)存中的page之間的映射關(guān)系。、
因為是映射,所以隨時都可能發(fā)生變化,例如某個進程虛擬內(nèi)存空間中的page1,在不同的時間點,可能出現(xiàn)在物理內(nèi)存中的不同位置(當發(fā)生了頁交換時)。
虛擬地址空間的內(nèi)部又被分為內(nèi)核空間和用戶空間兩部分。并不是所有的虛擬內(nèi)存都會分配物理內(nèi)存,只有那些實際使用的虛擬內(nèi)存才分配物理內(nèi)存,并且分配后的物理內(nèi)存,是通過內(nèi)存映射來管理的。
當進程訪問它的虛擬地址空間中的page時,如果這個page目前還不在物理內(nèi)存中,此時CPU是不能工作的,Linux會產(chǎn)生一個hard page fault中斷。系統(tǒng)需要從慢速設(shè)備(如磁盤)將對應(yīng)的數(shù)據(jù)page讀入物理內(nèi)存,并建立物理內(nèi)存地址與虛擬地址空間page的映射關(guān)系。然后進程才能訪問這部分虛擬地址空間的內(nèi)存。
page fault 又分為三種:minor page fault、major page fault、invalid(segment fault)。
2.1、minor page fault也稱為 soft page fault,指需要訪問的內(nèi)存不在虛擬地址空間,但是在物理內(nèi)存中,需要MMU建立物理內(nèi)存和虛擬地址空間的映射關(guān)系。
當一個進程在調(diào)用 malloc 獲取虛擬空間地址后,首次訪問該地址會發(fā)生一次soft page fault。
通常是多個進程訪問同一個共享內(nèi)存中的數(shù)據(jù),當某些進程還沒有建立起映射關(guān)系,訪問時也會出現(xiàn)soft page fault。
也稱為 hard page fault,指需要訪問的內(nèi)存不在虛擬地址空間,也不在物理內(nèi)存中,需要從慢速設(shè)備載入。
從磁盤 swap in 回到物理內(nèi)存就是 hard page fault。
swap out:當物理內(nèi)存不夠時,把一些物理內(nèi)存 page 中的內(nèi)容寫入到磁盤,以騰出一些空閑的 page;swap in:當CPU要執(zhí)行的指令被發(fā)現(xiàn)已經(jīng) swap out 到了磁盤中, 這時就需要從磁盤把這些指令再 swap in 到物理內(nèi)存中。注意:swap in 和 swap out 的操作都是比較耗時的。
2.3、invalid(segment fault)也稱為 segment fault,指進程需要訪問的內(nèi)存地址不在它的虛擬地址空間范圍內(nèi),屬于越界訪問,內(nèi)核就會報 segment fault 錯誤。
造成 segment fault 的原因可能有以下幾種:
堆棧溢出;內(nèi)存訪問越界,如數(shù)組下表錯誤訪問越界;使用strcpy/strcat/sprintf/strcmp 等字符串操作函數(shù)導(dǎo)致的讀寫越界,應(yīng)盡量使用strncpy/strncat/snprintf/strncmp 等函數(shù);非法指針:野指針,錯誤的指針轉(zhuǎn)換等;多線程讀寫的數(shù)據(jù)未加鎖保護,或使用了線程不安全的函數(shù)。轉(zhuǎn)載請注明來自夕逆IT,本文標題:《strncmp(虛擬內(nèi)存 和 page fault 的解釋)》

還沒有評論,來說兩句吧...