如何在shmat()共享内存段中给出附加起始地址?

时间:2012-11-03 20:38:10

标签: c posix fork shared-memory

根据要求包含所有标题。下面的这段代码正在运行,但问题在于shmat(seg_id,NULL,0)。第二个参数中的NULL表示操作系统将代表用户处理该位置。但我们可以给自己的记忆位置,但如何?我不知道,请帮忙。 (OS - Ubuntu 11.04 ,Compiler gcc 4.5.2) 我试过man shmat,但完全不理解

typedef struct {
         int id;
} emp;

int main() {
         emp *e;
         int seg_id;
         const int size=sizeof(emp);
         seg_id=shmget( IPC_PRIVATE, size, S_IRUSR | S_IWUSR); 
         pid_t pid=fork();
         if(pid<0) {
                 printf("Error");
                 return -1;
         }
         else if(pid == 0) {
                e=(emp *)shmat(seg_id,NULL,0);     
                 e->id=123;
                 shmdt(e);                       
         }
         else {
                 wait(NULL);
                 e=(emp *)shmat(seg_id,NULL,0);  
                 printf("\nEmp Id : %d\n\n",e->id);
                 shmdt(e);                          
                 shmctl(seg_id, IPC_RMID, NULL);  
         }
         return 0;
}

我也尝试过为{4K}页面对齐获取shmget()的地址

emp *e;
void **p;
posix_memalign(&p,4096,4096); // alignment as of pagesize 4K 
e=p; // get the first address of the aligned memory 
free(p); // free the allocated memory

然后将其用作shmat(seg_id,e,0); //认为e将是我想要的地址。 但它给出了分段错误

或者,第3个参数也有问题吗? 任何帮助或建议将不胜感激

1 个答案:

答案 0 :(得分:2)

我不确定你在posix_memalign()尝试做什么。您正在调用该函数从堆中分配一块内存,然后尝试使用posix_memalign()返回的相同地址作为映射共享内存段的位置。该地址显然无法使用,因为它是堆的一部分!

我看到你在调用posix_memalign()之前释放shmat()返回的块,但是从堆释放一块内存不会(通常)导致堆缩小,所以地址实际上仍然是堆的一部分。

如果必须为shmat()选择自己的地址,则应选择与地址空间中的任何其他地址相距甚远的地址,以避免与堆或任何其他映射冲突,并避免堆积在您的流程生命周期中增长时,会遇到映射。确定这样的地址本质上是不可移植的。

我想要为映射选择固定地址的唯一原因是确保它在几个不同的进程中映射为相同的地址(以便内部指针可以工作)。如果这是您想要的,您可以让操作系统在第一个过程中选择位置,并在第二个和所有其他过程中使用相同的地址调用shmat()。即使这可能不起作用,因为其他进程可能已经在某个映射到同一地址。