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

时间:2018-02-20 10:51:22

标签: 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

这是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

为什么我们在没有指定mmap标志的情况下匿名地映射为什么MAP_PRIVATE失败?

1 个答案:

答案 0 :(得分:5)

您不需要MAP_PRIVATE,需要MAP_PRIVATEMAP_SHARED之一。

  

flags参数确定是否对映射进行更新          映射相同区域的其他进程可见,以及是否          更新将传递到基础文件。这种行为是          通过在flags中包含以下其中一个值来确定:

     

MAP_SHARED
                分享这个映射。 [...]

     

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

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

  • MAP_PRIVATE由文件备份 映射同一文件的其他进程无法看到更新 没有更新写入后备文件 更新到COW页面。

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

  • MAP_PRIVATE | MAP_ANONYMOUS(例如由文件备份)
    没有要更新的文件 更新到COW页面。

    用于分配内存,不与分叉进程共享。

  • MAP_SHARED由文件备份 其他进程可以看到更新 更新将传播到后备文件。

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

  • MAP_SHARED | MAP_ANONYMOUS(例如由文件备份)
    对于映射了相同区域的所有进程,可以看到更新 没有要更新的文件。

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