混亂的Linux內核實時線程優先級

背景

Linux會把進程分爲普通進程和實時進程,普通進程採用CFS之類調度算法,而實時進程則是採用SCHED_FIFO或SCHED_RR。

無論優先級高低,實時進程都會優先於SCHED_NORMAL中的所有進程先執行,因爲後者裏面都是普通的非實時進程。

具體可以參看Linux閱碼場早期文章 

宋寶華:關於Linux進程優先級數字混亂的徹底澄清

內核線程的優先級

Linux內核會將大量(並且在不斷增加中)工作放置在內核線程中,這些線程是在內核地址空間中運行的特殊進程。大多數內核線程運行在SCHED_NORMAL類中,必須與普通用戶空間進程爭奪CPU時間。但是有一些內核線程它的開發者們認爲它們非常特殊,應該比用戶空間進程要有更高優先級。因此也會把這些內核線程放到SCHED_FIFO中去。

那麼問題來了,某個內核線程的實時優先級到底該設爲多少呢?

要回答這個問題,不僅需要判斷這個線程相對於所有其他實時線程是否更加重要,還要跟用戶態的實時進程比較誰更重要。這是一個很難回答的問題,更何況在不同的系統和工作模式下這個答案很有可能還會各不相同。

所以一般來說,內核開發人員也就是看心情直接隨便選一個實時優先級。

現在的一些內核實時線程如下:

最近大神Peter Zijlstra又看到有內核開發者隨便給內核線程設置優先級,終於看不下去了, 指責這種把內核線程放入SCHED_FIFO的做法毫無意義:

"the kernel has no clue what actual priority it should use for various things, so it is useless (or worse, counter productive) to even try"

所以他發了一個系列[PATCH 00/23] sched: Remove FIFO priorities from modules 把設置內核線程優先級的接口乾脆都給刪了,省得再有人瞎搞。

這個系列Patch(點擊閱讀原文可直達)主要做了下面幾件事情:

  • 刪除了原有的sched_setschedule() / sched_setattr() 接口

  • 增加了

    • sched_set_fifo(p)

    • sched_set_fifo_low(p)

    • sched_set_normal(p, nice)

其中調用sched_set_fifo()會將指定進程放到SCHED_FIFO類中,其優先級爲50——這只是min和max之間的一半位置。

對於需求不那麼迫切的線程,sched_set_fifo_low()將優先級設置爲最低值(1)。

而調用sched_set_normal()會將線程返回給定好的值SCHED_NORMAL類。

通過只留下這三個接口可以避免開發者們再不停地去隨機選取內核線程優先級,因爲這樣本來毫無意義,當然如果需要的話系統管理員還是可以按需調整不同進/線程的優先級。

到目前爲止,這個系列Patch已經有不少得到Reviewed-by,相信如果合入後,內核線程混亂的優先級狀況會得到持續改善。

Reference

https://lwn.net/Articles/818388/

宋寶華:關於Linux進程優先級數字混亂的徹底澄清

小討論:

內核線程和workqueue都可以用來把內核工作推遲執行,你知道他們有什麼差異嗎? 實際開發中你一般選擇用哪種更多呢,歡迎留言討論~

(END)

更多精彩,盡在"Linux閱碼場",掃描下方二維碼關注

您的鼓勵是我們前行的動力

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章