詳解Linux內(nèi)核進程調度函數(shù)schedule()的觸發(fā)和執(zhí)行時機
內(nèi)核的調度操作分為觸發(fā)和執(zhí)行兩個部分,觸發(fā)時僅僅設置一下當前進程的TIF_NEED_RESCHED標志,執(zhí)行的時候則是通過schedule()函數(shù)來完成進程的選擇和切換。當前進程的thread_info->flags中TIF_NEED_RESCHED位表示需要調用schedule()函數(shù)進行調度。內(nèi)核在兩種情況下會設置該標志,一個是在時鐘中斷進行周期性的檢查時,另一個是在被喚醒進程的優(yōu)先級比正在運行的進程的優(yōu)先級高時。
周期性地更新當前任務的狀態(tài)時:
定時中斷處理函數(shù)中會調用schedule_tick()用于處理關于調度的周期性檢查和處理,其調用路徑是和時鐘處理有關的tick_periodic()->update_process_times()->scheduler_tick()或者tick_sched_handle()->update_process_times()->scheduler_tick(),主要用于更新就緒隊列的時鐘、CPU負載和當前任務的運行時間統(tǒng)計等,如下所示:
//linux-3.13/kernel/sched/core.c
void scheduler_tick(void)
{
int cpu = smp_processor_id(); //獲取當前cpu編號
struct rq *rq = cpu_rq(cpu); //取得對應cpu的rq(就緒隊列)
struct task_struct *curr = rq->curr; //獲取當前運行的任務
sched_clock_tick();
raw_spin_lock(&rq->lock);
update_rq_clock(rq); //更新隊列時鐘
curr->sched_class->task_tick(rq, curr, 0); //調用當前任務的調度類對應的函數(shù)
update_cpu_load_active(rq); //更新本處理器的負載
raw_spin_unlock(&rq->lock);
perf_event_task_tick();
#ifdef CONFIG_SMP
rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq, cpu); //必要時進行負載均衡
#endif
rq_last_tick_reset(rq);
}
其中curr->sched_class->task_tick(rq, curr, 0);這行代碼調用了當前任務的調度類的task_tick()函數(shù),這個函數(shù)根據(jù)具體情況決定是否需要對當前任務設置TIF_NEED_RESCHED標志,如果需要則最終調用set_tsk_need_resched()設置該標志。需要注意的是,此處僅僅是設置標志而沒有執(zhí)行schedule()函數(shù),在各種系統(tǒng)調用、中斷的返回代碼最后,才會根據(jù)這個標志來決定是否執(zhí)行schedule()函數(shù)。
睡眠的任務被喚醒時:
當睡眠任務所等待的事件到達時,內(nèi)核(例如驅動程序的中斷處理函數(shù))將會調用wake_up()喚醒相關的任務,并最終調用try_to_wake_up()。它完成三件事:將任務重新添加到就緒隊列,將運行標志設置為TASK_RUNNING,如果被喚醒的任務可以搶占當前運行任務則設置當前任務的TIF_NEED_RESCHED標志。
設置了TIF_NEED_RESCHED標志之后,真正調用執(zhí)行schedule()函數(shù)的時機只有兩種,第一種是系統(tǒng)調用或者中斷返回時,根據(jù)TIF_NEED_RESCHED標志決定是否調用schedule()函數(shù)(從效率方面考慮,趁著還在內(nèi)核態(tài)把該處理的事情處理完畢);第二種情況是當前任務因為原因需要睡眠,進程睡眠后立即調用schedule()函數(shù),在內(nèi)核中這種情況也比較多,比如磁盤、網(wǎng)卡等設備驅動程序中。
參考文獻:《Linux技術內(nèi)幕》
PS:剛開始學習Linux內(nèi)核的時候很容易被各種結構體各種概念充斥腦海,一團亂麻。這時候需要把它們各自負責的功能以及之間相互的配合理清楚,推薦這本書??赐辍禠inux內(nèi)核設計與實現(xiàn)》后可以相互比照,效果不錯。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Linux 內(nèi)核通用鏈表學習小結
- Linux中的內(nèi)核鏈表實例詳解
- Linux內(nèi)核鏈表實現(xiàn)過程
- Linux內(nèi)核設備驅動之proc文件系統(tǒng)筆記整理
- Linux內(nèi)核設備驅動之高級字符設備驅動筆記整理
- Linux內(nèi)核設備驅動之Linux內(nèi)核模塊加載機制筆記整理
- Linux內(nèi)核設備驅動地址映射筆記整理
- Linux內(nèi)核設備驅動之Linux內(nèi)核基礎筆記整理
- 增強Linux內(nèi)核中訪問控制安全的方法
- Linux 內(nèi)核空間與用戶空間實現(xiàn)與分析
- Linux內(nèi)核設備驅動之內(nèi)核中鏈表的使用筆記整理
相關文章
apache time_wait連接數(shù)太多問題解決方法
這篇文章主要介紹了apache time_wait連接數(shù)太多問題解決方法,本文使用調整內(nèi)核參數(shù)來解決,需要的朋友可以參考下2014-11-11
詳解虛擬機中CentOS 7 網(wǎng)絡和ssh的配置
這篇文章主要介紹了詳解虛擬機中CentOS 7 網(wǎng)絡和ssh的配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
Linux系統(tǒng)利用cp命令實現(xiàn)強制覆蓋功能的方法
cp命令是我日常學習中經(jīng)常會遇到的一個命令,下面這篇文章主要給大家介紹了關于Linux系統(tǒng)利用cp命令實現(xiàn)強制覆蓋功能的方法,并且給大家簡單的介紹了cp命令的基礎知識,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧。2017-11-11
eclipse3.2.2 + MyEclipse5.5 + Tomcat5.5.27 配置數(shù)據(jù)庫連接池
首先有一點要明確, 我是個新手, 而我所知道的只是一個表面, 根源我并不了解, 目前也不打算去深究. 所以我的方法, 可能只適用于eclipse3.2.2 + MyEclipse5.5 + Tomcat5.5.27 的數(shù)據(jù)庫連接池的配置, 其他版本我無法保證.至少Tomcat 6的admin包還沒出, 所以我的方法肯定不適用于Tomcat 6.2008-10-10
Linux加入windows ad域步驟詳解(winbindsamba方案)
本文主要實驗centos加入windows AD的方法,大家參考使用2013-12-12
使用?DataAnt?監(jiān)控?Apache?APISIX的原理解析
Apache?APISIX?是一個開源的云原生?API?網(wǎng)關,作為?API?網(wǎng)關,它兼具動態(tài)、實時、高性能等特點,提供了負載均衡、動態(tài)上游、灰度發(fā)布、服務熔斷、身份認證、可觀測性等豐富的流量管理功能,這篇文章主要介紹了如何使用?DataAnt?監(jiān)控?Apache?APISIX,需要的朋友可以參考下2022-06-06

