The page is the smallest unit of memory that can have distinct permissions and behavior. Consequently, the page is the building block of memory mappings, which in turn are the building blocks of the process address space.
Themmap()system call operates on pages. Both theaddrandoffsetparameters must be aligned on a page-sized boundary. That is, they must be integer multiples of the page size.
Mappings are, therefore, integer multiples of pages. If thelenparameter provided by the caller is not aligned on a page boundary—perhaps because the underlying file’s size is not a multiple of the page size—the mapping is rounded up to the next full page. The bytes inside this added memory, between the last valid byte and the end of the mapping, are zero-filled. Any read from that region will return zeros. Any writes to that memory will not affect the backing file, even if it is mapped asMAP_SHARED. Only the originallenbytes are ever written back to the file.
sysconf(). The standard POSIX method of obtaining the page size is withsysconf(), which can retrieve a variety of system-specific information:
long sysconf (int name);
A call to sysconf() returns the value of the configuration item name, or-1ifnameis invalid. On error, the call setserrno toEINVAL. Because-1may be a valid value for some items (e.g., limits, where-1means no limit), it may be wise to clearerrnobefore invocation, and check its value after.
POSIX defines_SC_PAGESIZE(and a synonym,_SC_PAGE_SIZE) to be the size of a page, in bytes. Therefore, getting the page size is simple:
long page_size = sysconf (_SC_PAGESIZE);
getpagesize(). Linux also provides thegetpagesize()function:
int getpagesize (void);
A call to getpagesize() will likewise return the size of a page, in bytes. Usage is even simpler than sysconf():
int page_size = getpagesize ();
Not all Unix systems support this function; it’s been dropped from the 1003.1-2001 revision of the POSIX standard. It is included here for completeness.
PAGE_SIZE. The page size is also stored statically in the macroPAGE_SIZE, which is defined in<asm/page.h>. Thus, a third possible way to retrieve the page size is:
int page_size = PAGE_SIZE;
Unlike the first two options, however, this approach retrieves the system page size at compile-time, and not runtime. Some architectures support multiple machine types with different page sizes, and some machine types even support multiple page sizes themselves! A single binary should be able to run on all machine types in a given architecture—that is, you should be able to build it once and run it everywhere. Hard-coding the page size would nullify that possibility. Consequently, you should determine the page size at runtime. Becauseaddrandoffsetare usually0, this requirement is not overly difficult to meet.
Moreover, future kernel versions will likely not export this macro to user space. We cover it in this chapter due to its frequent presence in Unix code, but you should not use it in your own programs. Thesysconf()approach is your best bet.