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

标签 c posix fork shared-memory

根据要求包含所有 header 。下面的这段代码可以工作,但问题在于 shmat(seg_id,NULL,0)。第二个参数中的 NULL 意味着操作系统将处理该位置代表用户。但是我们可以给出我们自己的存储位置,但是如何呢?我不知道,请帮忙。 (操作系统 - Ubuntu 11.04,编译器 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 将是我想要的地址。 但它给出了段错误

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

最佳答案

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

我看到您释放了 posix_memalign() 返回的 block 在调用shmat()之前,但是从堆中释放内存块(通常)不会导致堆收缩,因此该地址实际上仍然是堆的一部分。

如果您必须为shmat()选择自己的地址,您应该选择一个远离地址空间中其他任何地址的地址,以避免与您的堆或任何其他映射发生冲突,并避免堆在进程生命周期中随着映射的增长而与您的映射发生冲突。确定这样的地址本质上是不可移植的。

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

关于c - 如何给出附加到 shmat() 共享内存段中的起始地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13213283/

相关文章:

c - emacs:是否有语义跳转到声明(使用 semantic.el)?

c - 多线程客户端服务器执行有时不会结束

c - 如何在使用程序集排序后刷新 C 数组

macos - Mac OS X POSIX 不兼容吗? (timer_settime)

c - 执行 : how can I initialise char *argv[ ] with multiple commands instead of a single command?

c - fgetc 阻塞 : problem with reading from a pipe

c - read() write() 通过 dup2() 与 stdin 和 stdout 写入 pipe()

父进程退出后,子进程无法从终端读取

c - 使用管道在两个进程之间连续传递数据

regex - 如何测试字符串是否与 POSIX shell 中的正则表达式匹配? (不是 bash )