Linux 進(jìn)程調(diào)度器是一個(gè)進(jìn)程嗎? 還是一個(gè)策略
Linux 進(jìn)程調(diào)度器(scheduler)不是一個(gè)進(jìn)程,而是一套內(nèi)核中的調(diào)度策略和相關(guān)代碼的總稱。
1. 調(diào)度器不是進(jìn)程
- 調(diào)度器不是一個(gè)進(jìn)程,它沒有自己的 PID,也不會(huì)出現(xiàn)在 ps/top 等進(jìn)程列表中。
- 它是內(nèi)核代碼的一部分,始終運(yùn)行在內(nèi)核空間,由內(nèi)核負(fù)責(zé)調(diào)用和維護(hù)。
2. 調(diào)度器是什么?
- 調(diào)度器(scheduler)是一套算法和實(shí)現(xiàn)代碼,決定了在任意時(shí)刻哪個(gè)進(jìn)程/線程可以獲得 CPU 運(yùn)行。
- 它管理所有進(jìn)程/線程的狀態(tài)(就緒、運(yùn)行、阻塞等),并根據(jù)優(yōu)先級(jí)、調(diào)度策略等因素做出調(diào)度決策。
3. 調(diào)度器的實(shí)現(xiàn)位置
- 主要代碼在 Linux 源碼的
kernel/sched/目錄下,比如:-
core.c(核心框架) -
fair.c(CFS 完全公平調(diào)度器,普通進(jìn)程用) -
rt.c(實(shí)時(shí)調(diào)度器) -
deadline.c(實(shí)時(shí) deadline 調(diào)度器)
-
- 這些文件實(shí)現(xiàn)了不同的調(diào)度策略,比如 CFS、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE 等。
4. 調(diào)度器的工作方式
- 每當(dāng)需要切換進(jìn)程(比如時(shí)間片用完、進(jìn)程阻塞/喚醒、系統(tǒng)調(diào)用等),內(nèi)核會(huì)調(diào)用調(diào)度器的相關(guān)函數(shù)(如
schedule())。 - 調(diào)度器會(huì)根據(jù)當(dāng)前所有可運(yùn)行進(jìn)程的狀態(tài)和優(yōu)先級(jí),選擇下一個(gè)要運(yùn)行的進(jìn)程。
5. 調(diào)度策略的含義
-
調(diào)度策略是調(diào)度器內(nèi)部支持的不同算法,比如:
- SCHED_OTHER(CFS,普通進(jìn)程)
- SCHED_FIFO、SCHED_RR(實(shí)時(shí)進(jìn)程)
- SCHED_DEADLINE(實(shí)時(shí) deadline)
- 用戶和程序可以通過系統(tǒng)調(diào)用(如
sched_setscheduler)選擇進(jìn)程的調(diào)度策略。
6. 總結(jié)
Linux 進(jìn)程調(diào)度器不是進(jìn)程,而是內(nèi)核中的一套調(diào)度算法和實(shí)現(xiàn)代碼。它負(fù)責(zé)管理和切換所有進(jìn)程的運(yùn)行,是操作系統(tǒng)的核心組成部分。
Linux 系統(tǒng)運(yùn)行過程中是有多個(gè)調(diào)度器在工作嗎?
你的問題是:“Linux 系統(tǒng)運(yùn)行過程中是有多個(gè)調(diào)度器在工作嗎?”
簡(jiǎn)短回答:
不是有多個(gè)調(diào)度器在工作,而是有一個(gè)統(tǒng)一的調(diào)度框架,支持多種調(diào)度策略。所有 CPU(核)都用同一套調(diào)度器代碼,但可以為不同進(jìn)程/線程選擇不同的調(diào)度策略。
1. 調(diào)度器的整體結(jié)構(gòu)
- Linux 只有一個(gè)調(diào)度器框架(scheduler framework),它是內(nèi)核的一部分,負(fù)責(zé)所有進(jìn)程/線程的調(diào)度。
- 這個(gè)調(diào)度器框架支持多種調(diào)度策略(如 CFS、實(shí)時(shí)、deadline),這些策略在同一個(gè)調(diào)度器框架下協(xié)同工作。
2. 多核系統(tǒng)的調(diào)度
- 在多核(SMP)系統(tǒng)中,每個(gè) CPU(核)都有自己的就緒隊(duì)列(runqueue),但調(diào)度器的實(shí)現(xiàn)代碼是同一套。
- 每個(gè) CPU 都會(huì)獨(dú)立運(yùn)行調(diào)度器的調(diào)度邏輯(比如定時(shí)器中斷觸發(fā) schedule()),但用的都是同樣的調(diào)度器代碼。
- 進(jìn)程/線程可以在不同 CPU 之間遷移(load balance),這也是調(diào)度器負(fù)責(zé)的。
3. 多種調(diào)度策略的協(xié)作
-
調(diào)度器支持多種調(diào)度策略,比如:
- CFS(普通進(jìn)程,SCHED_OTHER)
- 實(shí)時(shí)調(diào)度(SCHED_FIFO、SCHED_RR)
- Deadline 調(diào)度(SCHED_DEADLINE)
- 每個(gè)進(jìn)程/線程可以選擇自己的調(diào)度策略,調(diào)度器會(huì)根據(jù)優(yōu)先級(jí)和策略統(tǒng)一管理。
- 例如,實(shí)時(shí)進(jìn)程優(yōu)先于普通進(jìn)程,deadline 進(jìn)程有自己的調(diào)度規(guī)則。
4. 源碼結(jié)構(gòu)
- 主要在
kernel/sched/目錄下,不同文件實(shí)現(xiàn)不同策略,但都屬于同一個(gè)調(diào)度器框架。 - 例如:
-
fair.c:CFS -
rt.c:實(shí)時(shí) -
deadline.c:deadline -
core.c:調(diào)度器核心框架
-
5. 總結(jié)
- Linux 只有一個(gè)調(diào)度器框架,但支持多種調(diào)度策略。
- 所有 CPU 都用同一套調(diào)度器代碼,每個(gè)進(jìn)程/線程可以選擇不同的調(diào)度策略。
- 不是“多個(gè)調(diào)度器”并行工作,而是“一個(gè)調(diào)度器支持多種策略”。
一個(gè)進(jìn)程是怎么選擇不同的調(diào)度策略的
非常好的問題!
一個(gè)進(jìn)程如何選擇不同的調(diào)度策略?
這涉及到用戶空間和內(nèi)核空間的接口,以及調(diào)度器的實(shí)現(xiàn)。下面詳細(xì)解答:
1. 什么是調(diào)度策略?
Linux 支持多種調(diào)度策略(policy),常見的有:
-
SCHED_OTHER(也叫SCHED_NORMAL,CFS,普通進(jìn)程) -
SCHED_FIFO(實(shí)時(shí),先進(jìn)先出) -
SCHED_RR(實(shí)時(shí),時(shí)間片輪轉(zhuǎn)) -
SCHED_BATCH(批處理) -
SCHED_IDLE(空閑進(jìn)程) -
SCHED_DEADLINE(實(shí)時(shí) deadline)
2. 進(jìn)程如何選擇/更改調(diào)度策略?
A. 通過系統(tǒng)調(diào)用
- 主要有兩個(gè)相關(guān)系統(tǒng)調(diào)用:
-
sched_setscheduler(pid, policy, ¶m)
設(shè)置指定進(jìn)程的調(diào)度策略和優(yōu)先級(jí) -
sched_setparam(pid, ¶m)
只設(shè)置優(yōu)先級(jí),不改變策略
-
示例代碼:
#include <sched.h>
struct sched_param param;
param.sched_priority = 80; // 1~99 for real-time
sched_setscheduler(0, SCHED_FIFO, ¶m); // 把當(dāng)前進(jìn)程設(shè)置為實(shí)時(shí)FIFO策略
B. 通過命令行工具
-
chrt命令可以在 shell 下設(shè)置進(jìn)程的調(diào)度策略和優(yōu)先級(jí):
chrt -f -p 80 1234 # 把 PID 1234 設(shè)置為 SCHED_FIFO,優(yōu)先級(jí)80
chrt -r 50 myprog # 以 SCHED_RR 策略、優(yōu)先級(jí)50啟動(dòng) myprog
-
nice/renice只能調(diào)整普通進(jìn)程的 nice 值,不能切換到實(shí)時(shí)策略。
3. 新進(jìn)程的策略繼承
-
fork()出來的子進(jìn)程會(huì)繼承父進(jìn)程的調(diào)度策略和優(yōu)先級(jí)。 -
exec()不會(huì)改變調(diào)度策略。
4. 內(nèi)核如何實(shí)現(xiàn)?
- 每個(gè)進(jìn)程的
task_struct結(jié)構(gòu)體里有policy字段,記錄當(dāng)前調(diào)度策略。 - 系統(tǒng)調(diào)用
sched_setscheduler會(huì)檢查權(quán)限(只有 root 可以設(shè)置實(shí)時(shí)策略),然后修改policy字段,并調(diào)整優(yōu)先級(jí)。 - 調(diào)度器根據(jù)
policy字段決定該進(jìn)程用哪種調(diào)度算法。
5. 權(quán)限限制
- 只有 root 用戶才能把進(jìn)程設(shè)置為實(shí)時(shí)調(diào)度(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE),普通用戶只能用 SCHED_OTHER、SCHED_BATCH、SCHED_IDLE。
6. 查看進(jìn)程的調(diào)度策略
ps -eo pid,cmd,policychrt -p <pid>
7. 總結(jié)
進(jìn)程可以通過系統(tǒng)調(diào)用(如 sched_setscheduler)或 chrt 命令選擇/更改自己的調(diào)度策略。調(diào)度策略決定了進(jìn)程在調(diào)度器中的優(yōu)先級(jí)和調(diào)度方式。
像在 shell 中運(yùn)行的進(jìn)程, 調(diào)度策略是怎么被選擇的
非常好的問題!
在 shell(比如 bash、zsh)中直接運(yùn)行的進(jìn)程,它的調(diào)度策略是怎么被選擇的?
1. 默認(rèn)調(diào)度策略是什么?
- 在 shell 中直接運(yùn)行的進(jìn)程(比如你輸入
ls、vim、python等), -
默認(rèn)使用的是
SCHED_OTHER(也叫SCHED_NORMAL,即 CFS 完全公平調(diào)度器)。 - 這種策略適用于絕大多數(shù)普通用戶進(jìn)程。
2. 為什么是 SCHED_OTHER?
- shell 啟動(dòng)新進(jìn)程時(shí),調(diào)用的是
fork()+exec()。 - 新進(jìn)程會(huì)繼承父進(jìn)程(即 shell 本身)的調(diào)度策略。
- shell 進(jìn)程本身也是普通用戶進(jìn)程,默認(rèn)就是
SCHED_OTHER。 - 所以,你在 shell 里運(yùn)行的所有普通命令,默認(rèn)都是 SCHED_OTHER。
3. 優(yōu)先級(jí)(nice 值)如何確定?
- 默認(rèn) nice 值是 0(可以用
nice命令調(diào)整)。 - 你可以用
nice -n 10 command讓進(jìn)程以較低優(yōu)先級(jí)運(yùn)行。 - 但這不會(huì)改變調(diào)度策略,仍然是 SCHED_OTHER,只是優(yōu)先級(jí)(nice)變了。
4. 如何在 shell 里改變調(diào)度策略?
- 普通用戶不能直接用 shell 改為實(shí)時(shí)調(diào)度策略(SCHED_FIFO、SCHED_RR),需要 root 權(quán)限。
- 可以用
chrt命令(需要 root):
sudo chrt -f 80 ./myprog # 以 SCHED_FIFO 策略、優(yōu)先級(jí)80運(yùn)行
- 也可以用
nice調(diào)整普通進(jìn)程的優(yōu)先級(jí):
nice -n 10 ./myprog # 以較低優(yōu)先級(jí)運(yùn)行
5. 查看當(dāng)前進(jìn)程的調(diào)度策略
- 用
ps -eo pid,cmd,policy或chrt -p <pid>可以看到進(jìn)程的調(diào)度策略。
6. 總結(jié)
在 shell 中直接運(yùn)行的進(jìn)程,默認(rèn)調(diào)度策略是 SCHED_OTHER(CFS),優(yōu)先級(jí)由 nice 值決定。只有通過 chrt(需要 root)等方式才能讓進(jìn)程使用實(shí)時(shí)調(diào)度策略。
Linux 調(diào)度策略有多個(gè), 那 cpu 輪轉(zhuǎn)的時(shí)候具體選擇哪個(gè)策略呢?
Linux 支持多種調(diào)度策略(如 SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE),那 CPU 輪轉(zhuǎn)(調(diào)度)時(shí),內(nèi)核是如何選擇用哪個(gè)策略的?
1. 調(diào)度器的“分層”選擇機(jī)制
Linux 調(diào)度器采用分層優(yōu)先級(jí)的方式來管理不同策略的進(jìn)程:
A. 實(shí)時(shí)優(yōu)先,普通次之
-
實(shí)時(shí)進(jìn)程(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)
- 優(yōu)先級(jí)最高。只要有可運(yùn)行的實(shí)時(shí)進(jìn)程,調(diào)度器一定優(yōu)先調(diào)度實(shí)時(shí)進(jìn)程。
- 多個(gè)實(shí)時(shí)進(jìn)程之間,再根據(jù)各自的策略和優(yōu)先級(jí)排序。
-
普通進(jìn)程(SCHED_OTHER、SCHED_BATCH、SCHED_IDLE)
- 只有在沒有可運(yùn)行的實(shí)時(shí)進(jìn)程時(shí),調(diào)度器才會(huì)選擇普通進(jìn)程。
- 普通進(jìn)程之間再用 CFS(完全公平調(diào)度器)等算法排序。
2. 調(diào)度器的選擇流程(簡(jiǎn)化版)
每當(dāng)需要調(diào)度(比如時(shí)間片用完、進(jìn)程阻塞/喚醒、系統(tǒng)調(diào)用等),調(diào)度器會(huì):
-
檢查所有可運(yùn)行的實(shí)時(shí)進(jìn)程隊(duì)列
- 如果有 SCHED_DEADLINE 進(jìn)程,先選 deadline 最早的。
- 否則,檢查 SCHED_FIFO/SCHED_RR 隊(duì)列,按優(yōu)先級(jí)(1~99)從高到低選擇。
- SCHED_FIFO:同優(yōu)先級(jí)下先到先服務(wù),直到主動(dòng)讓出 CPU。
- SCHED_RR:同優(yōu)先級(jí)下輪流分配時(shí)間片。
-
如果沒有可運(yùn)行的實(shí)時(shí)進(jìn)程
- 選擇普通進(jìn)程隊(duì)列(CFS),按 vruntime(虛擬運(yùn)行時(shí)間)最小的進(jìn)程調(diào)度。
- SCHED_BATCH、SCHED_IDLE 進(jìn)程優(yōu)先級(jí)更低,只有系統(tǒng)空閑時(shí)才會(huì)被調(diào)度。
3. 多核系統(tǒng)的情況
- 每個(gè) CPU 都有自己的就緒隊(duì)列,但調(diào)度器的選擇邏輯是一樣的。
- 進(jìn)程可以在不同 CPU 之間遷移,調(diào)度器會(huì)做負(fù)載均衡。
4. 源碼入口
- 主要在
kernel/sched/core.c的pick_next_task()函數(shù)。 - 偽代碼邏輯如下:
if (有可運(yùn)行的 SCHED_DEADLINE 進(jìn)程)
選 deadline 最早的
else if (有可運(yùn)行的 SCHED_FIFO/SCHED_RR 進(jìn)程)
選優(yōu)先級(jí)最高的實(shí)時(shí)進(jìn)程
else
選 CFS 隊(duì)列中 vruntime 最小的普通進(jìn)程
5. 總結(jié)
CPU 輪轉(zhuǎn)時(shí),Linux 調(diào)度器總是優(yōu)先選擇實(shí)時(shí)策略(SCHED_DEADLINE > SCHED_FIFO/RR)的進(jìn)程。如果沒有實(shí)時(shí)進(jìn)程,才會(huì)選擇普通策略(SCHED_OTHER/CFS)的進(jìn)程。每種策略內(nèi)部再按各自規(guī)則排序。