簡體   English   中英

shm_open和ftruncate競爭條件可能嗎?

[英]shm_open and ftruncate race condition possible?

shm_open手冊頁:

新的共享內存對象最初的長度為零。 可以使用ftruncate(2)設置對象的大小。 [...] shm_open()函數本身不會創建指定大小的共享對象,因為這樣做會復制現有函數,該函數設置文件描述符引用的對象的大小。

這不會使應用程序暴露於競爭條件下嗎? 考慮以下偽代碼:

int fd = shm_open("/foo", CREATE);
if ( fd is valid ) {
  // created shm object, so set its size
  ftruncate(fd, 128);
} else {
  fd = shm_open("/foo", GET_EXISTING);
}
void* mem = mmap(fd, 128);

由於shm_openftruncate調用(一起)不是原子的,你可能有一個競爭條件,一個進程調用shm_openCREATE case)但是,在調用ftruncate之前,另一個進程調用shm_openGET_EXISTING case)並嘗試mmap對象為0大小,甚至可能寫入它。

我可以想到兩種避免這種競爭條件的方法:

  1. 使用IPC互斥量/信號量使整個事物同步,或者......

  2. 如果它是安全的(按POSIX),則在CREATEGET_EXISTING情況下調用ftruncate

哪種方法可以避免這種競爭條件?

你的方法(從兩者調用ftruncate )應該可行,但是你需要一種方法來同步使用共享內存段的內容 由於內存最初是空的(零填充),因此不包含有效的同步對象,除非您要使用atomics自行滾動,否則無論如何都需要輔助形式的同步來控制對共享內存的訪問。

我認為通常情況下,您不希望多個流程競爭創建或打開具有固定名稱的共享內存段,您希望擁有一個負責創建具有隨機名稱的段的所有者進程,使用O_EXCL來避免隨機或惡意沖突,然后傳遞名稱,一旦您成功打開它,將其大小,並在其中創建同步對象,到其他需要訪問它的進程。

作為@R。 這里提到的另一個問題是,在創建文件之前,在內容(例如互斥鎖)被初始化並准備好使用之前,仍然有一個窗口。

與上述略有不同的解決方案是:

嘗試打開()。 如果open()成功,只需map()並使用必要的保證(見下文),內容已經初始化並且很好用。 如果open()失敗,則創建並初始化臨時文件,然后嘗試將臨時文件硬鏈接()作為所需文件,並取消鏈接()臨時名稱。

如果link()成功,我們現在已經為我們自己和其他進程提供了初始化文件。 如果link()與EEXIST失敗,則另一個進程首先到達那里(與rename()不同,如果目標名稱存在,則link()失敗)。 無論哪種方式,我們重復的open()現在應該成功使用初始化的准備使用文件。

使用這種策略,臨時文件的初始化顯然存在競爭條件,但是如果初始化過程是冪等的,而不是資源過於昂貴,並且每個進程都選擇一個唯一的臨時文件,這是無關緊要的。 如果多個初始化可能是一個問題,則解決方案是將初始化分成兩個階段的過程,第一階段只是文件中的互斥體,用於防止在第二階段期間對文件的其余部分進行多次初始化。

暫無
暫無

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

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