Linux :多處理器遇到實時進程和普通進程的程序設計
問題很明顯:為什么 4 個線程為什么被同時執行了?
1 號和 2 號這兩個線程應該被優先執行啊,因為它倆是實時任務!
怎么結果是這個樣子?徹底凌亂了,一點都不符合預期!
想不出個所以然,只能求助網絡!但是沒有找到有價值的線索。
其中有一個信息涉及到 Linux 系統的調度策略,這里記錄一下。
Linux 系統中,為了不讓實時任務徹底占據 CPU 資源,會讓普通任務有很小的一段時間縫隙來執行。
在目錄 /proc/sys/kernel 下面,有 2 個文件,用來限制實時任務占用 CPU 的時間:
sched_rt_runtime_us: 默認值 950000sched_rt_period_us: 默認值 1000000
意思是:在 1000000 微秒(1秒)的周期內,實時任務占用 950000 微秒(0.95秒),剩下的 0.05 秒留給普通任務。
如果沒有這個限制的話,假如某個 SCHED_FIFO 任務的優先級特別高,恰巧出了 bug:一直占據 CPU 資源不放棄,那么我們壓根就沒有機會來 kill 掉這個實時任務,因為此時系統無法調度其他的任何進程來執行。
而有了這個限制呢,我們就可以利用這 0.05 秒的執行時間,來 kill 掉有 bug 的那個實時任務。
回到正題:資料上說,如果實時任務沒有被優先調度,可以把這個時間限制刪掉就可以了。方法是:
sysctl -w kernel.sched_rt_runtime_us=-1
我照做之后,依舊無效!
換一臺虛擬機,繼續測試
難道是電腦環境的問題嗎?于是,把測試代碼放到另一臺筆記本里的虛擬機 Ubuntu14.04 里測試。
編譯的時候,有一個小問題,提示錯誤:
error: ‘for’ loop initial declarations are only allowed in C99 mode
只要把編譯指令中添加 C99 標準就可以了:
gcc -o test test.c -lpthread -std=c99
執行程序,打印信息如下:
====> thread_index = 2
====> thread_index = 1
thread_index 1: SCHED_FIFO
thread_index 1: priority = 51
thread_index 2: SCHED_FIFO
thread_index 2: priority = 52
thread_index 1: num = 0
thread_index 2: num = 0
thread_index 2: num = 1
thread_index 1: num = 1
thread_index 2: num = 2
thread_index 1: num = 2
thread_index 2: num = 3
thread_index 1: num = 3
thread_index 2: num = 4
thread_index 1: num = 4
thread_index 2: num = 5
thread_index 1: num = 5
thread_index 2: num = 6
thread_index 1: num = 6
thread_index 2: num = 7
thread_index 1: num = 7
thread_index 2: num = 8
thread_index 1: num = 8
thread_index 2: num = 9
thread_index 2: exit
====> thread_index = 4
thread_index 4: SCHED_OTHER
thread_index 4: priority = 0
thread_index 1: num = 9
thread_index 1: exit
====> thread_index = 3
thread_index 3: SCHED_OTHER
thread_index 3: priority = 0
thread_index 3: num = 0
thread_index 4: num = 0
thread_index 3: num = 1
thread_index 4: num = 1
thread_index 3: num = 2
thread_index 4: num = 2
thread_index 3: num = 3
thread_index 4: num = 3
thread_index 3: num = 4
thread_index 4: num = 4
thread_index 3: num = 5
thread_index 4: num = 5
thread_index 3: num = 6
thread_index 4: num = 6
thread_index 3: num = 7
thread_index 4: num = 7
thread_index 3: num = 8
thread_index 4: num = 8
thread_index 3: num = 9
thread_index 3: exit
thread_index 4: num = 9
thread_index 4: exit
1 號和 2 號線程同時執行,完畢之后,再 3 號和 4 號線程同時執行。
但是這同樣也不符合預期:2 號線程的優先級比 1 號線程高,應該優先執行才對!
不知道應該怎么查這個問題了,想不出思路,只好請教 Linux 內核的大神,建議檢查一下內核版本。
這時,我才想起來在 Ubuntu16.04 這臺虛擬機上因為某種原因,降過內核版本。
往這個方向去排查了一下,最后確認也不是內核版本的差異導致的問題。
比較結果,尋找差異
只好再回過頭來看一下這兩次次打印信息的差異:
工作電腦里的 Ubuntu16.04 中:4 個線程同時調度執行,調度策略和優先級都沒有起作用;
筆記本里的 Ubuntu14.04 中:1 號和 2 號實時任務被優先執行了,說明調度策略起作用了,但是優先級沒有起作用;
突然, CPU 的親和性從腦袋里蹦了出來!
緊接著立馬感覺到問題出在哪里了:這TMD大概率就是多核引起的問題!
于是我把這 4 個線程都綁定到 CPU0 上去,也就是設置 CPU 親和性。
在線程入口函數 thread_routine 的開頭,增加下面的代碼:
cpu_set_t mask;
int cpus = sysconf(_SC_NPROCESSORS_CONF);
CPU_ZERO(&mask);
CPU_SET(0, &mask);
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)
{
printf("set thread affinity failed! ");
}
然后繼續在 Ubuntu16.04 虛擬機中驗證,打印信息很完美,完全符合預期:
====> thread_index = 1
====> thread_index = 2
thread_index 2: SCHED_FIFO
thread_index 2: priority = 52
thread_index 2: num = 0
。。。
thread_index 2: num = 9
thread_index 2: exit
thread_index 1: SCHED_FIFO
thread_index 1: priority = 51
thread_index 1: num = 0
。。。
thread_index 1: num = 9
thread_index 1: exit
====> thread_index = 3
thread_index 3: SCHED_OTHER
thread_index 3: priority = 0
====> thread_index = 4
thread_index 4: SCHED_OTHER
thread_index 4: priority = 0
thread_index 3: num = 0
thread_index 4: num = 0
。。。
thread_index 4: num = 8
thread_index 3: num = 8
thread_index 4: num = 9
thread_index 4: exit
thread_index 3: num = 9
thread_index 3: exit
至此,問題真相大白:就是多核處理器導致的問題!
而且這兩臺測試的虛擬機,安裝的時候分配的 CPU 核心是不同的,所以才導致打印結果的不同。
真相大白
最后,再確認一下這 2 個虛擬機中的 CPU 信息:
Ubuntu 16.04 中 cpuinfo 信息:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 158
model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
stepping : 10
cpu MHz : 2807.996
cache size : 9216 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
。。。其他信息
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 158
model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
stepping : 10
cpu MHz : 2807.996
cache size : 9216 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
。。。其他信息
processor : 2
vendor_id : GenuineIntel
cpu family : 6
model : 158
model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
stepping : 10
cpu MHz : 2807.996
cache size : 9216 KB
physical id : 0
siblings : 4
core id : 2
cpu cores : 4
。。。其他信息
processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 158
model name : Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
stepping : 10
cpu MHz : 2807.996
cache size : 9216 KB
physical id : 0
siblings : 4
core id : 3
cpu cores : 4
。。。
其他信息
在這臺虛擬機中,正好有 4 個核心,而我的測試代碼正好也創建了 4 個線程,于是每個核心被分配一個線程,一個都不閑著,同時執行。
因此打印信息中顯示 4 個線程是并行執行的。
這個時候,什么調度策略、什么優先級,都不起作用了!(準確的說:調度策略和優先級,在線程所在的那個 CPU 中是起作用的)
如果我在測試代碼中,一開始就創建 10 個線程,很可能會更快發現問題!
再來看看筆記本電腦里虛擬機 Ubuntu14.04 的 CPU 信息:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 142
model name : Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
stepping : 9
microcode : 0x9a
cpu MHz : 2304.000
cache size : 4096 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
。。。其他信息
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 142
model name : Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
stepping : 9
microcode : 0x9a
cpu MHz : 2304.000
cache size : 4096 KB
physical id : 0
siblings : 2
core id : 1
cpu cores : 2
。。。其他信息
在這臺虛擬機中,有 2 個核心,于是 2 個實時任務 1 號和 2 號被優先執行(因為是 2 個核心同時執行,所以這 2 個任務的優先級也就沒什么意義了),結束之后,再執行 3 號和 4 號線程。
再思考一下
這一圈測試下來,真的想用鍵盤敲自己的腦袋,怎么就沒有早點考慮到多核的因素呢?!
深層的原因:
之前的很多項目,都是 ARM、mips、STM32等單核情況,思維定式讓我沒有早點意識到多核這個屏體因素;
做過的一些 x86 平臺項目,并沒有涉及到實時任務這樣的要求。一般都是使用系統默認的調度策略,這也是 Linux x86 作為通用電腦,在調度策略上所關注的重要指標:讓每一個任務都公平的使用 CPU 資源。
隨著 x86 平臺在工控領域的逐漸應用,實時性問題就顯得更突出、更重要了。
所以才有了 Windows 系統中的 intime,Linux 系統中的 preempt、xenomai 等實時補丁。
請輸入評論內容...
請輸入評論/評論長度6~500個字
最新活動更多
- 1 AI狂歡遇上油價破百,全球股市還能漲多久? | 產聯看全球
- 2 OpenAI深夜王炸!ChatGPT Images 2.0實測:中文穩、細節炸,設計師慌了
- 3 6000億美元估值錨定:字節跳動的“去單一化”突圍與估值重構
- 4 Tesla AI5芯片最新進展總結
- 5 連夜測了一波DeepSeek-V4,我發現它可能只剩“審美”這個短板了
- 6 熱點丨AI“瑜亮之爭”:既生OpenClaw,何生Hermes?
- 7 AI界的殺豬盤:9秒刪庫跑路,全員被封號,還繼續扣錢!
- 8 2026,人形機器人只贏了面子
- 9 DeepSeek降價90%:價格屠夫不是身份,是戰略
- 10 AI Infra產業鏈卡在哪里了?


分享













