歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核Crash分析

Linux內核Crash分析

日期:2017/3/1 9:41:41   编辑:Linux內核

在工作中經常會遇到一些內核crash的情況,本文就是根據內核出現crash後的打印信息,對其進行了分析,使用的內核版本為:Linux2.6.32。

每一個進程的生命周期內,其生命周期的范圍為幾毫秒到幾個月。一般都是和內核有交互,例如用戶空間程序使用系統調用進入內核空間。這時使用的不再是用戶空間的棧空間,使用對應的內核棧空間。對每一個進程來說,Linux內核都會把兩個不同的數據結構緊湊的存放在一個單獨為進程分配的存儲空間中:一個是內核態的進程堆棧,另一個是緊挨進程描述符的數據結構thread_info,叫線程描述符。內核的堆棧大小一般為8KB,也就是8192個字節,占用兩個頁。在Linux-2.6.32內核中thread_info.h文件中有對內核堆棧的定義:

  1. #define THREAD_SIZE 8192

在Linux內核中使用下面的聯合結構體表示一個進程的線程描述符和內核棧,在內核中文件include/linux/sched.h。

  1. union thread_union {
  2. struct thread_info thread_info;
  3. unsignedlong stack[THREAD_SIZE/sizeof(long)];
  4. };

該結構是一個聯合體,我們在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的結構體:

  1. struct thread_info {
  2. unsignedlong flags;/* 底層標志,*/
  3. int preempt_count;/* 0 => 可搶占, <0 => bug */
  4. mm_segment_t addr_limit;/* 進程地址空間 */
  5. struct task_struct *task;/*當前進程的task_struct指針 */
  6. struct exec_domain *exec_domain;/*執行區間 */
  7. __u32 cpu;/* 當前cpu */
  8. __u32 cpu_domain;/* cpu domain */
  9. struct cpu_context_save cpu_context;/* cpu context */
  10. __u32 syscall;/* syscall number */
  11. __u8 used_cp[16];/* thread used copro */
  12. unsignedlong tp_value;
  13. struct crunch_state crunchstate;
  14. union fp_state fpstate __attribute__((aligned(8)));
  15. union vfp_state vfpstate;
  16. #ifdef CONFIG_ARM_THUMBEE
  17. unsignedlong thumbee_state;/* ThumbEE Handler Base register */
  18. #endif
  19. struct restart_block restart_block;/*用於實現信號機制*/
  20. };

PS:(1)flag 用於保存各種特定的進程標志,最重要的兩個是:TIF_SIGPENDING,如果進程有待處理的信號就置位,TIF_NEED_RESCHED表示進程應該需要調度器選擇另一個進程替換本進程執行。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-07/104789p2.htm

Copyright © Linux教程網 All Rights Reserved