为什么在映射内存时需要MAP_PRIVATE标志?

St.*_*rio 1 linux assembly x86-64

我正在尝试匿名映射内存页面。就这个:

mov rax, 0x09   ; SYS_mmap
mov rdi, 0x00   ; addr is NULL
mov rsi, 0x8000 ; x86 page_size
mov rdx, 0x02   ; PROT_WRITE
mov r10, 0x20   ; MAP_ANONYMOUS
mov r8, -1      ; fd = -1
mov r9, 0x00    ; offset = 0
syscall

mov [rax], dword -2 ; Segmentation fault, rax = -22
Run Code Online (Sandbox Code Playgroud)

这是SegFaulted。但是当我添加MAP_PRIVATE到标志时,它可以正常工作:

mov rax, 0x09   ; SYS_mmap
mov rdi, 0x00   ; addr is NULL
mov rsi, 0x8000 ; x86 page_size
mov rdx, 0x02   ; PROT_WRITE
mov r10, 0x22   ; MAP_ANONYMOUS | MAP_PRIVATE 
mov r8, -1      ; fd = -1
mov r9, 0x00    ; offset = 0
syscall

mov [rax], dword -2 ; Now it works ok, rax = 0x7ffff7ff2000
Run Code Online (Sandbox Code Playgroud)

我不太清楚为什么mmap我们为什么不指定MAP_PRIVATE标志就匿名映射呢?

Mar*_*oom 6

您不需要MAP_PRIVATE,您需要MAP_PRIVATE或之一MAP_SHARED

flags参数确定对映射的更新对于映射同一区域的其他进程是否可见,以及是否将更新进行到基础文件。通过在标志中完全包含以下值之一来确定此行为:

     MAP_SHARED
                分享此映射。[...]

     MAP_PRIVATE
                创建一个私有的写时复制映射。[...]


mmap 让您选择如何传播对映射区域所做的任何更改:

  • MAP_PRIVATE由文件备份
    没有更新对映射同一文件的其他进程可见。
    没有更新写入后备文件。将对COW页面
    进行更新。

    用于就地处理文件的内容。

  • MAP_PRIVATE | MAP_ANONYMOUS(例如,没有文件备份)
    没有文件可更新。
    将对COW页面进行更新。

    有用,可用于分配内存,不与分支进程共享。

  • MAP_SHARED由文件备份的
    更新其他进程可见。
    更新将传播到支持文件。

    对转换文件很有用。
    与使用名称的其他进程共享内存区域很有用(请参见shm_open)。

  • MAP_SHARED | MAP_ANONYMOUS(例如,通过文件备份)
    对于映射了相同区域的所有进程,更新都是可见的。
    没有要更新的文件。

    与分叉的进程共享内部存储区很有用。

  • @PeterCordes如果父级将其映射,然后派生,则子级将对其进行映射,并与彼此和父级共享。我尚未对其进行测试,但是在此处对此进行了质量检查。这与`fork`的行为一致。 (3认同)
  • 使用“MAP_SHARED |” MAP_ANONYMOUS`,任何其他进程实际上是否有可能映射“同一区域”?它是匿名的,因此没有“名称”。当与“MAP_ANONYMOUS”一起使用时,“MAP_SHARED”和“MAP_PRIVATE”之间是否有任何实际差异(包括任何奇怪的极端情况?) (2认同)