This article refers to the source code is freebsd5.0release, reference 4.4BSD design and implementation related chapters, Matt Dillon's article.
A description of the main data structures involved in the VM system
1. Vmspace
This structure is used to describe the virtual address space of a process that contains the VM_MAP structure of platform-independent and the PMAP structure of platform dependencies, as well as some statistical measurements of the memory usage of the process.
2. Vm_map
This structure is the top-level data structure describing the platform-independent virtual address space, which contains a series of virtual address mapping entities and attributes of these mappings.
3. Vm_map_entry
The structure describes a virtual address space (Start–end), and the segment address space represents a VM object, another address map, or an address child mapping, and its corresponding shared protection and inheritance attributes.
4. Vm_object
The structure describes a data source for a virtual address space, which can describe a file, a zero memory, a device, and so on.
5. Vm_page
This structure describes a page of physical memory, a low-level data structure used by the VM to represent physical memory. The page size is determined by the platform when the system starts.
6. Pagerops (Vm_pager)
This structure describes how the background storage of VM objects is accessed, in FreeBSD, it is through the PAGEROPS structure description function pointers, realizes the concrete operation of different types of objects, in vm_object structure, specifies the data structure of specific type object through the handle member, For example, the device type corresponds to dev_t (CDEV structure pointer). In the General OS description, the Vm_pager describes the data structure for that purpose.
This article focuses on the management of FreeBSD kernel virtual address space, involving kernel address space allocation and kernel address space dynamic allocation. FreeBSD kernel space is always mapped to the highest portion of each process's address space. Like any other process, the kernel manages the use of a segment of the address space through a VM_MAP structure that contains a series of vm_map_entry structure entities. Sub-mappings are specific to kernel mappings, which are used to isolate and restrict a segment of the address space for use by kernel subsystems, such as MBUF operations. This paper mainly discusses the content of platform-independent, when it relates to platform relativity, it is i386 as an example.
1. SI_SUB_VM Initialization
at system startup, the Mi_startup () function invokes the SI_SUB_VM initialization platform-independent VM system, which is defined as: "Sysinit (Vm_mem, SI_SUB_VM, Si_order_first, Vm_mem_init, NULL) ”。 After the Vm_mem_init function is initialized, we use only virtual memory, and now we analyze the implementation of the function:
Vm_set_page_size ();
The function sets the page size, i386 is page_size (4K), and is recorded in the V_page_size member of the global variable CNT of the system statistics vmmeter struct type.
Virtual_avail = Vm_page_startup (Avail_start, Avail_end, Virtual_avail);
This statement initializes the resident memory module. Parameter and return value of the parse function Vm_page_startup: Avail_start value is from the system startup, assembly language calls Init386 first, indicating the starting address of valid memory; Avail_end at the end of the Getmemsize () function , obtained by avail_end = phys_avail[pa_indx]; statement, the function is a platform-dependent function, which is not discussed in detail, just understand that the getmemsize () function is the size of the specific physical memory; Virtual_ Avail is a virtual address that points to the first available page, obtains the initial value in the Pmap_bootstrap function before calling the Vm_page_startup function, and adjusts to the Vm_page_startup function to get the real value. function Vm_page_startup The physical memory, allocate it as a page unit, and initialize the information required for the page Management module, each page unit is placed in a free list, and the detailed discussion of the function implementation is discussed in page scheduling, Part of the domain allocator initialization that is involved in kernel management is implemented by calling the Uma_startup function in the function, which is discussed later in this function.
Vm_object_init ();
Initializes the VM's object module, which uses virtual memory through a unified vm_object structure that completes the initialization of the information required by the Virtual Memory object module (FreeBSD).
Vm_map_startup ();
Initializes the VM address mapping module.
Kmem_init (Virtual_avail, virtual_end);
This function creates a kernel virtual address mapping relationship that maps kernel text, data, BSS, and all the space already allocated when the system was started, inserting between vm_min_kernel_address and Virtual_avail, and the remaining Virtual_ The address space between avail and virtual_end is free space available.
Pmap_init (Avail_start, avail_end);
This function initializes the mapping relationship of the physical memory address space.
Vm_pager_init ();
This function implements the initialization of all the page interface types supported by the system, which provides a mechanism for the movement of data between its supported storage space and physical memory, such as between the disk device and memory, and between the file system and memory.
At this point, the Vm_mem_init function completes and the VM system initializes.
2. Kernel Address space allocation
The virtual address space segment used by the VM system kernel provides a set of functions for allocation and release, which can be allocated from kernel address mappings and child mappings.
Depending on whether the requested page can be scheduled by the Pageout daemon, there are two paths to kernel memory allocation. When the VM subsystem is initialized, the Kmem_init function is invoked to create the kernel mappings. We analyze the specific implementation of this function:
function void Kmem_init (vm_offset_t start, vm_offset_t end)
m = Vm_map_create (Kernel_pmap, vm_min_kernel_address, end);
The function vm_map_create creates a new address map m based on the given Kernel_map physical address, and vm_min_kernel_address and end gives the water level (lower address bound) and the upper level of the mapping range ( Upper address bound).
Kernel_map = m;
Kernel_map->system_map = 1;
(void) Vm_map_insert (M, NULL, (vm_offset_t) 0,
Vm_min_kernel_address, start, Vm_prot_all, Vm_prot_all, 0);
Vm_map_unlock (m);
Because function kmem_init is used only for system initialization, creating kernel address mappings, the resulting address mappings are assigned to the global variable Kernel_map saved, and a vm_map_entry entity record-related value is created through the Vm_map_insert function, vm_prot_ All and Vm_prot_all identify the access rights to this virtual address, see/sys/vm/vm.h definition.
2.1 Wired (nonpageable, pages that are not pageout scheduled) Assign functions
A fixed page (Wired page) never produces a page fault (page fault). Its allocation is realized by the Kmem_alloc function and the Kmem_malloc function.
function vm_offset_t Kmem_alloc (vm_map_t map, vm_size_t size)
This function is used to allocate memory in a kernel address map or a child map.
Size = round_page (size);
Adjusts the size of the application memory so that it is an integer times page_size.
Vm_map_lock (map);
if (Vm_map_findspace (map, vm_map_min (map), size, &addr)) {
Vm_map_unlock (map);
return (0);
}
offset = addr-vm_min_kernel_address;
Vm_object_reference (Kernel_object);
Vm_map_insert (map, Kernel_object, offset, addr, addr + size,
Vm_prot_all, Vm_prot_all, 0);
Vm_map_unlock (map);