2009-08-07 39 views
0

我使用命名的System V信號量來鎖定OSX和Linux上的所有應用程序中的文件。根據任何定義,不是最漂亮的API。正確銷燬命名的系統V信號量

它似乎工作,但我不能完全弄清楚如何在每個人都完成後正確地銷燬信號量。

通用邏輯是這樣的:

創建:

[1]的線程或進程試圖打開信號量與()由ftok爲文件創建的key_t設置。 Set包含2個信號量。 [2]如果信號量集不存在,它將創建666個權限。 [3]「鎖定」(其中一個信號)設置爲釋放狀態(值1)。 [4]「引用計數」(同一組中的另一個信號量)遞增。

鎖定/解鎖:

要鎖定[5],線程減1,「鎖定」信號量的值(具有撤銷),從而等待如果它已經爲零。要解鎖[6],線程會將其加1,從而允許別人鎖定它。

毀:

[7] 「引用計數」 信號被試圖遞減(用IPC_NOWAIT標誌)。 [8]它的值被檢查爲0,並且如果它是[9]信號集被銷燬。

(也有基於線程本地存儲邏輯層,使一個線程內鎖遞歸)

的問題是:

  • 如何同步步驟[1] [2]? (如果信號集不存在,但是當我們計算星星時,它是由其他人創建的,所以現在創建也將失敗)
  • 如何將步驟[4]與[8]同步以便[9]執行不是過早地殺了我?
  • 有沒有其他的比賽條件?

PS:雖然POSIX信號有更漂亮的API,我不認爲我能活下來sem_inlink()行爲如下所述:

呼叫至sem_open()來重新創建或重新 - 連接到信號量是指在調用sem_unlink()後 之後的新信號量 。

所以我沒有辦法釋放他們...

回答

1

幾種方法:

首先,如果你的目標是鎖定文件,然後使用文件鎖定通話flock(2)fcntl(2)+F_SETLK,而不是一個信號量。恕我直言,這是最好的方法。

二,保持sem永遠。你說得對,提案很活潑,你的措詞表明新的sem客戶端可能隨時出現。你需要一個單獨的同步機制,像一個單獨的,長期生存的sem來控制你實際關心的sem的創建/銷燬。你可以得到異域風情,並將其與專用的「等待零」驅動程序(mysembuf.sem_op := 0)結合起來,觀看計數器sem並準備好IPC_RMID。呸。更好的辦法是擁有一個單一的,持久的二進制信號量,而不需要用戶提供的引用計數。

三,使用POSIX命名sems。忽略sem_unlink(),而不是簡單的sem_close()完成後(當然後sem_post()解鎖!)。這在概念上就像先前的方法 - 一個小的同步原始依然存在 - 但正如你所說,一個更簡單的API。你也不必處理SysV semaphores' fatal flaw

+0

我不知道致命的缺陷:信號量的創造是原子的(我希望?)。下一個進程會實際得到它,或者最壞的情況是無法創建一個調用(應該簡單地嘗試在循環中再次獲取它)。然後,直到創建過程釋放它(設置爲1),其他人將已經存在的sem,並且如果試圖「鎖定」(用-1),他們將等待。創建過程失去控制,但沒關係,它們都是平等的。 – Eugene 2009-08-07 04:57:58

+0

(其實這就回答我的一個問題,我只是不想循環:)) – Eugene 2009-08-07 05:01:54

+0

至於保持一個sem,在linux上最大一般很小,比如128集。我只需要鎖定幾個文件,但是我的單元測試速度非常快 - 這是我不想使用的主要原因。 – Eugene 2009-08-07 05:07:57

0

這是我最終做的事情(這是一個榮譽,在這一點上,我不會離開直到我有正確的代碼,無論它是否需要手頭的任務:))。

創建

嘗試打開[1]現有的SEM鑲有3個SEMS,如果失敗,嘗試[2]創建一個。如果由於某人已經創建而無法創建,請返回[1]。這個循環最終會退出,無論是打開或創建的sem,還是因爲我無法處理的錯誤,在這種情況下,我拿球並回家。 (我也有N次迭代的限制,以防萬一:))。

3個sems中的一個是有效負載,另一個是引用計數,第三個是引用計數鎖。 [2]鎖定初始化爲0後,鎖定狀態。

擋土牆

如果SEM組是由[2],所有3個SEMS被semoped [3]從0到1有效載荷被釋放時,引用計數是1時,鎖定被解除(沒有撤消)中創建。 如果它被[1]打開,獲取鎖定[4](-1),ref計數遞增(+1)並且鎖定被釋放(+1)。如果此時鎖定爲零,這將會阻止。如果這個semop由於sem set在我們等待的時候在[6]被銷燬而失敗,保留失敗,我們一路回到[1]。這個循環的迭代次數也是有限的。

釋放

獲取鎖[5](-1與等待),ref計數遞減(-1沒有等待)。如果成功,那麼如果ref count現在爲零,則sem集合將被銷燬。否則[6]鎖定被釋放(+1)。如果由於sem集被破壞而導致鎖失敗 - 無所事事。

在保留和釋放之間,有效載荷按照慣例使用。除了每集2個信號量的複雜性和開銷之外,只有一個問題(現在我看到致命缺陷:)) - 當創建者在[2]和[3]之間崩潰時。這將掛死所有客戶。我可以在Linux上使用定時等待並殺死孤立的信號量,但OSX,因爲通常的白癡自我,沒有定時操作,所以我有點擰...

* ...離開編寫自己的內核或者其他的東西...*