TL;DR:一个整数作为第三个参数传递。
现在让我们回答评论中的问题。如果您打开应该位于 /usr/include/asm-generic 中的 mman-common.h,您将找到这些值。
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
#define PROT_SEM 0x8 /* page may be used for atomic ops */
就在编译之前,预处理器用上面的数字替换你的参数。所以如果你有这个电话:
mprotect(myaddress, 256, PROT_READ | PROT_WRITE);
它将被以下代码替换:
mprotect(myaddress, 256, 0x1 | 0x2);
现在看看不同参数可以采用的值:它们不是随机选择的,它们是 2 的幂,因此在二进制表示法中,它们仅由一个 1 数字和零表示。
PROT_READ = 0x1 = 00000001
PROT_WRITE = 0x2 = 00000010
PROT_EXEC = 0x4 = 00000100
选择 2 的幂很方便,因为当您使用二进制 OR 时,您获得的数字结合了之前的两个值,因此这两个信息都包含在 OR-ed 数字中。
PROT_WRITE | PROT_EXEC =
00000010
| 00000100
= 00000110
现在回到我们的电话:
如果你打过电话mprotect(myaddress, 256, PROT_READ | PROT_WRITE)
,会发生的事情是那PROT_READ | PROT_WRITE
会被合并成0x1 | 0x2
,也就是0x3
。
现在在内核方面,假设PROT_READ | PROT_WRITE
是由用户编写的。内核收到参数0x3
,并想检查是否最初写入了 PROT_READ 。一种方法是这样写:
if (PROT_READ & userValue) { }
它之所以有效,是因为 userValue 包含 PROT_READ 和 PROT_WRITE 的组合版本,以二进制形式:
PROT_READ & userValue =
00000001
&& 00000011
= 00000001
如果设置了标志,则此数字非零,因此内核知道已通过标志。
希望这可以帮助。