Linux內核的一些知識。

一、中斷處理函數裏面爲何不可以進行sleep,信號量操做linux

中斷處理函數裏面不可以進行sleep有比較多的緣由,有如下幾個方面:tcp

  • 臨界區確定是不能進行sleep的,這樣子會致使系統癱瘓。
  • 中斷上下文沒有相應的task_struct,由於 linux進程內核調度是以task_struct爲單位的,因此若是進行sleep的話將沒法進行恢復。但這個不是主要緣由,由於 solaris的中斷上下文有相應的調度描述符IST。(因此這裏來料了,以前有同事說tcp三次握手完成的時候,這個鏈接屬於哪一個pid,在Linux上表現爲空,此時不知道誰持有這個鏈接,多是由於 沒有上下文,但若是在solaris這樣的環境可能就屬於中斷調試 IST的了)
  • 爲了簡單可控,若是容許中斷處理函數中進行sleep的話,可能當前調度優先級比較低的話,那麼它很難被恢復過來,另外,棧空間溢出也是個問題,由於目前中斷棧只有4k。
  • 內核設計緣由:內核設計的諸多因素使得這個沒法實現,好比目前的中斷線是每一個CPU一個,a  sleep ->schedule b -> b sleep -> a(i don't know where my stack is)

 

tasklet應用於異常後半部分的處理,優先級比前半部分要低,它在一些檢查點被觸發調用,一般tasklet也在中斷上下文中被處理,因此和中斷處理程序同樣,不能sleep也不能去調度,不能使用信號量。函數

a.若在中斷中schedule tasklet, 中斷結束後當即運行;
b.若CPU忙,在不在這次中斷後當即運行;
c.不在中斷中shedule tasklet;
d.有軟或硬中斷在運行;
e.從系統調用中返回;(僅當process閒時)
f.從異常中返回;
g.調度程序調度。(ksoftirqd運行時,此時CPU閒)

 

tasklet通常經過wake_up函數來喚醒等待隊列裏面的進程,每一個驅動均可以自定義一個等待隊列DECLARE_WAITQUEUE,進程通常在寫設備的時候調用 wait_event_xxx的方式陷入等待。工具

 

硬中斷觸發時,CPU會將中斷判斷,此時CPU處於臨界區。CPU退出臨界區後能夠開中斷spa

 

咱們可使用vmstat 來查看壓力狀況下的內存狀況,cpu在系統/用戶態的耗時,進程/任務切換的次數等,vmstat 是個好工具。翻譯

但用vmstat的時候,發現 中斷次數比進程/任務切換的次數還要多,因而懷疑軟件中斷是否是不計入中斷計數的。因而去查閱linux/arch/arm/kernel下的熟悉的entry-armv.s,發現軟件中斷的向量跟irq的不同,處理函數也不同,do_IRQ是會進行計數的,而arm_syscall不會進行計數,所以vmstat上面顯示的進程/任務切換的次數比中斷次數還要多。設計

從內核態到用戶態時,須要切換頁表目錄,寄器,以及權限寄存器CPSR。調試

多核心的CPU中,每一個核心應該都要有本身的TLB,這樣子MMU在進行翻譯的時候纔不會混淆,固然,多核心cpu在進行進程切換的時候狀況可能更加複雜一點,還涉及到cache相關的問題,好比cache是以VA(虛擬地址)仍是PA(物理地址)做爲索引的。目前CPU核心看到的地址都是虛擬地址,而Cache,MMU,DMA等設備看到的都是物理地址。code

相關文章
相關標籤/搜索