Linux :多處理器遇到實時進程和普通進程的程序設(shè)計
失敗是成功之母,這篇文章就是一次真實的失敗調(diào)試記錄。
通過這篇文章,您能深刻體驗到 Linux 系統(tǒng)中下面幾個概念:
實時進程和普通進程的調(diào)度策略;
Linux 中混亂的進程優(yōu)先級是如何計算的;
CPU親和性的測試;
多處理器(SMP)遇到實時進程和普通進程的程序設(shè)計;
道哥的腦袋被門夾了一下的短路經(jīng)歷;
背景知識:Linux 調(diào)度策略
關(guān)于進程的調(diào)度策略,不同的操作系統(tǒng)有不同的整體目標(biāo),因此調(diào)度算法也就各不相同。
這需要根據(jù)進程的類型(計算密集型?IO密集型?)、優(yōu)先級等因素來進行選擇。
對于 Linux x86 平臺來說,一般采用的是 CFS:完全公平調(diào)度算法。
之所以叫做完全公平,是因為操作系統(tǒng)以每個線程占用 CPU 的比率來進行動態(tài)的計算,操作系統(tǒng)希望每一個進程都能夠平均的使用 CPU 這個資源,雨露均沾。
我們在創(chuàng)建一個線程的時候,默認就是這個調(diào)度算法 SCHED_OTHER,默認的優(yōu)先級為 0。
PS: 在 Linux 操作系統(tǒng)中,線程的內(nèi)核對象與進程的內(nèi)核對象(其實就是一些結(jié)構(gòu)體變量)是很類似的,所以線程可以說是輕量級的進程。
在本文中,可以把線程約等于進程,有的地方也可能稱為任務(wù),在不同的語境下有一些不同的慣用說法。
可以這么理解:如果系統(tǒng)中一共有 N 個進程,那么每個進程會得到 1/N 的執(zhí)行機會。每個進程執(zhí)行一段時間之后,就被調(diào)出,換下一個進程執(zhí)行。
如果這個 N 的數(shù)量太大了,導(dǎo)致每個進程剛開始執(zhí)行時,分給它的時間就到了。如果這個時候就進行任務(wù)調(diào)度,那么系統(tǒng)的資源就耗費在進程上下文切換上去了。
因此,操作系統(tǒng)引入了最小粒度,也就是每個進程都有一個最小的執(zhí)行時間保證,稱作時間片。
除了 SCHED_OTHER 調(diào)度算法,Linux 系統(tǒng)還支持兩種實時調(diào)度策略:
1. SCHED_FIFO:根據(jù)進程的優(yōu)先級進行調(diào)度,一旦搶占到 CPU 則一直運行,直達自己主動放棄或被被更高優(yōu)先級的進程搶占;
2. SCHED_RR:在 SCHED_FIFO 的基礎(chǔ)上,加上了時間片的概念。當(dāng)一個進程搶占到 CPU 之后,運行到一定的時間后,調(diào)度器會把這個進程放在 CPU 中,當(dāng)前優(yōu)先級進程隊列的末尾,然后選擇另一個相同優(yōu)先級的進程來執(zhí)行;
本文想測試的就是 SCHED_FIFO 與普通的 SCHED_OTHER 這兩種調(diào)度策略混合的情況。
背景知識:Linux 線程優(yōu)先級
在 Linux 系統(tǒng)中,優(yōu)先級的管理顯得比較混亂,先看下面這張圖:

