标签: mmap

通过使用mmap()在进程之间共享内存

我在Linux 2.6.我有一个环境,其中2个进程通过简单的消息传递模式实现模拟(使用共享内存)数据交换.

我有一个客户端进程(从父服务器分叉,它是服务器),它将结构(消息)写入创建的内存映射区域(在fork之后):

message *m = mmap(NULL, sizeof(message), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

然后,该指针被写入到队列(在链接列表的形式)转换成是共同的服务器和客户端处理(因为如果事先创建上面相同的代码叉)另一个共享存储器区域.然后由服务器读取该区域,该服务器获得指向消息的指针并对其进行处理.

问题是*m是在fork()之后创建的,当服务器进程尝试访问指向的内存位置时,我得到了分段错误.在客户端创建后,是否可以将该内存区域附加到服务器POST分叉?

注意:我不想在分叉之前将指针映射到消息(然后在服务器之前共享它)因为我通常不知道客户端想要发送到服务器的消息数量,而且可能还有更多消息比一个客户端进程,所以我想只在客户端需要发送消息时创建一个新的共享内存块,并在服务器收到该消息后取消映射.

注意:这是出于学术目的:我知道这不是解决这个问题的最佳方法,但我只需要遵循这条道路.

提前致谢!

c linux ipc mmap shared-memory

19
推荐指数
3
解决办法
3万
查看次数

写入文件和映射内存有什么区别?

我有以下与处理文件和映射它们相关的问题(mmap):

  1. 我们知道,如果我们创建一个文件,并写入该文件,那么我们写入内存的方式.那么为什么要使用mmap然后写入该文件到内存?
  2. 如果是因为我们使用的是实现保护mmap- ,,PROT_NONE 使用文件,那么相同的保护级别也可以实现.,等等.那么,为什么?PROT_READPROT_WRITEO_RDONLYO_RDWRmmap
  3. 我们将文件映射到内存然后使用它有什么特别的优势吗?而不是仅仅创建一个文件并写入它?
  4. 最后,假设我们mmap有一个文件到内存,如果我们写入mmap返回的内存位置,它是否也同时写入该文件?

请帮我回复所有问题.

非常感谢提前.

*编辑:在线程之间共享文件*

据我所知,如果我们在两个线程(非进程)之间共享一个文件,那么建议将mmap它放入内存然后使用它,而不是直接使用该文件.

但我们知道使用文件意味着它肯定在主内存中,那么为什么线程需要再次进行mmaped?

c linux mmap file

19
推荐指数
2
解决办法
8617
查看次数

为什么我们可以分配1 PB(10 ^ 15)数组并访问最后一个元素,但是不能释放它?

众所周知:http://linux.die.net/man/3/malloc

默认情况下,Linux遵循乐观的内存分配策略.这意味着当malloc()返回非NULL时,无法保证内存确实可用.如果事实证明系统内存不足,那么一个或多个进程将被OOM杀手杀死.

和我们能够成功地通过使用分配1个拍字节VMA(虚拟存储区)的malloc(petabyte);:http://ideone.com/1yskmB

#include <stdio.h>
#include <stdlib.h>

int main(void) {

    long long int petabyte = 1024LL * 1024LL * 1024LL * 1024LL * 1024LL;    // 2^50
    printf("petabyte %lld \n", petabyte);

    volatile char *ptr = (volatile char *)malloc(petabyte);
    printf("malloc() - success, ptr = %p \n", ptr);

    ptr[petabyte - 1LL] = 10;
    printf("ptr[petabyte - 1] = 10; - success \n");

    printf("ptr[petabyte - 1] = %d \n", (int)(ptr[petabyte - 1LL]));

    free((void*)ptr);   // why the error is here? …
Run Code Online (Sandbox Code Playgroud)

c linux malloc mmap virtual-address-space

19
推荐指数
2
解决办法
1891
查看次数

Docker内存限制导致SLUB无法使用大页面缓存进行分配

给定一个通过mmap'd文件创建大型linux内核页面缓存的进程,在具有内存限制的docker容器(cgroup)中运行会导致内核slab分配错误:

Jul 18 21:29:01 ip-10-10-17-135 kernel: [186998.252395] SLUB: Unable to allocate memory on node -1 (gfp=0x2080020)
Jul 18 21:29:01 ip-10-10-17-135 kernel: [186998.252402]   cache: kmalloc-2048(2412:6c2c4ef2026a77599d279450517cb061545fa963ff9faab731daab2a1f672915), object size: 2048, buffer size: 2048, default order: 3, min order: 0
Jul 18 21:29:01 ip-10-10-17-135 kernel: [186998.252407]   node 0: slabs: 135, objs: 1950, free: 64
Jul 18 21:29:01 ip-10-10-17-135 kernel: [186998.252409]   node 1: slabs: 130, objs: 1716, free: 0
Run Code Online (Sandbox Code Playgroud)

看着slabtop我可以看到在以内存限制开始的容器中,buffer_head,radix_tree_node和kmalloc *对象的数量受到严格限制。这似乎会对应用程序中的IO吞吐量产生病理影响,并且可以通过观察到iostat。即使页面缓存消耗了在容器外部运行的主机OS上的所有可用内存或没有内存限制的容器,也不会发生这种情况。

这似乎是内核内存记帐中的一个问题,其中不将内核页面高速缓存计入容器内存,而是将其支持的SLAB对象计入容器内存。该行为似乎是异常的,因为在预先分配了一个大的平板对象池时运行,内存受限的容器运行良好,可以自由地重用现有的平板空间。只有在容器中分配的平板才计入容器。内存和内核内存的容器选项的组合似乎无法解决此问题(除非根本不设置内存限制,或者设置的限制太大以至于不能限制平板,但这会限制可寻址空间)。我试图通过cgroup.memory=nokmem引导完全禁用kmem记帐,但没有成功。

系统信息:

  • Linux ip-10-10-17-135 4.4.0-1087-aws#98-Ubuntu SMP
  • AMI ubuntu …

java mmap linux-kernel amazon-ecs docker

19
推荐指数
1
解决办法
564
查看次数

Linux上的Python mmap'权限被拒绝'

我有一个非常大的文件,我正试图用mmap打开,并且它允许我被拒绝.我尝试了不同的旗帜和模式,os.open但它不适合我.

我究竟做错了什么?

>>> import os,mmap
>>> mfd = os.open('BigFile', 0)
>>> mfile = mmap.mmap(mfd, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
mmap.error: [Errno 13] Permission denied
>>> 
Run Code Online (Sandbox Code Playgroud)

(使用内置的open()工作通过python docs示例,但它似乎在读取和写入模式下打开文件的多个句柄.我需要的mmap.mmap方法是文件编号,所以我不认为我需要创建一个file对象;因此我尝试使用os.open())

python mmap permission-denied

18
推荐指数
3
解决办法
1万
查看次数

将非连续块从文件映射到连续的内存地址

我对使用内存映射IO的前景感兴趣,最好利用boost :: interprocess中的工具来实现跨平台支持,将文件中不连续的系统页大小块映射到内存中的连续地址空间.

简化的具体方案:

我有许多"普通旧数据"结构,每个都有一个固定的长度(小于系统页面大小.)这些结构被连接成一个(非常长的)流,其结构的类型和位置由在流中进行它们的那些结构的值.我的目标是在要求苛刻的并发环境中最小化延迟并最大化吞吐量.

我可以非常有效地读取这些数据,通过内存映射它至少是系统页面大小的两倍...并建立一个新的映射,立即读取超出倒数第二个系统页面边界的结构.这使得与普通老式的数据结构交互的代码是一无所知,这些结构是存储器映射...,例如,可以比较使用memcmp()直接在两个不同的结构,而不必关心页边界.

事情变得有趣的是关于更新这些数据流......当它们被(同时)读取时.我想要使​​用的策略受到系统页面大小粒度的"写入时复制"的启发......基本上是写"覆盖页面" - 允许一个进程读取旧数据而另一个进程读取更新数据.

管理哪些叠加页面以及何时使用不一定是微不足道的......这不是我主要关注的问题.我主要担心的是我可能有一个跨越第4页和第5页的结构,然后更新完全包含在第5页的结构...在第6位写入新页面...当第5页时,将第5页保留为"垃圾收集"决定不再可达.这意味着,如果我将第4页映射到位置M,我需要将第6页映射到内存位置M + page_size ...,以便能够使用现有的(非内存映射)可靠地处理跨页边界的结构意识到)功能.

我正在努力建立最好的策略,而且我受到文件的阻碍,我认为这是不完整的.本质上,我需要将地址空间的分配与内存映射分离到该地址空间.使用mmap(),我知道我可以使用MAP_FIXED - 如果我希望显式控制映射位置......但我不清楚我应该如何保留地址空间以便安全地执行此操作.我可以在没有MAP_FIXED的情况下映射/ dev/zero两个页面,然后使用MAP_FIXED两次将两个页面映射到显式VM地址的分配空间吗?如果是这样,我应该三次打电话给munmap()吗?它会泄漏资源和/或有任何其他不利的开销吗?为了使问题更加复杂,我想在Windows上采用类似的行为......有什么办法可以做到这一点吗?如果我要牺牲我的跨平台野心,是否有完整的解决方案?

-

感谢您的回答,Mahmoud ......我已经读过了,并且认为我已经理解了代码......我已经在Linux下编译了它,它的行为与您的建议一致.

我主要关心的是第62行 - 使用MAP_FIXED.它对mmap做了一些假设,当我阅读我能找到的文档时,我无法确认.您将"更新"页面映射到与最初返回的mmap()相同的地址空间 - 我认为这是'正确' - 即不是恰好在Linux上运行的东西?我还需要假设它适用于文件映射和匿名映射的跨平台.

这个样本肯定让我前进......记录我最终需要的东西可能是在Linux上用mmap()实现的 - 至少.我真正喜欢的是指向文档的指针,该文档显示MAP_FIXED行将在示例演示中运行...并且,理想情况下,从Linux/Unix特定mmap()到独立平台的转换(Boost :: interprocess) )方法.

c++ boost mmap shared-memory boost-interprocess

18
推荐指数
1
解决办法
2157
查看次数

为什么要使用shm_open?

做的有什么好处:shm_open跟着一个mmap
为什么不创建一个常规文件,然后将其传递fdmmap
我看不到它的优点shm_open- 这些只是参考,不是吗?

我读过全家人.在我看来,"秘密"在于mmaping动作 - 文件"类型"似乎毫无意义.

任何指针都会很好,尤其是性能帐户.
我的上下文是一个(循环可写的)缓冲区(比如128MB),它将被不断地写成一个进程,并且不断地从另一个进程转发.

举个例子:这个 open/mmap方法有什么问题.

编辑
准确地说,下面的一个比另一个更好:

fd = open("/dev/shm/myshm.file", O_CREAT|O_RDWR, S_IRUSR | S_IWUSR);
mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
Run Code Online (Sandbox Code Playgroud)

fd = shm_open("/myshm.file", O_RDWR|O_CREATE, S_IRUSR | S_IWUSR);
mem = mmap(...same as before...);
Run Code Online (Sandbox Code Playgroud)

当我在fs open下创建一个带有常规文件的文件/dev/shm,并向其转储了一堆垃圾时,我的可用内存下降了1G,我的可用磁盘空间保持不变.
这两种方法有什么区别?

c linux buffer mmap shared-memory

18
推荐指数
2
解决办法
1万
查看次数

mmap系统调用中MAP_ANONYMOUS标志的用途是什么?

man页面,

MAP_ANONYMOUS
              The mapping is not backed by any file; its contents are initialized to zero.  The fd and offset arguments are ignored; however, some implementations  require
              fd  to  be  -1  if  MAP_ANONYMOUS  (or  MAP_ANON)  is  specified, and portable applications should ensure this.  The use of MAP_ANONYMOUS in conjunction with
              MAP_SHARED is only supported on Linux since kernel 2.4.
Run Code Online (Sandbox Code Playgroud)

使用目的是MAP_ANONYMOUS什么?任何一个例子都会很好.还要从哪里映射内存?

man页面上写的The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux …

linux memory memory-management mmap system-calls

18
推荐指数
1
解决办法
1万
查看次数

当使用PROT_READ时,mmap MAP_SHARED和MAP_PRIVATE之间是否有区别?

如果我创建mmap(2)一个文件用prot的参数,PROT_READ只和文件支持它也是只读的,没有变化,有没有之间的性能差异(或根本任何区别)MAP_SHAREDMAP_PRIVATE?内核会在两者之间做些不同的事吗?

(文档仅指"更新"方面的行为差异,但因为它PROT_READ不存在更新.我想知道是否还有其他差异?)

c linux mmap linux-kernel

17
推荐指数
1
解决办法
5049
查看次数

malloc() - 它是否使用brk()或mmap()

c代码:

// program break mechanism
// TLPI exercise 7-1

#include <stdio.h>
#include <stdlib.h>

void program_break_test() {
    printf("%10p\n", sbrk(0));

    char *bl = malloc(1024 * 1024);
    printf("%x\n", sbrk(0));

    free(bl);
    printf("%x\n", sbrk(0));

}

int main(int argc, char **argv) {
    program_break_test();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译以下代码时:

 printf("%10p\n", sbrk(0));
Run Code Online (Sandbox Code Playgroud)

我收到警告提示:

format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’

问题1:为什么?


在我之后malloc(1024 * 1024),程序突破似乎没有改变.

这是输出:

9b12000
9b12000
9b12000
Run Code Online (Sandbox Code Playgroud)

问题2:进程在启动以备将来使用时是否在堆上分配内存?或者编译器改变分配的时间点?否则,为什么?


[更新]摘要:brk()或mmap()

在查看TLPI并检查手册页(在TLPI的作者的帮助下)之后,现在我了解了如何malloc()决定使用brk()mmap(),如下所示:

mallopt() …

c malloc memory-management mmap sbrk

16
推荐指数
3
解决办法
9634
查看次数