linux 進(jìn)程調(diào)度的實現(xiàn) ---- 進(jìn)程記賬
linux 進(jìn)程調(diào)度的實現(xiàn)一共由四部分組成:
進(jìn)程記賬:就是記錄一個進(jìn)程占用處理器資源的時間長度。既然要記錄,那么就需要存在在一個位置,內(nèi)核說,放在 sched_entity
結(jié)構(gòu)中吧。我們當(dāng)然要聽內(nèi)核的....
至于 sched_entity
這個結(jié)構(gòu)的源碼我就不貼了,但是里面有一個 vruntime
成員變量,這個成員變量可看成 virtual run time
,正確名字是虛擬實時。
這個 vruntime
變量就是用來記錄進(jìn)程已經(jīng)運行的時間長短,或者說,占用處理器已經(jīng)多長時間了。那么這個事件越長就越證明運行的時間越長,就越容易被其他的進(jìn)程擠掉,也就是,其他進(jìn)程容易搶占進(jìn)來。linux 系統(tǒng)對于進(jìn)城的調(diào)度室要看這個變量來采取行動的。那么這個虛擬實時 (時間值) 怎么計算出來的?(這個計算過程就是進(jìn)程記賬的過程),內(nèi)核使用 update_curr()
函數(shù)來實現(xiàn)這個過程。
源碼:
```static void update_curr(struct cfs_rq cfs_rq) { struct sched_entity curr = cfs_rq->curr; u64 now = rq_of(cfs_rq)->clock_task; unsigned long delta_exec; if (unlikely(!curr)) return; /*
這個 update_curr
函數(shù)中存在這么幾個變量和函數(shù)。curr
是一個 sched_entity
結(jié)構(gòu)指針,接收函數(shù)傳進(jìn)的參數(shù)。函數(shù)參數(shù)那個結(jié)構(gòu)是什么? 搞不明白,反正就是吧其中的一個成員復(fù)制 curr
變量。看名字可以知道是指進(jìn)程當(dāng)前的狀態(tài) (當(dāng)然,包括虛擬實時)。接著定義了一個無符號長整型變量 delta_exec
,查一下 delta
有增量的意思,而 exec
是執(zhí)行,那么從名字上看就是值執(zhí)行的增量 (就是時間的增量)。然后,看到 delta_exec
被賦值為 now
和 exec_start
的差值,exec_start
這個可以知道這時開始,現(xiàn)在減開始的,那就是已經(jīng)運行的時間。最后執(zhí)行__update_curr
函數(shù)將當(dāng)前的進(jìn)程賬本,和已經(jīng)運行的時間作為參數(shù)傳如,先來看一下__update_curr()
這個函數(shù):
```static inline void __update_curr(struct cfs_rq cfs_rq,struct sched_entity curr, unsigned long delta_exec) { unsigned long delta_exec_weighted; schedstat_set(curr->statistics.exec_max, max((u64)delta_exec,curr->statistics.exec_max)); curr->sum_exec_runtime += delta_exec; schedstat_add(cfs_rq,exec_clock,delta_exec); delta_exec_weighted = calc_delta_fair(delta_exec,curr); curr->vruntime += delta_exec_weighted; update_min_vruntime(cfs_rq); #if defined CONFIG_SMP && defined CONFIG_FAIR_GROUP_SCHED cfs_rq->load_unacc_exec_time += delta_exec; #endif }
分析一下:傳入的參數(shù) `curr`,`delta_exec`,執(zhí)行了 `calc_delta_fair`,從名字入手,這是計算,計算什么? 增量,還是公平的,那就是加入了權(quán)重,這樣計算出了權(quán)重值。接著在 `vruntime` 上加上權(quán)重,這就是進(jìn)程運行的時間,記賬完成。