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