2010-06-18 14 views
8

我正在開發一種在Linux上使用共享內存的兩個或多個進程之間交換數據的機制。問題是需要一定程度的併發控制來保持共享內存本身的數據完整性,並且正如我在某個時間或其他地方所指出的那樣,我的進程可能會被殺死/崩潰,所以常見的鎖機制不工作,因爲它們可能會留下內存處於「鎖定」狀態並在臨終之後,使其他進程等待鎖被釋放。共享內存一致性的鎖定機制

因此,做了一些研究後,我發現System V信號量有一個名爲SEM_UNDO的標誌,當程序失敗時它可以恢復鎖定狀態,但這並不保證能正常工作。另一種選擇是監視可能使用共享內存的所有進程的PID,並在發生不愉快事件時對其進行一些控制,但我不確定這是否是解決我的問題的正確方法。

任何想法?? :)

編輯:爲了解釋的目的,我們的應用程序需要某種類型的IPC機制儘可能最小的延遲。所以,我也開放了可以處理這一要求的機制。

+0

另一種方法是不使用共享內存 - 我從來沒有理解它似乎對程序員的可怕魅力。還有很多其他的IPC機制(一些在共享內存上預先構建和測試過),那麼爲什麼不使用它們呢? – 2010-06-18 15:07:18

+1

爲了表現。我們的應用程序需要處理微秒級的延遲。有IPC機制可以實現這種性能? – scooterman 2010-06-18 16:42:04

+0

@scooterman您正在使用哪種實時Linux變體? – 2010-06-18 16:47:59

回答

0

我會很好奇,知道你說的SEM_UNDO不能保證工作的源碼。我以前沒有聽說過。我似乎記得閱讀聲稱Linux的SYSV IPC的文章通常是越野車,但那是相當一段時間以前。我在想,如果你的信息只是過去的時代的神器。

要考慮的其他事情(如果我沒有記錯的話)是SYSV信號量能夠告訴您執行信號操作的最後一個進程的PID。如果你掛了,你應該能夠查詢,看看持有鎖的進程是否還活着。由於任何進程(不僅僅是持有鎖的進程)都可以擺弄信號量,所以你可以通過這種方式進行控制。

最後,我將放入消息隊列。它們可能不適合您的速度要求,但它們通常不會比共享內存慢得多。實質上,他們正在盡你所能地用SM手動執行任何操作,但操作系統將它全部放在封面下面。同步,原子性,易用性以及經過全面測試的免費機制您的速度幾乎相同。

+0

我會將此視爲已接受,因爲我已切換到消息隊列並發現它適合我的需求。謝謝 – scooterman 2010-06-23 21:16:48

2

只有幾件事情可以保證從程序失敗中清理乾淨。這裏我唯一想到的就是鏈接數量。一個打開的文件描述符會增加底層inode的鏈接數量,相應的關閉會降低它,包括程序失敗時強制關閉。

所以,你的過程可以全部打開一個共同文件(不記得它是否適合共享內存段),如果計數減少,它應該不是你可能會引發某種報警。例如,不要簡單地等待你的進程可以在一個循環中等待一段時間(例如一秒鐘),並且在有些事情出錯時輪詢鏈接計數。

+0

如果您正確使用futexes,內核將清理它們 – Spudd86 2010-06-18 18:20:04

+0

問題用posix標記。 IIRC futexes是純粹的linux結構,不能移植到其他POSIX系統。 – 2010-06-18 18:27:42

+0

經過一番思考,實際上存在一個POSIX兼容的鎖結構,並保證在進程終止時清理:通過fcntl方式建立諮詢文件鎖。它們使用起來有點棘手(陷阱:當同一個inode上的任何fd被進程的任何線程關閉時,你會釋放一個鎖),但是完全在內核空間中實現,而沒有實際寫入磁盤。 – 2010-06-19 06:34:19

1

當你聲明信號量不能幹淨地處理進程時,我有點驚訝。這種支持似乎相當重要!在我的ubuntu 10.4系統和網頁here上查看semop手冊頁似乎表明它應該沒問題。希望用於存儲SEM_UNDO計數的內存存儲在內核空間中,因此可以避免錯誤的內存寫入。

雖然真相被告知,即使是可靠的信號量鎖定機制也可能無法完全解決您的問題。如果您使用鎖來允許事務處理,那麼您還需要處理事務在崩潰之前中途停止並允許其他程序訪問數據結構的情況。

+0

對不起,還沒有找到我從哪裏來的來源。儘管系統IV信號量有限制,可以由進程保留大約37k個SEM_UNDO結構,所以它無法工作,因爲我的應用程序可以快速寫入這些數量的消息。不管怎麼說,還是要謝謝你。 – scooterman 2010-06-23 21:21:48

1

您可以使用共享內存並行線程互斥pthread_mutexattr_setpshared(http://linux.die.net/man/3/pthread_mutexattr_setpshared

你也可以嘗試使用futexes的直接看到http://people.redhat.com/drepper/futex.pdfhttp://lxr.linux.no/#linux+v2.6.34/Documentation/robust-futexes.txthttp://www.kernel.org/doc/man-pages/online/pages/man7/futex.7.htmlhttp://www.kernel.org/doc/man-pages/online/pages/man2/futex.2.html particularaly第二個自認爲有關獲取內核釋放會談它在持有它的過程中死亡。

另外,我認爲可以使pthreads鎖/ CV變得健壯,這是一個更好的主意,因爲那時處理強健鎖的所有東西都是爲你完成的(在一個甚至是現代化的發行版中,它應該使用強健的futexs在http://lxr.linux.no/#linux+v2.6.34/Documentation/robust-futexes.txt爲pthread_mutex IIRC描述,因爲這一直是在內核相當長一段時間,但你可能想確保你不需要做任何事來讓你的pthread_mutex穩健)

3

所以,做一些研究,我我們發現System V信號量有一個名爲SEM_UNDO的標誌,當程序失敗時它可以恢復鎖定狀態,但這並不保證能夠正常工作。

如果進程崩潰,SEM_UNDO將解鎖信號量。如果進程因共享內存損壞而崩潰,則沒有任何信號量可以爲您執行操作。操作系統無法撤銷共享內存的狀態。

如果你需要能夠回滾共享內存的狀態,那麼你必須自己實現一些東西。我已經看到至少有兩個處理這個問題的模型。

修改共享內存中任何內容之前的第一個模型是拍攝結構的快照,並保存在共享內存的列表中。如果任何其他進程能夠獲得該鎖並且該列表不是空的,則它將撤銷任何崩潰的進程可能已經改變的情況。

第二種模式是在本地內存中創建shm結構的副本並鎖定整個事務的鎖定。當提交事務時,在釋放鎖之前,只需將本地內存中的結構複製到共享內存中即可。應用程序在複製期間崩潰的可能性較低,並且可以使用sigprocmask()來阻止外部信號的干預。 (在這種情況下,最好鎖定在數據上,例如我已經看到測試使用1000個鎖進行10Mln記錄,並通過4個併發進程訪問shm。)

+0

非常有趣的東西。謝謝! – scooterman 2010-06-23 21:17:11