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