http://man7.org/training/download/posix_shm_slides.pdf 第22-30页描述:
假设我们有正确的情况 baseaddr是来自mmap()的返回值 想要在* p
中存储指向目标的指针错误的方式 * p =目标
正确方法(相对偏移): * p = target - baseaddr;
取消引用指针: target = baseaddr + * p;
据此,我有以下源工具:
shmem1.cpp:
struct datafeed
{
int seqno ;
int val1 ;
char *ptr ;
int val2 ;
} ;
static datafeed *conf;
#define STATE_FILE "/datafeed.shared"
#define ARRAYSIZE 50
int main(int argc, char* argv[])
{
int shm_fd;
if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_EXCL | O_RDWR),
(S_IREAD | S_IWRITE))) > 0 ) {
; /* We are the first instance */
}
else if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_RDWR),
(S_IREAD | S_IWRITE))) < 0)
{
printf("Could not create shm object. %s\n", strerror(errno));
exit( 0 ) ;
}
int iTotalByte = sizeof(datafeed)*ARRAYSIZE ;
ftruncate(shm_fd, iTotalByte );
conf = (datafeed*) mmap(0, iTotalByte ,
(PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0) ;
if(conf == MAP_FAILED)
{
printf(" mmap error ....\n") ;
exit( 0 ) ;
}
(conf+0)->seqno++ ;
(conf+0)->val1++ ;
(conf+0)->val2 = (conf+0)->val2 + 2 ;
char *p = new char(128) ;
strcpy(p,"hello world") ;
(conf+0)->ptr = (char *)((char *)p - (char *)conf) ;
}
和shmem2.cpp
int main(int argc, char* argv[])
{
int shm_fd;
if((shm_fd = shm_open(STATE_FILE, (O_RDWR),
(S_IREAD | S_IWRITE))) < 0) {
printf("Could not create shm object. %s\n", strerror(errno));
return errno;
}
int iTotalByte = sizeof(datafeed)*ARRAYSIZE ;
ftruncate(shm_fd, iTotalByte );
conf = (datafeed *)mmap(0, iTotalByte ,
(PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0) ;
if(conf == MAP_FAILED)
{
printf("error in mmap \n") ;
exit(0) ;
}
int seqno = (conf+0)->seqno ;
int val1 = (conf+0)->val1 ;
int val2 = (conf+0)->val2 ;
printf("(%d)(%d)(%d)\n",seqno,val1,val2) ;
//char *p = (char *) ( (char *)conf + (conf+0)->ptr ) ;
char *p = (char *) ( (char *)conf + *((conf+0)->ptr) ) ;
printf("(%s)\n",p) ;
}
在g ++ 4.8.2上编译:
g++ --std=c++11 shmem1.cpp -lrt -o shmem1.exe
g++ --std=c++11 shmem2.cpp -lrt -o shmem2.exe
运行shmem1.exe 2次看起来很好,然后shmem2.exe段错误:
(2)(2)(4)
Segmentation fault
我真的没有在本说明书中得到偏移,我应该修改什么 获得正确的“你好世界”的来源?!
编辑:
http://accu.org/index.php/journals/376
优秀的网页参考。
答案 0 :(得分:4)
char *p = new char(128) ;
(conf+0)->ptr = (char *)((char *)p - (char *)conf) ;
使用此方法,您将创建指针p
并将其值(相对或绝对,无关紧要)存储在共享内存中。
但是当你从另一个进程读取它时,p
的地址在该进程中可能无效,因为它来自另一个进程。所以它就像访问未分配的内存地址一样。这会导致段错误。
您提到的文档中不清楚的一点是,您要存储在共享内存中的地址也应该驻留在同一共享内存中。您不能在共享内存中存储地址(同样是绝对的或相对的),并安全地从另一个进程访问它。
因此,您需要扩展您创建的共享内存以存储包含字符串p
的{{1}}。换句话说,而不是"hello world"
或new()
,您应该从malloc()
的共享内存中获取适当的免费地址。