文章總列表

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多執行緒

原本上述CONTEXT SWITCH都發生在作業系統的層級,一般用戶摸不到;但C語言提供setjmp/ longjmp這對函數,可以儲存和還原CONTEXT,這意味著用戶就可以自己切換CONTEXT,不依賴作業系統,達成多工

     拿他來做什麼?

本來軟體跑在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

留言

Bee寫道…
http://wallace7914032.blogspot.com/2019/09/coroutine.html
這是我寫的coroutine程式。完全不需要RTOS。

這個網誌中的熱門文章

STM32 UART + DMA,使用HAL實作TX/RX,以及不定長度接收

幼犬書桌椅選擇心得 升降桌 兒童桌椅

CANON G3000 廢墨瓶改裝