带有 IPC_EXCL 的 shmget

Posted

技术标签:

【中文标题】带有 IPC_EXCL 的 shmget【英文标题】:shmget with IPC_EXCL 【发布时间】:2012-07-11 12:37:01 【问题描述】:

我在使用 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;
   

【问题讨论】:

【参考方案1】:

您应该密切关注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
^^^^^^^^^^

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

【讨论】:

我注意到了归零的键,但现在更有意义了!谢谢

以上是关于带有 IPC_EXCL 的 shmget的主要内容,如果未能解决你的问题,请参考以下文章

如何取回现有的 msg queue id

Linux 进程间共享内存 SYSTEMV

带有多个链接的 NSAttributedString 的 UILabel,带有行限制,显示尾部截断,带有未见文本的 NSBackgroundColorAttributeName

使用带有 uuencode 的“sendmail”发送邮件,并带有主题

带有和不带有聚合的 sql 查询

带有滚动的 Div 和带有绝对位置的内容