2012-08-28 102 views
2

我的程序有2个线程,我使用共享内存在两者之间进行通信。调用shmat两次

每个线程都有一个'init'方法。在init方法中,我调用'shmget'和'shmat'来获取共享内存段并附加到局部变量。代码的一部分是象下面这样:

Thread 1 (which runs first): 

void init() { 
    this->segment_id = shmget(SAME_KEY,SAME_SIZE,IPC_CREAT|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH); 
    this->data  = shmat(this->segment_id,0,0); 
} 

Thread 2 (which runs after thread 1): 

void init() { 
    this->segment_id = shmget(SAME_KEY,SAME_SIZE,0); 
    this->data  = shmat(this->segment_id,0,0); 
} 

该程序正在运行,但它给出意想不到的结果。我担心的是,在第二个线程中调用'shmat'可能会导致线程1中的'数据'无法访问或出现某种故障。事实是,在线程1中,我可以访问整个共享段,但在线程2中,我只能访问前16个字节,所以我不知道发生了什么。

这是否意味着每个共享内存段可以一次连接到1个位置? 可以两次调用'shmat'使共享内存可以从不同的指针访问吗?

+1

“在线程2我只能访问前16个字节” - 当您尝试访问的第17个字节会发生什么? SIGSEGV还是别的? –

+1

请注意,使用'shm_open()'然后'mmap()'的POSIX版本更易于使用。 – Ariel

+0

@SteveJessop:没有错误发生,但是,当线程1将一堆数据写入共享内存时,比如说1024字节,线程2可以读取仅前16个字节的值,之后的所有字节都是零 – jondinham

回答

2

每个共享内存段可以一次连接到多个位置。可以调用'shmat'两次以使共享内存可以从不同的指针访问。

我怀疑在给定的例子中,你不能确定Thread1 :: init()是在Thread2 :: init()之前调用的,所以在Thread2中你正在访问未创建的内存 - 所以这就是为什么观察到问题。

这两个调用都使用IPC_CREAT(当然没有IPC_EXCL)。

manpage

+0

uhm,我发现我的错误,我在触发线程2之前意外修改共享内存数据 – jondinham