這張圖表示的是內(nèi)核中的優(yōu)先級,分為兩段。
前面的數(shù)值 0-99 是實時任務(wù),后面的數(shù)值 100-139 是普通任務(wù)。
數(shù)值越低,代表這個任務(wù)的優(yōu)先級越高。
數(shù)值越低,代表這個任務(wù)的優(yōu)先級越高。
數(shù)值越低,代表這個任務(wù)的優(yōu)先級越高。
再強調(diào)一下,以上是從內(nèi)核角度來看的優(yōu)先級。
好了,重點來了:
我們在應(yīng)用層創(chuàng)建線程的時候,設(shè)置了一個優(yōu)先級數(shù)值,這是從應(yīng)用層角度來看的優(yōu)先級數(shù)值。
但是內(nèi)核并不會直接使用應(yīng)用層設(shè)置的這個數(shù)值,而是經(jīng)過了一定的運算,才得到內(nèi)核中所使用的優(yōu)先級數(shù)值(0 ~ 139)。
1. 對于實時任務(wù)
我們在創(chuàng)建線程的時候,可以通過下面這樣的方式設(shè)置優(yōu)先級數(shù)值(0 ~ 99):
struct sched_param param;
param.__sched_priority = xxx;
當(dāng)創(chuàng)建線程函數(shù)進入內(nèi)核層面的時候,內(nèi)核通過下面這個公式來計算真正的優(yōu)先級數(shù)值:
kernel priority = 100 - 1 - param.__sched_priority
如果應(yīng)用層傳入數(shù)值 0,那么在內(nèi)核中優(yōu)先級數(shù)值就是 99(100 - 1 - 0 = 99),在所有實時任務(wù)中,它的優(yōu)先級是最低的。
如果應(yīng)用層傳輸數(shù)值 99,那么在內(nèi)核中優(yōu)先級數(shù)值就是 0(100 - 1 - 99 = 0),在所有實時任務(wù)中,它的優(yōu)先級是最高的。
因此,從應(yīng)用層的角度看,傳輸人優(yōu)先級數(shù)值越大,線程的優(yōu)先級就越高;數(shù)值越小,優(yōu)先級就越低。
與內(nèi)核角度是完全相反的!
2. 對于普通任務(wù)
調(diào)整普通任務(wù)的優(yōu)先級,是通過 nice 值來實現(xiàn)的,內(nèi)核中也有一個公式來把應(yīng)用層傳入的 nice 值,轉(zhuǎn)成內(nèi)核角度的優(yōu)先級數(shù)值:
kernel prifoity = 100 + 20 + nice
nice 的合法數(shù)值是:-20 ~ 19。
如果應(yīng)用層設(shè)置線程 nice 數(shù)值為 -20,那么在內(nèi)核中優(yōu)先級數(shù)值就是 100(100 + 20 + (-20) = 100),在所有的普通任務(wù)中,它的優(yōu)先級是最高的。
如果應(yīng)用層設(shè)置線程 nice 數(shù)值為 19,那么在內(nèi)核中優(yōu)先級數(shù)值就是 139(100 +20 +19 = 139),在所有的普通任務(wù)中,它的優(yōu)先級是最低的。
因此,從應(yīng)用層的角度看,傳輸人優(yōu)先級數(shù)值越小,線程的優(yōu)先級就越高;數(shù)值越大,優(yōu)先級就越低。
與內(nèi)核角度是完全相同的!
背景知識交代清楚了,終于可以進行代碼測試了!
測試代碼說明
注意點:
#define _GNU_SOURCE 必須在 #include <sched.h> 之前定義;
#include <sched.h> 必須在 #include <pthread.h> 之前包含進來;
這個順序能夠保證在后面設(shè)置繼承的 CPU 親和性時,CPU_SET, CEPU_ZERO這兩個函數(shù)能被順利定位到。
// filename: test.c
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
// 用來打印當(dāng)前的線程信息:調(diào)度策略是什么?優(yōu)先級是多少?
void get_thread_info(const int thread_index)
{
int policy;
struct sched_param param;
printf("====> thread_index = %d ", thread_index);
pthread_getschedparam(pthread_self(), &policy, &param);
if (SCHED_OTHER == policy)
printf("thread_index %d: SCHED_OTHER ", thread_index);
else if (SCHED_FIFO == policy)
printf("thread_index %d: SCHED_FIFO ", thread_index);
else if (SCHED_RR == policy)
printf("thread_index %d: SCHED_RR ", thread_index);
printf("thread_index %d: priority = %d ", thread_index, param.sched_priority);
}
// 線程函數(shù),
void *thread_routine(void *args)
{
// 參數(shù)是:線程索引號。四個線程,索引號從 1 到 4,打印信息中使用。
int thread_index = *(int *)args;
// 為了確保所有的線程都創(chuàng)建完畢,讓線程睡眠1秒。
sleep(1);
// 打印一下線程相關(guān)信息:調(diào)度策略、優(yōu)先級。
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
11月7日立即參評>> 【評選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評選
-
11月20日立即報名>> 【免費下載】RISC-V芯片發(fā)展現(xiàn)狀與測試挑戰(zhàn)-白皮書
-
即日-11.25立即下載>>> 費斯托白皮書《柔性:汽車生產(chǎn)未來的關(guān)鍵》
-
11月27日立即報名>> 【工程師系列】汽車電子技術(shù)在線大會
-
11月28日立即下載>> 【白皮書】精準(zhǔn)洞察 無線掌控——283FC智能自檢萬用表
-
12月18日立即報名>> 【線下會議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
推薦專題
- 1 特斯拉工人被故障機器人打成重傷,索賠3.6億
- 2 AI 時代,阿里云想當(dāng)“安卓” ,那誰是“蘋果”?
- 3 拐點已至!匯川領(lǐng)跑工控、埃斯頓份額第一、新時達海爾賦能扭虧為盈
- 4 L3自動駕駛延期,逼出車企技術(shù)自我淘汰
- 5 隱退4年后,張一鳴久違現(xiàn)身!互聯(lián)網(wǎng)大佬正集體殺回
- 6 機器人9月大事件|3家國產(chǎn)機器人沖刺IPO,行業(yè)交付與融資再創(chuàng)新高!
- 7 谷歌“香蕉”爆火啟示:國產(chǎn)垂類AI的危機還是轉(zhuǎn)機?
- 8 7倍機器人大牛股:高管股東套現(xiàn)VS機構(gòu)兇猛抱團,該信誰?
- 9 八部門聯(lián)手放行L3自動駕駛!巨頭開始拼搶萬億市場?
- 10 OpenAI發(fā)布的AI瀏覽器,市場為何反應(yīng)強烈?


分享













