共享内存包含指针
shared memory contain pointer
http://man7.org/training/download/posix_shm_slides.pdf
第 22-30 页描述:
假设我们有右边的情况
baseaddr 是来自 mmap() 的 return 值
想要在 *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
这个描述我实在是看不懂offset的意思,我该修改什么
获得正确 "hello world" 的来源 ?!
编辑:
http://accu.org/index.php/journals/376
优秀的网页可以参考。
char *p = new char(128) ;
(conf+0)->ptr = (char *)((char *)p - (char *)conf) ;
这样你就可以创建指针 p
并将其值(相对或绝对,无关紧要)存储在共享内存中。
但是当您从另一个进程读取它时,p
的地址在该进程中可能无效,因为它来自另一个进程。所以它就像访问未分配的内存地址。这会导致段错误。
您提到的文档中有一点不清楚,您要存储在共享内存中的地址也应该位于同一共享内存中。您不能将地址(绝对或相对)存储在共享内存中并从另一个进程安全地访问它。
因此您需要扩展您创建的共享内存以存储包含字符串 "hello world"
的 p
。换句话说,您应该从 p
.
的共享内存中获取适当的空闲地址,而不是 new()
或 malloc()
http://man7.org/training/download/posix_shm_slides.pdf 第 22-30 页描述:
假设我们有右边的情况 baseaddr 是来自 mmap() 的 return 值 想要在 *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
这个描述我实在是看不懂offset的意思,我该修改什么 获得正确 "hello world" 的来源 ?!
编辑:
http://accu.org/index.php/journals/376
优秀的网页可以参考。
char *p = new char(128) ;
(conf+0)->ptr = (char *)((char *)p - (char *)conf) ;
这样你就可以创建指针 p
并将其值(相对或绝对,无关紧要)存储在共享内存中。
但是当您从另一个进程读取它时,p
的地址在该进程中可能无效,因为它来自另一个进程。所以它就像访问未分配的内存地址。这会导致段错误。
您提到的文档中有一点不清楚,您要存储在共享内存中的地址也应该位于同一共享内存中。您不能将地址(绝对或相对)存储在共享内存中并从另一个进程安全地访问它。
因此您需要扩展您创建的共享内存以存储包含字符串 "hello world"
的 p
。换句话说,您应该从 p
.
new()
或 malloc()