2012-07-11 22 views
0

我遇到了使用shmget()來管理內存段的問題。根據手冊頁,如果同時設置了IPC_CREAT和IPC_EXCL標誌,則shmget會在請求爲已存在的密鑰創建段時失敗。shmget與IPC_EXCL

我看到的是shmget創建一個新的段爲同一個鍵(與一個新的shmid)不管。下面的代碼說明了這個問題。我正在運行它的兩個實例,一個是'創建者'模式,另一個是'客戶端'模式。

./test 10 0 
./test 10 1 

創建者爲key = 10分配一個內存段,然後附加到它。客戶也重視該細分市場。運行ipcs -m我可以看到該段存在,並且有兩個進程連接到它。

然後我讓創建者銷燬該段,並且如預期的那樣ipcs顯示它被標記爲銷燬,並且仍然附加了1個進程。奇怪的是,如果我再次啓動創建者,使用相同的鍵,它會創建一個新的段而不是失敗,因爲段已經存在?

感謝您的幫助!

#include <sys/shm.h> 
#include <sys/stat.h> 
#include <errno.h> 

#include <stdlib.h> 
#include <vector> 
#include <iostream> 
#include <stdexcept> 
using namespace std; 

int main(int argc, char** argv) 
{ 
    cout << "usage: " << argv[0] << " <key> <mode (0=creator 1=client)>" << endl; 
    if (argc < 3) return 0; 

    int key = atoi(argv[1]); 
    int mode = atoi(argv[2]); 

    cout << "key=" << key << endl; 
    cout << "mode=" << mode << endl; 

    char c; 
    int shmid=-1; 
    int size = 100; // bytes 

    try 
    { 
     if (mode == 0) // creator 
     { 
     cout << "creating segment" << endl; 
     int flags = (IPC_CREAT | IPC_EXCL | 0666); 
     shmid = shmget(key, size, flags); 

     if (shmid== -1) 
      throw runtime_error("failed to create segment"); 

     cout << "created: shmid=" << shmid << endl; 
     } 
     else if (mode == 1) 
     { 
     shmid = shmget(key, 0, 0); 

     if (shmid== -1) 
      throw runtime_error("failed to load"); 

     cout << "loaded: shmid=" << shmid << endl; 
     } 

     cout << "attach? (press key to continue)" << endl; 
     cin >> c; 

     void* data = shmat(shmid, NULL, 0); 

     if (data == (void *) -1) 
     throw runtime_error("failed to attach"); 

     cout << "attached to id=" << shmid << endl; 

     cout << "destroy? (press key to continue)" << endl; 
     cin >> c; 

     if (shmctl(shmid, IPC_RMID, NULL) == -1) 
     throw runtime_error("failed to destroy"); 

     cout << "destroyed" << endl; 
    } 
    catch(const exception& e) 
    { 
     cout << e.what() << " errno=" << errno << endl; 
    } 
} 

回答

3

您應該密切關注ipcs的輸出。使用您的密碼爲10的示例代碼。

服務器已經創建段:

$ ipcs -m 
------ Shared Memory Segments -------- 
key  shmid  owner  perms  bytes  nattch  status 
0x0000000a 1470791680 hristo  666  100  1 

客戶端連接,服務器已標記爲破壞的部分:

$ ipcs -m 
------ Shared Memory Segments -------- 
key  shmid  owner  perms  bytes  nattch  status 
0x00000000 1470791680 hristo  666  100  1   dest 
^^^^^^^^^^ 

由於沒有新的進程預計將能夠找到並通過他們的密鑰附加這些段,關鍵是被清零。這就是爲什麼你可以用同一把鑰匙來創建一個新的。

+0

我注意到了調零鍵,但它現在更有意義!謝謝 – chataign 2012-07-12 08:35:00

相關問題