[英]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_open
和ftruncate
調用(一起)不是原子的,你可能有一個競爭條件,一個進程調用shm_open
( CREATE
case)但是,在調用ftruncate
之前,另一個進程調用shm_open
( GET_EXISTING
case)並嘗試mmap
對象為0大小,甚至可能寫入它。
我可以想到兩種避免這種競爭條件的方法:
使用IPC互斥量/信號量使整個事物同步,或者......
如果它是安全的(按POSIX),則在CREATE
和GET_EXISTING
情況下調用ftruncate
。
哪種方法可以避免這種競爭條件?
你的方法(從兩者調用ftruncate
)應該可行,但是你需要一種方法來同步使用共享內存段的內容 。 由於內存最初是空的(零填充),因此不包含有效的同步對象,除非您要使用atomics自行滾動,否則無論如何都需要輔助形式的同步來控制對共享內存的訪問。
我認為通常情況下,您不希望多個流程競爭創建或打開具有固定名稱的共享內存段,您希望擁有一個負責創建具有隨機名稱的段的所有者進程,使用O_EXCL
來避免隨機或惡意沖突,然后傳遞名稱,一旦您成功打開它,將其大小,並在其中創建同步對象,到其他需要訪問它的進程。
作為@R。 這里提到的另一個問題是,在創建文件之前,在內容(例如互斥鎖)被初始化並准備好使用之前,仍然有一個窗口。
與上述略有不同的解決方案是:
嘗試打開()。 如果open()成功,只需map()並使用必要的保證(見下文),內容已經初始化並且很好用。 如果open()失敗,則創建並初始化臨時文件,然后嘗試將臨時文件硬鏈接()作為所需文件,並取消鏈接()臨時名稱。
如果link()成功,我們現在已經為我們自己和其他進程提供了初始化文件。 如果link()與EEXIST失敗,則另一個進程首先到達那里(與rename()不同,如果目標名稱存在,則link()失敗)。 無論哪種方式,我們重復的open()現在應該成功使用初始化的准備使用文件。
使用這種策略,臨時文件的初始化顯然存在競爭條件,但是如果初始化過程是冪等的,而不是資源過於昂貴,並且每個進程都選擇一個唯一的臨時文件,這是無關緊要的。 如果多個初始化可能是一個問題,則解決方案是將初始化分成兩個階段的過程,第一階段只是文件中的互斥體,用於防止在第二階段期間對文件的其余部分進行多次初始化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.