前言
最近在調(diào)試 RT-Smart 上的用戶態(tài) mq(消息隊(duì)列)時(shí),遇到一個(gè)奇怪的問題,這個(gè)例程打印了一下獲取的時(shí)間,就可以正常的工作(超時(shí)退出),否則,就一直卡住(無法超時(shí))
雖然沒有認(rèn)真的閱讀用戶態(tài) mq 的具體實(shí)現(xiàn)代碼,大概能了解到底層對接了 IPC 消息隊(duì)列,如果一直卡住,可能的原因是超時(shí)時(shí)間參數(shù)沒有正確傳遞下?
排查思路
當(dāng)前未采用 qemu 調(diào)試,直接使用板子驗(yàn)證,所以就手動增加了一些 LOG,用戶態(tài)應(yīng)用與 內(nèi)核態(tài)的應(yīng)用,很快定位到是 內(nèi)核代碼 softwarekernelcomponentslibccompilerscommonctime.c 中的函數(shù) rt_timespec_to_tick 返回值異常導(dǎo)致的
開啟log 打印一下時(shí)間,就可以【正?!客顺?/p>
不開啟 log,發(fā)現(xiàn)卡住了,也就是 ipc 一直沒有超時(shí)
繼續(xù)排查
發(fā)現(xiàn) tick 計(jì)算的有問題,異常的 tick,也就是 IPC timeout 非常大
找到根源:int 型乘法計(jì)算溢出
tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;,這里 nsecond 定義為 int 類型,int 是 32位,所以當(dāng) nsecond 較大時(shí),再乘上 RT_TICK_PER_SECOND, 也就是 1000,由于32位有符號整數(shù)溢出,變?yōu)榱恕矩?fù)值】。
而此時(shí) second 比較小,造成 tick 為一個(gè) 負(fù)值,但是 timeout 是無符號的,所以把一個(gè)負(fù)值當(dāng)成無符號數(shù),就是一個(gè)比較大的數(shù)值
解決方法
第一種,把 nsecond 定義為 int64_t 類型,也就是 long long 類型,這樣計(jì)算時(shí),會按照 64位計(jì)算,不會溢出
第二種:把 tick = second * RT_TICK_PER_SECOND + nsecond * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND; 改為 tick = second * RT_TICK_PER_SECOND + nsecond / (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
小結(jié)
這問題,如果粗心一點(diǎn),可能會直接【放過】,比如加了 LOG 打印發(fā)現(xiàn)沒有問題,但是細(xì)節(jié)決定成敗,有些 BUG 可能出現(xiàn)的方式很奇特,這就是測試代碼需要有一定的覆蓋性,各個(gè)場景下都需要驗(yàn)證,比如 Debug 版本、 Release 版本都測試一下,看看現(xiàn)象是否一致。
經(jīng)過了解 int 溢出,也發(fā)現(xiàn)了一些基礎(chǔ)性的知識點(diǎn),如 32位與64位 CPU 下, long long 類型都是 8字節(jié),如果使用 long 類型定義 nsecond,在 32位平臺上,是 4字節(jié),依舊是異常有問題
修復(fù)問題后,再次驗(yàn)證,發(fā)現(xiàn)定時(shí)比較的準(zhǔn)確了,偏差很小,比如 20秒,20000 個(gè) tick,而不是 19001 個(gè) tick
修復(fù)后,再次運(yùn)行的效果,此時(shí) tick = 19994,與 20秒比較匹配
msh /kernel>./mq_test
msh /kernel>31111111111111111111111111111
msg_queue is 3
main : enter
sys_mq_timedreceive : 5974 1514764824-963161303
tp : 1676378 - 1514764804
tm_spec : 1676378 - 1514764824
rt_timespec_to_tick : line - 730, second : 19, nsecond : 994459929
rt_timespec_to_tick : tick = 19994
mq_timedreceive : tick = 19994
mq_receive()
-
cpu
+關(guān)注
關(guān)注
68文章
10807瀏覽量
210852 -
IPC
+關(guān)注
關(guān)注
3文章
337瀏覽量
51772 -
調(diào)試器
+關(guān)注
關(guān)注
1文章
300瀏覽量
23668 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1261瀏覽量
39841 -
qemu
+關(guān)注
關(guān)注
0文章
57瀏覽量
5320
發(fā)布評論請先 登錄
相關(guān)推薦
評論