C++共享內存刪除的陷阱

文章轉自微信公眾號:CPP開發前沿

當進程結束使用共享內存區時,要通過函數 shmdt 斷開與共享內存區的連接。該函數聲明在 sys/shm.h 中,其原型如下:
 

int shmdt(const void *shmaddr);

參數 shmaddr 是 shmat 函數的返回值。

進程脫離共享內存區後,數據結構 shmid_ds 中的 shm_nattch 就會減 1 。但是共享段內存依然存在,隻有 shm_attch 為 0 後,即沒有任何進程再使用該共享內存區,共享內存區才在內核中被刪除。一般來說,當一個進程終止時,它所附加的共享內存區都會自動脫離。
我們通過:
 

int shmctl( int shmid , int cmd , struct shmid_ds *buf );

來刪除已經存在的共享內存:

  • 第一個參數,shmid,是由shmget所返回的標記符。
  • 第二個參數,cmd,是要執行的動作。他可以有三個值:

命令 描述:

  • IPC_STAT 設置shmid_ds結構中的數據反射與共享內存相關聯的值。
  • IPC_SET 如果進程有相應的權限,將與共享內存相關聯的值設置為shmid_ds數據結構中所提供的值。
  • IPC_RMID 刪除共享內存段。
  • 第三個參數,buf,是一個指向包含共享內存模式與權限的結構的指針,刪除的時候可以默認為0。

如果共享內存已經與所有訪問它的進程斷開瞭連接,則調用IPC_RMID子命令後,系統將立即刪除共享內存的標識符,並刪除該共享內存區,以及所有相關的數據結構;

如果仍有別的進程與該共享內存保持連接,則調用IPC_RMID子命令後,該共享內存並不會被立即從系統中刪除,而是被設置為IPC_PRIVATE狀態,並被標記為”已被刪除”(使用ipcs命令可以看到dest字段);直到已有連接全部斷開,該共享內存才會最終從系統中消失。

需要說明的是:一旦通過shmctl對共享內存進行瞭刪除操作,則該共享內存將不能再接受任何新的連接,即使它依然存在於系統中!所以,可以確知, 在對共享內存刪除之後不可能再有新的連接,則執行刪除操作是安全的;否則,在刪除操作之後如仍有新的連接發生,則這些連接都將可能失敗!

Shmdt和shmctl的區別:

hmdt 是將共享內存從進程空間detach出來,使進程中的shmid無效化,不可以使用。但是保留空間。
shmctl(sid,IPC_RMID,0)則是刪除共享內存,徹底不可用,釋放空間。

到此這篇關於C++共享內存刪除的陷阱的文章就介紹到這瞭,更多相關共享內存刪除的陷阱內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: