2013-12-08 32 views
2

對於用戶級線程,在單個內核線程上運行N個用戶級線程。這與只有一個用戶線程在內核線程上運行的pthread相反。如何在Linux中爲用戶級線程實施搶先式調度?

在單個內核線程上搶先調度N個用戶級線程。但是,這是如何做的細節。

我聽到一些建議線程庫設置的東西,以便內核發送信號,這是將執行從單個用戶級線程抽出到信號處理程序的機制,然後可以執行搶先調度。

但是,如何保存和/或突變狀態(如寄存器和線程結構)以使這一切工作的細節如何?是否有一個非常簡單的用戶級線程可用於瞭解詳細信息?

回答

2

要獲得詳細信息,請使用源代碼!但這是我讀到它時記得的......

用戶級別的線程有兩種調度方式:自願和搶先。

  • 自願調度:線程必須定期調用一個函數來使用CPU的傳遞到另一個線程。這個功能被稱爲yield()schedule()或類似的東西。
  • 搶先調度:該庫強制從一個線程中刪除CPU並將其傳遞給另一個線程。這通常使用定時器信號完成,例如SIGALARM(詳情請參見man ualarm)。

關於如何做到真正的開關,如果你的操作系統是友好的,並提供必要的功能,那很容易。在Linux中,您可以使用makecontext()/swapcontext()函數輕鬆地從一個任務交換到另一個任務。再次請參閱手冊頁以獲取詳細信息。

不幸的是,這些函數從POSIX中刪除,所以其他UNIX可能沒有它們。如果是這樣的話,還有其他的技巧可以完成。最流行的是一個調用sigaltstack()來設置一個用於管理信號的備用堆棧,然後kill()本身進入備用堆棧,longjmp()從信號功能到您想要運行的實際用戶模式線程。聰明,呃?作爲一個側面說明,在Windows中,用戶模式線程被稱爲光纖並且也受到完全支持(請參閱文檔CreateFiber())。

最後的手段是使用匯編程序,它可以在幾乎任何地方工作,但它完全是系統特定的。創建UMT的步驟爲:

  • 分配一個堆棧。
  • 分配並初始化一個UMT上下文:一個保存相關CPU寄存器值的結構。

並切換從一個UMT到另一個:

  • 保存當前上下文。
  • 切換堆棧。
  • 恢復CPU中的下一個上下文並跳轉到下一條指令。

這些步驟在彙編程序中相對容易實現,但在普通C語言中完全不可能,沒有上述任何技巧的支持。

相關問題