在工作中經常會遇到一些內核crash的情況,本文就是根據內核出現crash後的打印信息,對其進行了分析,使用的內核版本為:Linux2.6.32。
每一個進程的生命周期內,其生命周期的范圍為幾毫秒到幾個月。一般都是和內核有交互,例如用戶空間程序使用系統調用進入內核空間。這時使用的不再是用戶空間的棧空間,使用對應的內核棧空間。對每一個進程來說,Linux內核都會把兩個不同的數據結構緊湊的存放在一個單獨為進程分配的存儲空間中:一個是內核態的進程堆棧,另一個是緊挨進程描述符的數據結構thread_info,叫線程描述符。內核的堆棧大小一般為8KB,也就是8192個字節,占用兩個頁。在Linux-2.6.32內核中thread_info.h文件中有對內核堆棧的定義:
在Linux內核中使用下面的聯合結構體表示一個進程的線程描述符和內核棧,在內核中文件include/linux/sched.h。
該結構是一個聯合體,我們在C語言書上看到過關於union的解釋,在在C Programming Language 一書中對於聯合體是這麼描述的:
1) 聯合體是一個結構;
2) 它的所有成員相對於基地址的偏移量都為0;
3) 此結構空間要大到足夠容納最"寬"的成員;
4) 其對齊方式要適合其中所有的成員;
通過上面的描述可知,thread_union結構體的大小為8192個字節。也就是stack數組的大小,類型是unsigned long類 型。由於聯合體中的成員變量都是占用同一塊內存區域,所以,在平時寫代碼時總有一個概念,對一個聯合體的實例只能使用其中一個成員變量,否則會把原先變量 給覆蓋掉,這句話如果正確的話,必須要有一個前提假設,成員占用的字節數相同,當成員所占的字節數不同時,只會覆蓋相應的字節。對於thread_union聯合體,我們是可以同時訪問這兩個成員,只要能夠正確獲取到兩個成員變量的地址。
怎樣在 Ubuntu 上安裝 Linux 3.11 內核 http://www.linuxidc.com/Linux/2013-09/89674.htm
Ubuntu 13.10 (Saucy Salamander) 內核已升級至 Linux Kernel 3.10 RC5 http://www.linuxidc.com/Linux/2013-06/86110.htm
Linux Kernel 3.4.62 LTS 現已經提供下載 http://www.linuxidc.com/Linux/2013-09/90368.htm
如何在Ubuntu 13.10上安裝Linux內核 3.12 http://www.linuxidc.com/Linux/2013-11/92930.htm
在內核中的某一個進程使用了過多的棧空間時,內核棧就會溢出到thread_info部分,這將導致嚴重的問題(系統重啟),例如,遞歸調用的層次太深;在函數內定義的數據結構太大。
圖:進程中thread_info task_struct和內核棧中的關系
下面我們看一下thread_info的結構體:
PS:(1)flag 用於保存各種特定的進程標志,最重要的兩個是:TIF_SIGPENDING,如果進程有待處理的信號就置位,TIF_NEED_RESCHED表示進程應該需要調度器選擇另一個進程替換本進程執行。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-07/104789p2.htm