Linux--進(jìn)程調(diào)度
1 結(jié)構(gòu)

2? 優(yōu)先級
0--99 :實(shí)時優(yōu)先級
100--139 : 普通優(yōu)先級
普通優(yōu)先級nice值:-20--+19
優(yōu)先級調(diào)整:
p->prio = effective_prio(p);
static int effective_prio(struct task_struct *p)
{
p->normal_prio = normal_prio(p);
/*如果實(shí)時優(yōu)先級或者提高到實(shí)時優(yōu)先級,則保持優(yōu)先級不變,否則返回普通優(yōu)先級*/
if (!rt_prio(p->prio))
return p->normal_prio;
return p->prio;
}
動態(tài)優(yōu)先級:task_struct->prio
普通優(yōu)先級:task_struct->normal_prio
靜態(tài)優(yōu)先級:task_struct->static_prio? ? ?//static_prio計算起點(diǎn)
nice權(quán)重:/* ? 0 */ ? ? ?1024, ? ? ? 820, ? ? ? 655, ? ? ? 526, ? ? ? 423,
1>A B兩個進(jìn)程,nice都為0 則每個進(jìn)程的份額1024/(1024+1024)=50%,則即每個進(jìn)程得到cpu的時間各50%.
2>A ,B兩個進(jìn)程,A的nice=0,B的nice=1;
則A 1024/(1024+820)=0.55%,B 820/(1024+820)=0.45%,這樣產(chǎn)生10%的差額

調(diào)度類:
extern const struct sched_class stop_sched_class;
extern const struct sched_class dl_sched_class;
extern const struct sched_class rt_sched_class;//實(shí)時調(diào)度
extern const struct sched_class fair_sched_class;//完全公平調(diào)度
extern const struct sched_class idle_sched_class;
調(diào)度相關(guān)成員:
struct task_struct {?
int prio;//動態(tài)優(yōu)先級
//靜態(tài)優(yōu)先級,進(jìn)程啟動時分配的優(yōu)先級,,可以用Nice和sched_setscheduler系統(tǒng)調(diào)用修改,否則一直保持恒定
int static_prio;
int normal_prio;//動態(tài)優(yōu)先級
//實(shí)時優(yōu)先級 0-99? 值越大優(yōu)先級越高
unsigned int rt_priority;
//調(diào)度類
const struct sched_class *sched_class;
//調(diào)度實(shí)體
struct sched_entity se;
//實(shí)時調(diào)度實(shí)體
struct sched_rt_entity rt;
//idle 調(diào)度實(shí)體
struct sched_dl_entity dl;
unsigned int policy;//調(diào)度策略 SCHED_NORMAL? SCHED_BATCH SCHED_IDLE SCHED_RR SCHED_FIFO
int nr_cpus_allowed;//限制進(jìn)程可以再哪個處理器上運(yùn)行
struct sched_info sched_info;//調(diào)度信息
...
}
調(diào)度類:
struct sched_class {
const struct sched_class *next;//鏈表指針,當(dāng)系統(tǒng)中有多個調(diào)度類,安裝優(yōu)先級排除排成一個鏈表
//進(jìn)程加入到執(zhí)行隊(duì)列中,即將調(diào)度實(shí)體放入紅黑樹中
void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
//放棄CPU執(zhí)行權(quán),實(shí)際上該函數(shù)執(zhí)行先出對后入隊(duì),它直接將調(diào)度實(shí)體放在紅黑樹的最右端
void (*yield_task)? ?(struct rq *rq);
bool (*yield_to_task)(struct rq *rq, struct task_struct *p, bool preempt);
//用于檢查當(dāng)前進(jìn)程是否可被新進(jìn)程搶占
void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags);
struct task_struct *(*pick_next_task)(struct rq *rq);
//選擇下一個要運(yùn)行的進(jìn)程
void (*put_prev_task)(struct rq *rq, struct task_struct *p);
//將進(jìn)程回放到運(yùn)行隊(duì)列中
void (*set_next_task)(struct rq *rq, struct task_struct *p, bool first);
...
就緒類:
struct rq {
raw_spinlock_t lock;
unsigned int nr_running;//隊(duì)列上可以運(yùn)行的進(jìn)程數(shù)目
unsigned long nr_load_updates;
u64 nr_switches;
struct cfs_rq cfs;//cfs調(diào)度
struct rt_rq rt;//實(shí)時調(diào)度
struct dl_rq dl;//空閑調(diào)度
unsigned long nr_uninterruptible;
struct task_struct __rcu *curr;
struct task_struct *idle;
struct task_struct *stop;
unsigned long next_balance;
struct mm_struct *prev_mm;
調(diào)用實(shí)體:
//task_struct中內(nèi)嵌sched_entity 所以進(jìn)程是可調(diào)度實(shí)體
struct sched_entity {
struct load_weight load;//制定了權(quán)重,決定了各個實(shí)體占隊(duì)列總負(fù)荷的比例
unsigned long runnable_weight;
struct rb_node run_node;//紅黑樹節(jié)點(diǎn),使得實(shí)體可以在紅黑樹上排序
struct list_head group_node;
unsigned int on_rq;//該實(shí)體是否 在就緒隊(duì)列上接收調(diào)度
u64 exec_start;//更新到當(dāng)前時間
u64 sum_exec_runtime;//差值
u64 vruntime;//虛擬時鐘上流逝的時間
u64 prev_sum_exec_runtime;//進(jìn)程被撤銷CPU時,將sum_exec_runtime保存到prev_sum_exec_runtime,而sum_exec_runtime持續(xù)增長
...
}