Creating a Memory Mapping

To create a new memory mapping, a process issues an mmap( ) system call, passing the following parameters to it:

• A file descriptor identifying the file to be mapped.

• An offset inside the file specifying the first character of the file portion to be mapped.

• The length of the file portion to be mapped.

• A set of flags. The process must explicitly set either the map_shared flag or the map_private flag to specify the kind of memory mapping requested.-4

[41 The process could also set the map_anonymous flag to specify that the new memory region is anonymous — that is, not associated with any disk-based file (see Section 8.4.3). This flag is supported by some Unix operating systems, including Linux, but it is not defined by the POSIX standard. In Linux 2.4, a process can also create a memory region that is both MAP_SHARED and map_anonymous. In this case, the region maps a special file in the shm filesystem (see Section 19.3.5), which can be accessed by all the process's descendants.

• A set of permissions specifying one or more types of access to the memory region: read access (prot_read), write access (prot_write), or execution access

• An optional linear address, which is taken by the kernel as a hint of where the new memory region should start. If the map_fixed flag is specified and the kernel cannot allocate the new memory region starting from the specified linear address, the system call fails.

The mmap( ) system call returns the linear address of the first location in the new memory region. For compatibility reasons, in the 80 x 86 architecture, the kernel reserves two entries in the system call table for mmap( ) : one at index 90 and the other at index 192. The former entry corresponds to the old_mmap( ) service routine (used by older C libraries), while the latter one corresponds to the sys_mmap2( ) service routine (used by recent C libraries). The two service routines differ only in how the six parameters of the system call are passed. Both of them end up invoking the do_mmap_pgoff( ) function described in Section 8.3.4. We now complete that description by detailing the steps performed only when creating a memory region that maps a file.

1. Checks whether the mmap file operation for the file to be mapped is defined; if not, it returns an error code. A null value for mmap in the file operation table indicates that the corresponding file cannot be mapped (for instance, because it is a directory).

2. Checks whether the get_unmapped_area method of the file object is defined. If so, invokes it; otherwise, invokes the arch_get_unmapped_area( ) function already described in Chapter 8. On the 80 x 86 architecture, a custom method is used only by the frame buffer layer, so we don't discuss the case further. Remember that the arch_get_unmapped_area( ) allocates an interval of linear addresses for the new memory region.

3. In addition to the usual consistency checks, compares the kind of memory mapping requested and the flags specified when the file was opened. The flags passed as a parameter of the system call specify the kind of mapping required, while the value of the f_mode field of the file object specifies how the file was opened. Depending on these two sources of information, it performs the following checks:

a. If a shared writable memory mapping is required, checks that the file was opened for writing and that it was not opened in append mode (o_append flag of the open( ) system call)

b. If a shared memory mapping is required, checks that there is no mandatory lock on the file (see Section 12.7)

c. For any kind of memory mapping, checks that the file was opened for reading

If any of these conditions is not fulfilled, an error code is returned.

4. When initializing the value of the vm_flags field of the new memory region descriptor, sets the vm_read, vm_write, vm_exec, vm_shared, vm_mayread, vm_maywrite, vm_mayexec, and vm_mayshare flags according to the access rights of the file and the kind of requested memory mapping (see Section 8.3.2). As an optimization, the vm_shared flag is cleared for nonwritable shared memory mapping. This can be done because the process is not allowed to write into the pages of the memory region, so the mapping is treated the same as a private mapping; however, the kernel actually allows other processes that share the file to access the pages in this memory region.

5. Initializes the vm_file field of the memory region descriptor with the address of the file object and increments the file's usage counter.

6. Invokes the mmap method for the file being mapped, passing as parameters the address of the file object and the address of the memory region descriptor. For most filesystems, this method is implemented by the generic_file_mmap( ) function, which performs the following operations:

a. If a shared writable memory mapping is required, checks that the writepage method of the address_space object of the file is defined; if not, it returns the error code -einval.

b. Checks that the readpage method of the address_space object of the file is defined; if not, it returns the error code -enoexec.

c. Stores the current time in the i_atime field of the file's inode and marks the inode as dirty.

d. Initializes the vm_ops field of the memory region descriptor with the address of the generic_file_vm_ops table. All methods in this table are null, except the nopage method, which is implemented by the filemap_nopage( ) function.

7. Recall from Section 8.3.4 that do_mmap( ) invokes vma_link( ) . This function inserts the memory region descriptor into either the i_mmap list or the i_mmap_shared list of the address_space object, according to whether the requested memory mapping is private or shared, respectively.

Continue reading here: Returns the address of the requested page 1525 Flushing Dirty Memory Mapping Pages to Disk

Was this article helpful?

0 0