如何判断内存页面是否标记为只读?

时间:2008-11-02 01:53:58

标签: memory copy-on-write

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

4 个答案:

答案 0 :(得分:3)

在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和名称内存映射文件。

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

如果您使用的是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以处理异常。

答案 3 :(得分:1)

你是在谈论通过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 */