获取Linux中内存页的起始地址
在我的代码中,我需要跟踪一些正在修改的页面。最初,我只授予它们读取访问权限,但在信号处理程序上,我授予它们读取和写入访问权限(我不会解释这一切的目的,并且信号处理程序中实际上有更多代码,我'没有显示)。
现在我的问题是如何从驻留在该页面的内存地址中获取该页面的起始地址。所以基本上我需要实现代码中显示的 get_page_start_addr 。到目前为止,我只对一个页面执行此操作,我的程序知道其起始地址。但现在,由于我需要对多个页面执行此操作,因此我需要从任意内存地址获取页面的起始地址,因为 mprotect 只接受起始页面地址作为有效参数。
static void memory_change_handler(int sig, siginfo_t *si, void *unused)
{
long addr = (long)si->si_addr;
long page_start_addr = get_page_start_addr( addr );
if (mprotect((void*)page_start_addr, pagesize, PROT_READ | PROT_WRITE) == -1)
{
print_error();
handle_error("mprotect");
}
}
In my code, I need to keep track of some pages which are being modified. Initially I give only read access to them, but on the signal handler I give them both read and write access (I am not going to explain what is the purpose for all that and there is actually more code in the signal handler, which I've not shown).
Now my question is how to get the starting address of a page from a memory address which resides in that page. So basically I need to implement the get_page_start_addr shown here in the code. Up till now, I was only doing it for a single page, whose starting address my program knew. But now, since I need to do it for multiple pages, I need to get the starting address of the page from any arbitrary memory address, because mprotect only accepts starting page address as valid argument.
static void memory_change_handler(int sig, siginfo_t *si, void *unused)
{
long addr = (long)si->si_addr;
long page_start_addr = get_page_start_addr( addr );
if (mprotect((void*)page_start_addr, pagesize, PROT_READ | PROT_WRITE) == -1)
{
print_error();
handle_error("mprotect");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 Linux 中(我猜在其他操作系统中也是如此),页面在页面边界处对齐。因此,如果您知道
PAGE_SIZE
,那么您可以通过屏蔽较低的地址位来简单地获取页面的开头。In Linux (in other OSes too, I guess), pages are aligned at page boundaries. Thus, if you know your
PAGE_SIZE
, then you can simply get the start of the page by masking the lower address bits.要方便地了解您的页面大小,请使用 sysconf(_SC_PAGESIZE)。
To portably know your pagesize, use
sysconf(_SC_PAGESIZE)
.您可以采用该地址(无符号长整型)/pagesize 和 *pagesize。
这为您提供了逻辑地址的首页地址。
You can take that address (unsigned long) /pagesize and *pagesize.
This gives you the first page address of your logical address.