CO-ROUTINE
我小時候一直很好奇,電動程式要怎麼一心多用?同時能吃鍵盤輸入,更新畫面,撥放音樂,這樣起碼三件事同時做。我小時候寫過BASIC,記得用play這個指令可以撥放音樂,撥放完了才能讓程式繼續執行下去
PLAY "..."
After play done, execute subsequent commands
長大後我知道,這些API都是blocking call,這行PLAY得撥完才會出來;於是系統要設計緩衝區,先填入資料,再讓硬體慢慢撥放;硬體快要搬光了,打中斷通知程式填下一段音樂。這種概念是前景背景的設計,前景反覆跑(繪圖,吃鍵盤輸入,處理敵人);背景填音樂。只要他們切換得夠快,人就不覺得有中斷後來學了另外一個方法叫執行緒(Threading),一個程式可以啟動很多執行緒,讓作業系統分時間喚醒執行緒。只要切割得夠快,人還是覺得他們是同時的。Multi-Threading的程式有個好處,他可能在多核心的電腦同時執行,於是就得用"鎖"處理同步存取的問題,這題不容易,暫且跳過
後來工作接觸到RTOS(Real Time Operating System),他們也是作業系統,只是資源更少,他一樣能在多個工作之間切換。這種切換工作的術語叫CONTEXT SWITCH,原理是切換之前,把程式的狀態保存下來,等一下就能切回來。下圖是個想像的CPU(大概是ARM7),切出去之前把所有暫存器(Register)的數值存下,還有程式跑到哪裡(PC)存下,這樣就能在工作之間切換
上述的一切招數都只為了讓處理器一心多用,或著說多工,最底層都是CONTEXT SWITCH
- 前景工作,背景(中斷)工作
- Linux多執行緒
- RTOS多執行緒
拿他來做什麼?
本來軟體跑在RTOS上,希望移植到電腦執行,加速開發。最大的困難是底層的工作切換由作業系統負責,他們刻成組合語言,不容易移植。稍等... 前面不是說,setjmp/ longjmp提供CONTEXT SWITCH基礎設施?
是的,我們可以土炮做CONTEXT SWITCH,達成RTOS的效果
根據這篇文章,我們用比較高階的setcontext()/ swapcontext()做到CONTEXT SWITCH;切換邏輯還是用戶決定:我們編寫一段排程器(scheduler),喚醒最優先的工作起來跑。核心程式不大,我們很快就得到一個模擬器的基礎,跑得飛快無比。當然移植工作是另外一個坑,大大的坑...
我是有種相見恨晚的遺憾:CO-ROUTINE,這些東西看過很多年,卻始終沒弄清楚,其實就只是CONTEXT SWITCH。這意味著RTOS的好東西可以搬進USER PROGRAM裡,編寫更好的程式
Reference
http://zevoid.blogspot.com/2017/11/cc-coroutine-fiber.html
https://hackmd.io/@sysprog/c-control-flow?type=view
https://descent-incoming.blogspot.com/2014/01/setjmplongjmp-x86-32-bit.html
留言
這是我寫的coroutine程式。完全不需要RTOS。