mprotect - 如何对齐多个pagesize有效?

时间:2010-04-08 15:20:50

标签: linux memory-management

我不理解mprotect用法中的'对齐分配的内存'部分。

我指的是http://linux.die.net/man/2/mprotect

上给出的代码示例
char *p;
char c;
/* Allocate a buffer; it will have the default
   protection of PROT_READ|PROT_WRITE. */
p = malloc(1024+PAGESIZE-1);
if (!p) {
    perror("Couldn't malloc(1024)");
    exit(errno);
}
/* Align to a multiple of PAGESIZE, assumed to be a power of two */
p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
c = p[666];         /* Read; ok */
p[666] = 42;        /* Write; ok */
/* Mark the buffer read-only. */
if (mprotect(p, 1024, PROT_READ)) {
    perror("Couldn't mprotect");
    exit(errno);
}

根据我的理解,我尝试使用PAGESIZE为16,而0010为p的地址。 我最终因(((int) p + PAGESIZE-1) & ~(PAGESIZE-1))而获得0001。

您能否澄清一下这整个'对齐'的工作原理?

谢谢,

1 个答案:

答案 0 :(得分:11)

假设PAGESIZE是2的幂(需求),则可以将整数值 x 向下舍入为PAGESIZE的倍数(x & ~(PAGESIZE-1)) 。同样,((x + PAGESIZE-1) & ~(PAGESIZE-1))会将 x 四舍五入为PAGESIZE的倍数。

例如,如果PAGESIZE为16,则为32位字的二进制:
00000000000000000000000000010000 PAGESIZE
00000000000000000000000000001111 PAGESIZE-1
11111111111111111111111111110000 ~(PAGESIZE-1)
具有上述值的按位和(&)将清除该值的低4位,使其成为16的倍数。

也就是说,描述中引用的代码来自手册页的旧版本,并且不好,因为它浪费内存而不能在64位系统上运行。最好使用posix_memalign() or memalign()来获取已正确对齐的内存。当前版本的mprotect()手册页上的示例使用memalign()posix_memalign()的优势在于它是POSIX标准的一部分,并且在不同的系统上没有不同的行为,例如旧的非标准memalign()