1. 程式人生 > >Linux 相關學習記錄

Linux 相關學習記錄

trac 參考 targe scrip trace max o-k 描述 level

  自己學習的備忘,從筆記轉移過來,後面每一項寫一篇對應的理解文章

內核線程和用戶進程異同記錄

  • 所有進程的內核地址空間則都是一樣的。對於內核進程,由於其始終運行在內核態,所以沒有用戶地址空間,其對應的tast_struct結構體中的mm域也就被賦值為NULL。而堆的概念應該是只存在於進程的用戶地址空間中,所以內核進程是沒有堆一說的。
  • 內核線程只工作在內核態中;而用戶線程則既可以運行在內核態,也可以運行在用戶態; 內核線程沒有用戶空間,所以對於一個內核線程來說,它的0-3G的內存空間是空白的,它的current->mm是空的,與內核使用同一張頁表;而用戶線程則可以看到完整的0-4G內存空間。
  • 殺死內核線程:將該task_struct的狀態標誌位改為 KTHREAD_SHOULD_STOP (調kthread_stop函數),內核線程忽略信號,可見 http://lzz5235.github.io/2015/06/23/how-to-kill-a-kthread.html
  • 守護進程可被信號殺死,父進程ID為1,內核進程父進程ID為2(kthreadd)

內核空間分布和尋址

  • 這裏寫得挺詳細:https://www.cnblogs.com/wuchanming/p/4360277.html

    1. 分 ZONE_DMA(16M), ZONE_NORMAL(16M-896M), ZONE_HIGHMEN(896M-1G)(32位機器), ZONE_NORMAL 和 ZONE_DMA 直接映射物理內存,ZONE_HIGHMEM 通過內核PTE頁面建立映射,臨時用,用完後歸還
    2. 進程尋址空間0-4G,進程只有進入內核態才能訪問3G-4G
    3. 進程通過系統調用進入內核態
    4. 每個進程虛擬空間的3G~4G部分是相同的
    5. 進程從用戶態進入內核態不會引起CR3的改變但會引起堆棧的改變
  • 從用戶態進入內核態過程(門的判斷)

    • 圖參考這裏:https://blog.csdn.net/drshenlei/article/details/4265101
    • CPU特權級切換(CPL):是取的CS寄存器的低兩位,在任何時候,不管CPU內部正在發生什麽,只要看一眼cs中的CPL,你就可以知道此刻的特權級了。
    • 防止用戶態訪問內核態空間
      • 通過分段保護機制,當 RPL 和 CPL 都大於 DPL 時候才可以訪問對應地址的內存
        • CPL是當前進程的權限級別(Current Privilege Level),是當前正在執行的代碼所在的段的特權級,存在於cs寄存器的低兩位。
        • DPL:描述符特權(Descriptor Privilege Level) 存儲在描述符中的權限位,用於描述代碼的所屬的特權等級,也就是代碼本身真正的特權級。一個程序可以使用多個段(Data,Code,Stack)也可以只用一個code段等。正常的情況下,當程序的環境建立好後,段描述符都不需要改變——當然DPL也不需要改變,因此每個段的DPL值是固定。
        • RPL:請求特權級RPL(Request Privilege Level) ,RPL保存在選擇子的最低兩位。RPL說明的是進程對段訪問的請求權限,意思是當前進程想要的請求權限。RPL的值由程序員自己來自由的設置,並不一定RPL>=CPL,但是當RPL<CPL時,實際起作用的就是CPL了,因為訪問時的特權檢查是判斷:EPL=max(RPL,CPL)<=DPL是否成立,所以RPL可以看成是每次訪問時的附加限制,RPL=0時附加限制最小,RPL=3時附加限制最大。所以你不要想通過來隨便設置一個rpl來訪問一個比cpl更內層的段。
  • 用戶態到內核態切換途徑

    1. 系統調用
    2. 中斷
    3. 異常
  • 用戶態進入內核態後進程棧如何切換

    • 詳細代碼參考這裏:https://www.cnblogs.com/justcxtoworld/p/3155741.html
    • 讀取TSS段(保存有用戶棧頂指針和內核棧頂指針)讀取 sp0, ss0
      // TSS 結構定義(參考)
      
      #ifdef CONFIG_X86_32
      /* This is the TSS defined by the hardware. */
      struct x86_hw_tss {
          unsigned short          back_link, __blh;
          unsigned long           sp0;              //當前進程的內核棧頂指針
          unsigned short          ss0, __ss0h;       //當前進程的內核棧段描述符
          unsigned long           sp1;
          /* ss1 caches MSR_IA32_SYSENTER_CS: */
          unsigned short          ss1, __ss1h;
          unsigned long           sp2;
          unsigned short          ss2, __ss2h;
          unsigned long           __cr3;
          unsigned long           ip;
          unsigned long           flags;
          unsigned long           ax;
          unsigned long           cx;
          unsigned long           dx;
          unsigned long           bx;
          unsigned long           sp;            //當前進程用戶態棧頂指針
          unsigned long           bp;
          unsigned long           si;
          unsigned long           di;
          unsigned short          es, __esh;
          unsigned short          cs, __csh;
          unsigned short          ss, __ssh;
          unsigned short          ds, __dsh;
          unsigned short          fs, __fsh;
          unsigned short          gs, __gsh;
          unsigned short          ldt, __ldth;
          unsigned short          trace;
          unsigned short          io_bitmap_base;
      } __attribute__((packed));

Linux 相關學習記錄