0

我在使用 shmget() 管理内存段时遇到问题。根据手册页,如果同时设置了 IPC_CREAT 和 IPC_EXCL 标志,如果要求 shmget 为已经存在的键创建段,则它应该会失败

我所看到的是 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;
   }
}
4

1 回答 1

4

您应该更密切地注意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
^^^^^^^^^^

由于预计没有新进程能够通过其密钥找到并附加此类段,因此密钥被归零。这就是为什么您可以使用相同的密钥创建一个新的。

于 2012-07-11T15:28:56.257 回答