MetallicPriest
MetallicPriest

Reputation: 30765

Get starting address of a memory page in Linux

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");
  }
}

Upvotes: 2

Views: 4468

Answers (3)

ikari_shinji
ikari_shinji

Reputation: 3

You can take that address (unsigned long) /pagesize and *pagesize. This gives you the first page address of your logical address.

Upvotes: 0

ninjalj
ninjalj

Reputation: 43688

To portably know your pagesize, use sysconf(_SC_PAGESIZE).

Upvotes: 2

Didier Trosset
Didier Trosset

Reputation: 37437

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.

page_start = addr & ~(PAGE_SIZE-1);

Upvotes: 10

Related Questions