I'm working on porting some code from AIX to Linux. Parts of the code use the shmat()
system call to create new files. When used with SHM_MAP
in a writable mode, one can extend the file beyond its original length (of zero, in my case):
When a file is mapped onto a segment, the file is referenced by accessing the segment. The memory paging system automatically takes care of the physical I/O. References beyond the end of the file cause the file to be extended in page-sized increments. The file cannot be extended beyond the next segment boundary.
(A "segment" in AIX is a 256 MB chunk of address space, and a "page" is usually 4 KB.)
What I would like to do on Linux is the following:
- Reserve a large-ish chunk of address space (it doesn't have to be as big as 256 MB, these aren't such large files)
- Set up the page protection bits so that a segfault is generated on the first access to a page that hasn't been touched before
- On a page fault, clear the "cause a page fault" bit and allocate committed memory for the page, allowing the write (or read) that caused the page fault to proceed
- Upon closing the shared memory area, write the modified pages to a file
I know I can do this on Windows with the VirtualProtect function, the PAGE_GUARD
memory protection bit, and a structured exception handler. What is the corresponding method on Linux to do the same? Is there perhaps a better way to implement this extend-on-write functionality on Linux?
I've already considered:
- using
mmap()
with some fixed large-ish size, but I can't tell how much of the file was written to by the application code - allocating an anonymous shared memory area of large-ish size, but again I can't tell how much of the area has been written
mmap()
by itself does not seem to provide any facility to extend the length of the backing file
Naturally I would like to do this with only minimal changes to the application code.