簡體   English   中英

在用戶級別C中實現信號量

[英]Implement semaphore in User Level C

信號量的有效和必要實現要求它是原子指令。

我在互聯網上看到了幾種用戶級別的C實現,這些實現使用諸如count之類的變量或諸如queue之類的數據結構來實現信號量。 但是,涉及變量的指令不能作為原子指令運行。 因此,任何人都不能在C級用戶中實施臨時任務。

交流圖書館semaphore.h如何實現信號量?

答案幾乎肯定是“沒有”-相反,它將調用提供必要的原子操作的內核服務。

直到標准 C中是不可能的。 正如您所說,您需要的是原子操作。 最終指定了它們,例如參見stdatomic.h

如果您使用的是該標准的較舊版本,則必須直接使用嵌入式匯編程序,或者依賴於編譯器的特定於供應商的擴展,例如,參見GCC原子內建 當然,處理器支持有關內存屏障, 檢查和交換操作等的指令。純和更早的版本無法訪問它們,因為並行執行不在標准范圍內。

在閱讀MartinJames的評論之后,我應該在這里添加說明:僅當您在用戶空間中實現所有線程時,這才適用,因為信號量必須阻塞等待它的線程,因此,如果線程是由內核的調度程序管理的(例如例如在Linux上使用pthreads),則必須執行syscall。 不在您的問題范圍內,但是原子操作對於實現例如無鎖數據結構仍然可能很有趣。

您可以簡單地實現信號量操作:

void sema_post(atomic_uint *value) {
    unsigned old = 0;
    while (!atomic_compare_exchange_weak(value, &old, old + 1));
}

void sema_wait(atomic_uint *value) {
    unsigned old = 1;
    while (old == 0 || !atomic_compare_exchange_weak(value, &old, old - 1));
}

從語義sema_wait可以,但是在sema_wait確實忙於等待(旋轉)。 (請注意, sema_post是無鎖的,盡管它也可能旋轉。)相反,它應該休眠直到value變為正數。 用原子無法解決此問題,因為所有原子操作都是非阻塞的。 在這里,您需要OS內核的幫助。 因此,有效的信號量可以使用基於原子的類似算法,但在兩種情況下進入內核(有關此方法的更多詳細信息,請參見Linux futex ):

  • sema_wait :當發現value == 0 ,請睡覺
  • sema_post :當它的value從0遞增到1時,請喚醒另一個睡眠線程(如果有)

通常,要在數據結構上實現無鎖(使用原子)操作,要求每個操作都適用於任何狀態。 對於信號量, wait不適用於值0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM