【问题标题】:How can you tell if a memory page is marked as read-only?如何判断内存页是否标记为只读?
【发布时间】:2008-11-02 01:53:57
【问题描述】:

当使用写时复制语义在进程之间共享内存时,如何测试内存页是否可写或是否标记为只读?这可以通过调用特定的汇编代码、读取内存中的某个位置或通过操作系统的 API 来完成吗?

【问题讨论】:

    标签: memory copy-on-write


    【解决方案1】:

    在 Linux 上,您可以检查 /proc/pid/maps:

    $ cat /proc/self/maps
    
    002b3000-002cc000 r-xp 00000000 68:01 143009   /lib/ld-2.5.so
    002cc000-002cd000 r-xp 00018000 68:01 143009   /lib/ld-2.5.so
    002cd000-002ce000 rwxp 00019000 68:01 143009   /lib/ld-2.5.so
    002d0000-00407000 r-xp 00000000 68:01 143010   /lib/libc-2.5.so
    00407000-00409000 r-xp 00137000 68:01 143010   /lib/libc-2.5.so
    00409000-0040a000 rwxp 00139000 68:01 143010   /lib/libc-2.5.so
    0040a000-0040d000 rwxp 0040a000 00:00 0
    00c6f000-00c70000 r-xp 00c6f000 00:00 0        [vdso]
    08048000-0804d000 r-xp 00000000 68:01 379298   /bin/cat
    0804d000-0804e000 rw-p 00004000 68:01 379298   /bin/cat
    08326000-08347000 rw-p 08326000 00:00 0
    b7d1b000-b7f1b000 r--p 00000000 68:01 226705   /usr/lib/locale/locale-archive
    b7f1b000-b7f1c000 rw-p b7f1b000 00:00 0
    b7f28000-b7f29000 rw-p b7f28000 00:00 0
    bfe37000-bfe4d000 rw-p bfe37000 00:00 0        [stack]
    

    第一列是虚拟内存地址范围,第二列包含权限(读、写、执行和私有),第 3-6 列包含偏移量、主要和次要设备号、inode 和名称内存映射文件。

    【讨论】:

      【解决方案2】:

      在 Win32 上,最好的方法是使用VirtualQuery。它为地址所在的页面返回MEMORY_BASIC_INFORMATION。其中一个成员是Protect,它是these 标志的某种组合,其中包含可能的保护模式。该函数还告诉您内存是空闲的、已提交的、保留的,以及它是私有的、图像的一部分还是共享内存部分。

      操作系统的 API 是确定页面保护的最佳方式。 CPU 从页面描述符中读取保护模式,该页面描述符只能从内核模式访问。

      【讨论】:

      • Chris 的评论对于 Windows 是正确的。请务必在下方查看 Jim Nelson 的评论和 Raymond Chen 的博客。
      【解决方案3】:

      您是在谈论通过 shmget(在 Unix 上)分配的各种共享内存吗?即

      int shmget(key_t, size_t, int);
      

      如果是这样,您可以使用查询该内存

      int shmctl(int, int, struct shmid_ds *);
      

      例如:

      key_t key = /* your choice of memory api */
      int flag = /* set of flags for your app */
      int shmid = shmget(key, 4096, flag);
      
      struct shmid_ds buf;
      int result = shmctl(shmid, IPC_STAT, &buf);
      /* buf.ipc_perm.mode contains the permissions for the memory segment */
      

      【讨论】:

        【解决方案4】:

        如果您使用的是 Win32,则有 IsBadReadPtr 和 IsBadWritePtr 调用。但是,不鼓励使用它们:

        "The general consensus is that the IsBad family of functions (IsBadReadPtr, IsBadWritePtr, and so forth) is broken and should not be used to validate pointers."

        Raymond Chen 的标题说明了一切:"IsBadXxxPtr should really be called CrashProgramRandomly"

        Chen 有一些关于如何处理这个问题的有用建议here

        结果是,您不应该在运行时测试这种东西。编写代码,以便您知道自己收到了什么,如果不是预期的,请将其视为错误。如果实在别无选择,请查看 SEH 处理异常。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-02
          • 2010-12-26
          • 2017-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-12
          相关资源
          最近更新 更多