linux內核堆
『壹』 linux為什麼區分內核空間和用戶空間
程序如果要被CPU執行,就得編譯成CPU可以執行的指令,一大堆的程序就變成了一堆的指令。
一個操作系統它也是一堆程序組成的,可以想像CPU的指令是很多的,但是這么多的指令中,有些指令涉及到系統底層的東西,如果有些指令錯用或者使用不當是非常危險的,比如清內存、設置時鍾、修改用戶訪問許可權、分配系統資源等等,可能導致系統崩潰。
CPU將這些指令進行了分類,分為 特權指令 和 非特權指令 ,不讓所有程序都能使用所有指令,如果所有程序都能使用,那系統崩潰就會變得非常常見了。
操作系統的核心是內核,它是獨立於普通的應用程序,負責管理系統的進程、內存、設備驅動程序、文件和網路系統,決定著系統的性能和穩定性,所以一定要埋悄鉛保證內核的安全。
為了保護內核的安全,操作系統一般都限制用戶進程不能直接操作內核,在32位操作系統總的地址空間4G(2^32 = 4GB),實現這個限制的方式就是操作系統將總的地址空間分為兩個部分,對於Linux操作系統:
《 你該知道你寫的程序的內存布局 》
總之,有1G的內核空間是每個進程共享的,剩下的3G是進程自己使用的。
在內核態下,CPU可以執行指令系統的全集,也就是說內核態進程可以調用系統的一切資源,但是特權指令只能在內核態下執行,它不直接提供給用戶使用,用戶態下只能使用非特權指令,也就是說用戶態進程只能執行簡單運算,不能直接調用系統資源。
那麼CPU如何知道當前是否可以使用特權指令?
Linux操作系統通過區分內核空間和用戶空間的這種設計,將操作系統代碼和用戶程序代碼分開,這樣即使在某一個應用程序出錯,也不會影響到操作系統,再說,Linux操作系統是多任務系統,其它應用程彎好序不也還能運行。
現代操作系統基本上都是分內核空間和用戶空間的做法,來 保護操作系統自身的安全性和穩定性,這也是區分內核空間和用戶空間的本質。
你也可以繼續閱讀 點擊 以下文運信章,下面是我推薦給大家的幾篇文章:
1.《 竟然把通信協議講的如此通俗? 》
2.《 c++如何學習?趕緊收藏這些好書 》
3.《 select和epoll的前世今生 》
4.《 徹底明白Linux硬鏈接和軟鏈接 》
『貳』 linux內核探索
對待知識領域,我們總喜歡去下一個定義。操作系統是我們每天工作都要使用的東西,由於現代商業操作系統的復雜性和沒有統一的標准,若對一個操作系統下定義並不能精確的描述操作系統所屬領域。根據經驗我們可以認為操作系統就是在整個應用系統中負責最基本功能和系統管理的那部分。包括內核、設備驅動程序、啟動引導程序、命令行Shell或者GUI界面、基本文件管理工具和系統工具。
嚴格的來講linux只是操作系統內核本身,廣義上的linux則常用來指基於linux內二的完整的操作系統,它包括GUI組件和其它許多工具。
GUI其實只是操作系統的表象,內核才是操作系統內在的核心。系統的其它部分必須依靠內核所提供的服務,像管理硬體設備、分配系統資源等,內核有時候被稱為管理者或者操作系統核心。
通常一個內核由負責響應中斷的中斷服務程序,負責進程調度的CPU調度程序,負責管理進程地址空間的內存管理程序以及網路、進程間通信等系統服務共同組成的。
內核在有安全機制的操作系統中不同於普通程序,一般處於系統態(內核態),擁有受保護的內存空間和訪問硬體設備的所有許可權。這種系統狀態和被保護起來的內存空間,統稱為 內核空間 。
與內核空間相對的,用戶所執行的應用程序在用戶空間執行。用戶態的應用程序只能訪問允許它們使用的系統資源,並且只使用某些特定的系統功能,不能直接訪問硬體,也不能訪問內核劃分給其它應用程序的內存空間。
應用程序通過系統調用來和內核通信,當一個應用程序發起系統調用時,內核便代其執行。在這種情況下應用程序通過系統調用在內核空間運行,而內核被稱為運行在進程上下文中。應用程序通過系統調用進入內核空間時應用完成其工作的基本方式。
操作系統內核可分為兩大陣營:單內核和微內核。
單內核是一種較為簡單的設計,通常以單個靜態二進制文件存儲在磁碟中,整體上作為一個單獨的大過程,所有的內核服務都在這樣的一個大內核地址空間上運行。內核服務都處於內核態,並身處同一內核地址空間,之間可以幾乎無性能損耗的相互通信。
單內核具有簡單和高性能等特點。
微內核根據功能被分割成多個獨立的過程,每個過程都叫做一個伺服器。所有的伺服器都運行在各自的地址空間上(大部分處於用戶空間),只有強烈請求特權服務的伺服器才運行在特權模式下。
微內核伺服器之間不能直接調用函數通信,而是通過 消息傳遞 通信。系統採用進程間通信(IPC)機制,服務之間各自獨立,通過IPC互換消息,有效的避免了服務之間的失敗傳染。
IPC機制的開銷遠高於函數調用,而且在運行時還會牽扯到內核空間和用戶空間上下文切換,所以消息傳遞需要一些開銷。所以在內核的實際實現上大部分微內核的操作系統也會讓大部分的服務放置與內核中,這樣就可以直接調用函數,消除消息傳遞的開銷。
windows NT和Mach(Mac OS X)都是典型的微內核,不過在實際實現上,其所有服務都運行在內核空間。
linux是一個單內核,不過linux汲取了微內核的精華,並擁有模塊化設計、搶占式內核、支持內核線程以及動態裝載內核模塊等特性。
linux內核在設計時充分參考了已有的很多UNIX的內核實現,並且有一些創新方案。linux內核和傳統的UNIX系統之間存在一些顯著的差異:
本文的寫作和學習中參考了以下資料
1.《Linux Kenel Development ~ Thrid Edition 》
『叄』 linux系統的組成結構
Linux系統一般有4個主要部分:內核、shell、文件系統和應用程序。內核、shell和文件系統一起形成了基本的操作系統結構,它們使得用戶可以運行程序、管理文件並使用系統。
1、內核
內核是操作系統的核心,具有很多最基本功能,它負責管理系統的進程、內存、設備驅動程序、文件和網路系統,決定著系統的性能和穩定性。
Linux內核由如下幾部分組成:內存管理、進程管理、設備驅動程序、文件系統和網路管理等。
2、shell
shell是系統的用戶界面,提供了用戶與內核進行交互操作的一種介面。它接收用戶輸入的命令並把它送入內核去執行,是一個命令解釋器。另外,shell編程語言具有普通編程語言的很多特點,用這種編程語言編寫的shell程序與其他應用程序具有同樣的效果。
目前主要有下列版本的shell:
①Bourne shell:是貝爾實驗室開發的。
②BASH:是GNU的Bourne Again
shell,是GNU操作系統上默認的shell,大部分Linux的發行套件使用的都是這種shell。
③Korn shell:是對Bourne shell的發展,在大部分內容上與Bourne shell兼容。
④C shell:是SUN公司shell的BSD版本。
3、文件系統
文件系統是文件存放在磁碟等存儲設備上的組織方法。Linux系統能支持多種目前流行的文件系統,如EXT2、EXT3、FAT、FAT32、VFAT和ISO9660。
4、應用程序
標準的Linux系統一般都有一套稱為應用程序的程序集,它包括文本編輯器、編程語言、X Window、辦公套件、Internet工具和資料庫等。
『肆』 Linux內核由哪幾個子系統組成
Linux內核主要由五個子系統組成:進程調度,內存管理,虛擬文件系統,網路介面,進程間通信。
1.進程調度(SCHED):控制進程對CPU的訪問。當需要選擇下一個進程運行時,由調度程序選擇最值得運行的進程。可運行進程實際上是僅等待CPU資源的進程,如果某個進程在等待其它資源,則該進程是不可運行進程。Linux使用了比較簡單的基於優先順序的進程調度演算法選擇新的進程。
2.內存管理(MM)允許多個進程安全的
共享主內存區域。Linux
的內存管理支持虛擬內存,即在計算機中運行的程序,其代碼,數據,堆棧的總量可以超過實際內存的大小,操作系統只是把當前使用的程序塊保留在內存中,其餘
的程序塊則保留在磁碟中。必要時,操作系統負責在磁碟和內存間交換程序塊。內存管理從邏輯上分為硬體無關部分和硬體有關部分。硬體無關部分提供了進程的映
射和邏輯內存的對換;硬體相關的部分為內存管理硬體提供了虛擬介面。
3.虛擬文件系統
(Virtual File
System,VFS)隱藏了各種硬體的具體細節,為所有的設備提供了統一的介面,VFS提供了多達數十種不同的文件系統。虛擬文件系統可以分為邏輯文件
系統和設備驅動程序。邏輯文件系統指Linux所支持的文件系統,如ext2,fat等,設備驅動程序指為每一種硬體控制器所編寫的設備驅動程序模塊。
4.網路介面(NET)提供了對各種網路標準的存取和各種網路硬體的支持。網路介面可分為網路協議和網路驅動程序。網路協議部分負責實現每一種可能的網路傳輸協議。網路設備驅動程序負責與硬體設備通訊,每一種可能的硬體設備都有相應的設備驅動程序。
5.進程間通訊(IPC) 支持進程間各種通信機制。
『伍』 Linux內核——用戶堆棧和內核堆棧
每個進程都有用戶堆棧和內核堆棧兩個堆棧。進程在用戶態時使用用戶堆棧,陷入到內核態時便使用內核堆棧。
『陸』 linux 內核堆棧總大小 怎麼決定
Linux內核棧溢出(stack overflow)問題
最近一段時間在設計和開發一個Linux內核模塊,進入到最後的正確性測試與穩定性測試階段。在這個階段發現了一個非常有意思的問題,堆棧溢出(stack overflow)。Linux內核堆棧溢出之後直接導致了系統kernel Panic。由於導致stack overflow的原因是遞歸調用導致的,所以,最後通過調試串口導出的kernel panic信息很快就定位問題所在了,否則這樣的問題還真是很難調試和發現。通過這次bug,我們應該記住的是:Linux內核stack資源是有限的,而遞歸調用將大量消耗stack資源,因此在內核編程中盡量少用遞歸演算法,否則將會導致出乎意料的一些問題。依次類推,為了減少stack資源的消耗,程序的局部變數定義的不要太大,否則也將會消耗大量stack資源,從而導致內核程序的不穩定。
為了解決遞歸調用導致的問題,我將遞歸演算法改寫成了非遞歸演算法,解決了stack overflow的問題。在此介紹一下遞歸演算法改寫成非遞歸演算法的一些思想。在項目實現過程中,需要對IO請求進行按順序排隊,因此採用了效率較高並且實現簡單的快速排序演算法,該演算法是一種分治演算法,即將排序隊列進行切分,分解成一系列的小問題進行求解,針對這種問題,很容易採用遞歸的辦法進行實現,偽代碼描述如下:
/* qs_sort實現從小到大的排序 */
Struct bio qs_sort(struct bio_list *list_head, struct bio *bio_tail) {
Struct bio_list *less_list, *large_list;
Struct bio *middle_bio;
/* 遞歸調用結束點,小問題求解完畢,直接返回最後一個元素 */
If (!list_head) {
Return bio_tail;
}
/* 對隊列進行切分,選擇一個middle_bio,並且按照middle_bio將其切分成less_list隊列和large_list隊列 */
Split_list(list_head, less_list, large_list, &middle_bio);
/* 採用遞歸的方法實現大隊列的排序操作 */
Middle_bio->bi_next = qs_sort(large_list, bio_tail);
/* 採用遞歸的方法實現小隊列的排序操作 */
Return qs_sort(less_list, middle_bio);
}
『柒』 LINUX系統的內存管理知識詳解
內存是Linux內核所管理的最重要的資源之一。內存管理系統是操作系統中最為重要的部分,因為系統的物理內存總是少於系統所需要的內存數量。虛擬內存就是為了克服這個矛盾而採用的策略。系統的虛擬內存通過在各個進程之間共享內存而使系統看起來有多於實際內存的內存容量。Linux支持虛擬內存, 就是使用磁碟作為RAM的擴展,使可用內存相應地有效擴大。核心把當前不用的內存塊存到硬碟,騰出內存給其他目的。當原來的內容又要使用時,再讀回內存。以下就是我為大家整理到的詳細LINUX系統內存管理的知識,歡迎大家閱讀!!!
LINUX系統教程:內存管理的知識詳解
一、內存使用情況監測
(1)實時監控內存使用情況
在命令行使用「Free」命令可以監控內存使用情況
代碼如下:
#free
total used free shared buffers cached
Mem: 256024 192284 63740 0 10676 101004
-/+ buffers/cache: 80604 175420
Swap: 522072 0 522072
上面給出了一個256兆的RAM和512兆交換空間的系統情況。第三行輸出(Mem:)顯示物理內存。total列不顯示核心使用的物理內存(通常大約1MB)。used列顯示被使用的內存總額(第二行不計緩沖)。 free列顯示全部沒使用的內存。Shared列顯示多個進程共享的內存總額。Buffers列顯示磁碟緩存的當前大小。第五行(Swap:)對對換空間,顯示的信息類似上面。如果這行為全0,那麼沒使用對換空間。在預設的狀態下,free命令以千位元組(也就是1024位元組為單位)來顯示內存使用情況。可以使用—h參數以位元組為單位顯示內存使用情況,或者可以使用—m參數以兆位元組為單位顯示內存使用情況。還可以通過—s參數使用命令來不間斷地監視內存使用情況:
#free –b –s2
這個命令將會在終端窗口中連續不斷地報告內存的使用情況,每2秒鍾更新一次。
(2)組合watch與 free命令用來實時監控內存使用情況:
代碼如下:
#watch -n 2 -d free
Every 2.0s: free Fri Jul 6 06:06:12 2007
total used free shared buffers cached
Mem: 233356 218616 14740 0 5560 64784
-/+ buffers/cache: 148272 85084
Swap: 622584 6656 615928
watch命令會每兩秒執行 free一次,執行前會清除屏幕,在同樣位置顯示數據。因為 watch命令不會卷動屏幕,所以適合出長時間的監測內存使用率。可以使用 -n選項,控制執行的頻率;也可以利用 -d選項,讓命令將每次不同的地方顯示出來。Watch命令會一直執行,直到您按下 [Ctrl]-[C] 為止。
二、虛擬內存的概念
(1)Linux虛擬內存實現機制
Linux虛擬內存的實現需要六種機制的支持:地址映射機制、內存分配回收機制、緩存和刷新機制、請求頁機制、交換機制、內存共享機制。
首先內存管理程序通過映射機制把用戶程序的邏輯地址映射到物理地址,在用戶程序運行時如果發現程序中要用的虛地址沒有對應的物理內存時,就發出了請求頁要求;如果有空閑的內存可供分配,就請求分配內存(於是用到了內存的分配和回收),並把正在使用的物理頁記錄在緩存中(使用了緩存機制)。 如果沒有足夠的內存可供分配,那麼就調用交換機制,騰出一部分內存。另外在地址映射中要通過TLB(翻譯後援存儲器)來尋找物理頁;交換機制中也要用到交換緩存,並且把物理頁內容交換到交換文件中後也要修改頁表來映射文件地址。
(2)虛擬內存容量設定
也許有人告訴你,應該分配2倍於物理內存的虛擬內存,但這是個不固定的規律。如果你的物理保存比較小,可以這樣設定。如果你有1G物理內存或更多的話,可以縮小一下虛擬內存。Linux會把大量的內存用做Cache的,但在資源緊張時回收回.。你只要看到swap為0或者很小就可以放心了,因為內存放著不用才是最大的浪費。
三、使甩vmstat命令監視虛擬內存使用情況
vmstat是Virtual Meomory Statistics(虛擬內存統計)的縮寫,可對操作系統的虛擬內存、進程、CPU活動進行監視。它是對系統的整體情況進行統計,不足之處是無法對某個進程進行深入分析。通常使用vmstat 5 5(表示在5秒時間內進行5次采樣)命令測試。將得到一個數據匯總它可以反映真正的系統情況。
代碼如下:
#vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 62792 3460 9116 88092 6 30 189 89 1061 569 17 28 54 2
0 0 62792 3400 9124 88092 0 0 0 14 884 434 4 14 81 0
0 0 62792 3400 9132 88092 0 0 0 14 877 424 4 15 81 0
1 0 62792 3400 9140 88092 0 0 0 14 868 418 6 20 74 0
1 0 62792 3400 9148 88092 0 0 0 15 847 400 9 25 67 0
vmstat命令輸出分成六個部分:
(1)進程procs:
r:在運行隊列中等待的進程數 。
b:在等待io的進程數 。
(2)內存memoy:
swpd:現時可用的交換內存(單位KB)。
free:空閑的內存(單位KB)。
buff: 緩沖去中的內存數(單位:KB)。
cache:被用來做為高速緩存的內存數(單位:KB)。
(3) swap交換頁面
si: 從磁碟交換到內存的交換頁數量,單位:KB/秒。
so: 從內存交換到磁碟的交換頁數量,單位:KB/秒。
(4) io塊設備:
bi: 發送到塊設備的塊數,單位:塊/秒。
bo: 從塊設備接收到的塊數,單位:塊/秒。
(5)system系統:
in: 每秒的中斷數,包括時鍾中斷。
cs: 每秒的環境(上下文)切換次數。
(6)cpu中央處理器:
cs:用戶進程使用的時間 。以百分比表示。
sy:系統進程使用的時間。 以百分比表示。
id:中央處理器的空閑時間 。以百分比表示。
如果 r經常大於 4 ,且id經常小於40,表示中央處理器的負荷很重。 如果bi,bo 長期不等於0,表示物理內存容量太小。
四、Linux 伺服器的內存泄露和回收內存的方法
1、內存泄漏的定義:
一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完後必須顯示釋放的內存。應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了。
2、內存泄露的危害
從用戶使用程序的角度來看,內存泄漏本身不會產生什麼危害,作為一般的用戶,根本感覺不到內存泄漏的存在。真正有危害的`是內存泄漏的堆積,這會最終消耗盡系統所有的內存。從這個角度來說,一次性內存泄漏並沒有什麼危害,因為它不會堆積,而隱式內存泄漏危害性則非常大,因為較之於常發性和偶發性內存泄漏它更難被檢測到。存在內存泄漏問題的程序除了會佔用更多的內存外,還會使程序的性能急劇下降。對於伺服器而言,如果出現這種情況,即使系統不崩潰,也會嚴重影響使用。
3、內存泄露的檢測和回收
對於內存溢出之類的麻煩可能大家在編寫指針比較多的復雜的程序的時候就會遇到。在 Linux 或者 unix 下,C、C++語言是最使用工具。但是我們的 C++ 程序缺乏相應的手段來檢測內存信息,而只能使用 top 指令觀察進程的動態內存總額。而且程序退出時,我們無法獲知任何內存泄漏信息。
使用kill命令
使用Linux命令回收內存,我們可以使用Ps、Kill兩個命令檢測內存使用情況和進行回收。在使用超級用戶許可權時使用命令「Ps」,它會列出所有正在運行的程序名稱,和對應的進程號(PID)。Kill命令的工作原理是:向Linux操作系統的內核送出一個系統操作信號和程序的進程號(PID)。
應用例子:
為了高效率回收內存可以使用命令ps 參數v:
代碼如下:
[root@www ~]# ps v
PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND
2542 tty1 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty1
2543 tty2 Ss+ 0:00 0 8 1631 428 0.1 /sbin/mingetty tty2
2547 tty3 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty3
2548 tty4 Ss+ 0:00 0 8 1627 428 0.1 /sbin/mingetty tty4
2574 tty5 Ss+ 0:00 0 8 1631 432 0.1 /sbin/mingetty tty5
2587 tty6 Ss+ 0:00 0 8 1627 424 0.1 /sbin/mingetty tty6
2657 tty7 Ss+ 1:18 12 1710 29981 7040 3.0 /usr/bin/Xorg :0 -br -a
2670 pts/2 Ss 0:01 2 682 6213 1496 0.6 -bash
3008 pts/4 Ss 0:00 2 682 6221 1472 0.6 /bin/bash
3029 pts/4 S+ 0:00 2 32 1783 548 0.2 ping 192.168.1.12
3030 pts/2 R+ 0:00 2 73 5134 768 0.3 ps v
然後如果想回收Ping命令的內存的話,使用命令:
代碼如下:
# Kill -9 3029
使用工具軟體
Memprof是一個非常具有吸引力且非常易於使用的軟體,它由Red Hat的Owen Talyor創立。這個工具是用於GNOME前端的Boehm-Demers-Weiser垃圾回收器。這個工具直接就可以執行,並且其工作起來無需對源代碼進行任何修改。在程序執行時,這個工具會以圖形化的方式顯示內存的使用情況。
相關介紹:Linux
嚴格來講,Linux這個詞本身只表示Linux內核,但人們已經習慣了用Linux來形容整個基於Linux內核,並且使用GNU 工程各種工具和資料庫的操作系統。
Linux擁有以下特性:類似於Unix的基本思想,支持完全免費與自由傳播,完全兼容POSIX1.0標准,支持多用戶、多任務、有著良好的界面、支持多種平台。Linux 能運行主要的UNIX工具軟體、應用程序和網路協議。它支持32位和64位硬體。Linux繼承了Unix以網路為核心的設計思想,是一個性能穩定的多用戶網路操作系統。
Linux有著許多不同的版本,但它們都使用了Linux內核。Linux可安裝在各種計算機硬體設備中,比如手機、平板電腦、路由器、視頻游戲控制台、台式計算機、大型機和超級計算機。
『捌』 linux中斷處理程序使用的堆棧是內核的堆棧嗎,在哪裡
當然是,進程生成時,會被分配一個task_struct 結構(常說的進程式控制制塊),2.4內核中,在task_struct 結構體上面的7KB空間就是。加上task_struct結構本身(1KB),進程內核棧共8KB(兩個頁面 ),不會動態擴展,所以非常有限(你會見到內核代碼用"大塊"內存都會kmalloc申請的,就是這個原因)。2.6內核的沒注意,不知一樣否。詳見:《Linux內核源代碼情景分析(上)》267頁。
為什麼會在內核的原因是CPU的保護機制,中斷處理需要更高的許可權(可能執行硬體相關的操作),故要在0級,不會在用戶區的。
『玖』 如何查看Linux內存中的程序所有堆的地址
linux 下面查看內存有多種渠道,比如通過命令 ps ,top,free 等,比如通過/proc系統,一般需要比較詳細和精確地知道整機內存/某個進程內存的使用情況,最好通過/proc 系統,下面介紹/proc系統下內存相關的幾個文件
單個進程的內存查看 cat /proc/[pid] 下面有幾個文件: maps , smaps, status
maps 文件可以查看某個進程的代碼段、棧區、堆區、動態庫、內核區對應的虛擬地址,如果你還不了解linux進程的內存空間,可以參考這里。
下圖是maps文件內存示例
Develop>cat /proc/self/maps
00400000-0040b000 r-xp 00000000 fd:00 48 /mnt/cf/orig/root/bin/cat
0060a000-0060b000 r--p 0000a000 fd:00 48 /mnt/cf/orig/root/bin/cat
0060b000-0060c000 rw-p 0000b000 fd:00 48 /mnt/cf/orig/root/bin/cat 代碼段
0060c000-0062d000 rw-p 00000000 00:00 0 [heap] 堆區
7f1fff43b000-7f1fff5d4000 r-xp 00000000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff5d4000-7f1fff7d3000 ---p 00199000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d3000-7f1fff7d7000 r--p 00198000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d7000-7f1fff7d9000 rw-p 0019c000 fd:00 861 /mnt/cf/orig/root/lib64/libc-2.15.so
7f1fff7d9000-7f1fff7dd000 rw-p 00000000 00:00 0
7f1fff7dd000-7f1fff7fe000 r-xp 00000000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9f9000-7f1fff9fd000 rw-p 00000000 00:00 0
7f1fff9fd000-7f1fff9fe000 r--p 00020000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9fe000-7f1fff9ff000 rw-p 00021000 fd:00 2554 /mnt/cf/orig/root/lib64/ld-2.15.so
7f1fff9ff000-7f1fffa00000 rw-p 00000000 00:00 0
7fff443de000-7fff443ff000 rw-p 00000000 00:00 0 [stack] 用戶態棧區
7fff443ff000-7fff44400000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 內核區
有時候可以通過不斷查看某個進程的maps文件,通過查看其虛擬內存(堆區)是否不停增長來簡單判斷進程是否發生了內存溢出。
maps文件只能顯示簡單的分區,smap文件可以顯示每個分區的更詳細的內存佔用數據
下圖是smaps文件內存示例, 實際顯示內容會將每一個區都顯示出來,下面我只拷貝了代碼段和堆區,
每一個區顯示的內容項目是一樣的,smaps文件各項含義可以參考這里
Develop>cat /proc/self/smaps
00400000-0040b000 r-xp 00000000 fd:00 48 /mnt/cf/orig/root/bin/cat
Size: 44 kB 虛擬內存大小
Rss: 28 kB 實際使用物理內存大小
Pss: 28 kB
Shared_Clean: 0 kB 頁面被改,則是dirty,否則是clean,頁面引用計數>1,是shared,否則是private
Shared_Dirty: 0 kB
Private_Clean: 28 kB
Private_Dirty: 0 kB
Referenced: 28 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB 處於交換區的頁面大小
KernelPageSize: 4 kB 操作系統一個頁面大小
MMUPageSize: 4 kB 體系結構MMU一個頁面大小
Locked: 0 kB
0060c000-0062d000 rw-p 00000000 00:00 0 [heap]
Size: 132 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
下圖是status文件內存示例, 加粗部分是內存相關的統計,
Develop>cat /proc/24475/status
Name: netio 可執行程序的名字
State: R (running) 任務狀態,運行/睡眠/僵死
Tgid: 24475 線程組號
Pid: 24475 進程id
PPid: 19635 父進程id
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256 該進程最大文件描述符個數
Groups: 0
VmPeak: 6330708 kB 內存使用峰值
VmSize: 268876 kB 進程虛擬地址空間大小
VmLck: 0 kB 進程鎖住的物理內存大小,鎖住的物理內存無法交換到硬碟
VmHWM: 16656 kB
VmRSS: 11420 kB 進程正在使用的物理內存大小
VmData: 230844 kB 進程數據段大小
VmStk: 136 kB 進程用戶態棧大小
VmExe: 760 kB 進程代碼段大小
VmLib: 7772 kB 進程使用的庫映射到虛擬內存空間的大小
VmPTE: 120 kB 進程頁表大小
VmSwap: 0 kB
Threads: 5
SigQ: 0/63346
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001000000
SigCgt: 0000000180000000
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: 01
Cpus_allowed_list: 0
Mems_allowed: 01
Mems_allowed_list: 0
voluntary_ctxt_switches: 201
nonvoluntary_ctxt_switches: 909
可以看到,linux下內存佔用是一個比較復雜的概念,不能
簡單通過一個單一指標就判斷某個程序「內存消耗」大小,原因有下面2點:
進程所申請的內存不一定真正會被用到(malloc或mmap的實現)
真正用到了的內存也不一定是只有該進程自己在用 (比如動態共享庫)
關於內存的使用分析及本文幾個命令的說明也可以參考這里
下面是查看整機內存使用情況的文件 /proc/meminfo
Develop>cat /proc/meminfo
MemTotal: 8112280 kB 所有可用RAM大小 (即物理內存減去一些預留位和內核的二進制代碼大小)
MemFree: 4188636 kB LowFree與HighFree的總和,被系統留著未使用的內存
Buffers: 34728 kB 用來給文件做緩沖大小
Cached: 289740 kB 被高速緩沖存儲器(cache memory)用的內存的大小
(等於 diskcache minus SwapCache )
SwapCached: 0 kB 被高速緩沖存儲器(cache memory)用的交換空間的大小
已經被交換出來的內存,但仍然被存放在swapfile中。
用來在需要的時候很快的被替換而不需要再次打開I/O埠
Active: 435240 kB 在活躍使用中的緩沖或高速緩沖存儲器頁面文件的大小,
除非非常必要否則不會被移作他用
Inactive: 231512 kB 在不經常使用中的緩沖或高速緩沖存儲器頁面文件的大小,可能被用於其他途徑.
Active(anon): 361252 kB
Inactive(anon): 120688 kB
Active(file): 73988 kB
Inactive(file): 110824 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB 交換空間的總大小
SwapFree: 0 kB 未被使用交換空間的大小
Dirty: 0 kB 等待被寫回到磁碟的內存大小
Writeback: 0 kB 正在被寫回到磁碟的內存大小
AnonPages: 348408 kB 未映射頁的內存大小
Mapped: 33600 kB 已經被設備和文件等映射的大小
Shmem: 133536 kB
Slab: 55984 kB 內核數據結構緩存的大小,可以減少申請和釋放內存帶來的消耗
SReclaimable: 25028 kB 可收回Slab的大小
SUnreclaim: 30956 kB 不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack: 1896 kB 內核棧區大小
PageTables: 8156 kB 管理內存分頁頁面的索引表的大小
NFS_Unstable: 0 kB 不穩定頁表的大小
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 2483276 kB
Committed_AS: 1804104 kB
VmallocTotal: 34359738367 kB 可以vmalloc虛擬內存大小
VmallocUsed: 565680 kB 已經被使用的虛擬內存大小
VmallocChunk: 34359162876 kB
HardwareCorrupted: 0 kB
HugePages_Total: 1536 大頁面數目
HugePages_Free: 0 空閑大頁面數目
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB 大頁面一頁大小
DirectMap4k: 10240 kB
DirectMap2M: 8302592 kB
『拾』 linux內核內存泄露檢測
經常碰到系統跑著跑著一段時間內存滿了,出現內存泄漏的問題,系統軟體太龐大,這類問題又不好直接從源碼中分析,所以需要藉助工具來分析了,kmemleak就是這樣的一個工具。
在Kernel hacking中打開CONFIG_DEBUG_KMEMLEAK =y即使能了kmemleak,其實就是開了一個內核線程,該內核線程每10分鍾(默認值)掃描內存,並列印發現派耐新的未引用的對象的數量。kmemleak的原理其實就是通過kmalloc、vmalloc、kmem_cache_alloc等內存的分配,跟蹤其指針,連同其他的分配大小和堆棧跟蹤信息,存儲在PRIO搜索樹。如果存在相應的釋放函數調用跟蹤和指針,就會從kmemleak數據結構中移除塵毀春。下面我們看看具體的用法。
查看內核列印信息詳細過程如下:
1、掛載debugfs文件系統
mount -t debugfs nodev /sys/kernel/debug/
2、開啟內核自動檢測線程
echo scan > /sys/kernel/debug/kmemleak
3、查看列印信息
cat /sys/kernel/debug/kmemleak
4、清除內核檢測報告,新的內存泄露報告將重新寫入/sys/kernel/debug/kmemleak
echo clear > /sys/kernel/debug/kmemleak
內存掃描參數可以進行修改通過向/sys/kernel/debug/kmemleak 文件寫入。 參數使用如下:
off 禁用kmemleak(不可逆)
stack=on 啟用任務堆棧掃描(default)
stack=off 禁用任務堆棧掃描
scan=on 啟動自動記憶掃描線程(default)
scan=off 停止自動記憶掃描線程
scan=<secs> 設置n秒內自動記憶掃描,默認600s
scan 開啟內核掃描
clear 清除內存泄露報告
mp=<addr> 轉存信息對象在<addr>
通過「kmemleak = off」,也可以在啟動時禁用Kmemleak在內核命令行。在初始化kmemleak之前,內存的分配或釋放這些動作被存儲在余弊一個前期日誌緩沖區。這個緩沖區的大小通過配CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設置。