首页 > 系统相关 >Notes: Understanding the linux kernel Chapter 9 Process Address Space

Notes: Understanding the linux kernel Chapter 9 Process Address Space

时间:2024-05-30 14:22:45浏览次数:19  
标签:Chapter kernel struct Space mm region address vm memory

Process Address Space

When a User Mode process asks for dynamic memory, it doesn’t get additional page frames; instead, it gets the
right to use a new range of linear addresses, which become part of its address space. This interval is called a “memory region”.

The Process's Address Space

The address space of a process consists of all linear addresses that the process is allowed to use.

The kernel represents intervals of linear addresses by means of resources called memory regions, which are characterized by an initial linear address, a length, and some access rights.

The Memory Descriptor

All information related to the process address space is included in an object called the memory descriptor of type mm_struct.

All memory descriptors are stored in a doubly linked list. Each descriptor stores the address of the adjacent list items in the mmlist field. The first element of the list is the mmlist field of init_mm, the memory descriptor used by process 0 in the initialization phase. The list is protected against concurrent accesses in multiprocessor systems by
the mmlist_lock spin lock.

The mm_users field stores the number of lightweight processes that share the mm_struct data structure.The mm_count field is the main usage counter of the memory descriptor; all “users” in mm_users count as one unit in mm_count. all “users” in mm_users count as one unit in mm_count.If the kernel wants to be sure that the memory descriptor is not released in the middle of a lengthy operation, it might increase the mm_users field instead of mm_count(this is what the try_to_unuse() function does). The final result is the same because the increment of mm_users ensures that mm_count does not become zero even if all lightweight processes that own the memory descriptor die.

Memory Descriptor of Kernel Threads

To avoid useless TLB and cache flushes, a kernel thread uses the set of Page Tables of the last previously running regular process.

mm and active_mm

The mm field in the process descriptor points to the memory descriptor owned by the process, while the active_mm field points to the memory descriptor used by the process when it is in execution. For regular processes, the two fields store the same pointer. Kernel threads, however, do not own any memory descriptor, thus their mm field is always NULL.

the page table of kernel

every time a high linear address has to be remapped, the kernel updates a canonical set of Page Tables rooted at the swapper_pg_dir master kernel Page Global Directory. This Page Global Directory is pointed to by the pgd field of a master memory descriptor, which is stored in the init_mm variable.

Memory Regions

Linux implements a memory region by means of an object of type vm_area_struct;Each memory region descriptor identifies a linear address interval. The vm_start field contains the first linear address of the interval, while the vm_end field contains the first linear address outside of the interval; vm_end–vm_start thus denotes the length of the memory region. The vm_mm field points to the mm_struct memory descriptor of the process that owns the region.

Memory regions owned by a process never overlap, and the kernel tries to merge regions when a new one is allocated right next to an existing one. Two adjacent regions can be merged if their access rights match.

The vm_ops field points to a vm_operations_struct data structure, which stores the methods of the memory region.

Memory Region Data Structures

All the regions owned by a process are linked in a simple list(also managed in rb-tree). Regions appear in the list in ascending order by memory address;successive regions can be separated by an area of unused memory addresses. The vm_next field of each vm_area_struct element points to the next element in the list. The kernel finds the memory regions through the mmap field of the process memory descriptor, which points to the first memory region descriptor in the list.

In general, the red-black tree is used to locate a region including a specific address, while the linked list is mostly useful when scanning the whole set of regions.

Memory Region Access Rights

rights associated with the pages of a memory region must be duplicated in all the corresponding Page Table entries, so that checks can be directly performed by the Paging Unit circuitry.

The initial values of the Page Table flags are stored in the vm_page_prot field of the vm_area_struct descriptor. When adding a page, the kernel sets the flags in the corresponding Page Table entry according to the value of the vm_page_prot field.

Memory Region Handling

Finding the closest region to a given address:find_vma()

/* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);

/* find_vma_prev() - Find the VMA for a given address, or the next vma and set %pprev to the previous VMA, if any.*/
struct vm_area_struct *
find_vma_prev(struct mm_struct *mm, unsigned long addr, struct vm_area_struct **pprev)

It locates the first memory region whose vm_end field is greater than addr and returns the address of its descriptor; if no such region exists, it returns a NULL pointer. Notice that the region selected by find_vma( ) does not necessarily include addr because addr may lie outside of any memory region.

Finding a region that overlaps a given interval: find_vma_intersection()

/**
 * find_vma_intersection() - Look up the first VMA which intersects the interval
 * @mm: The process address space.
 * @start_addr: The inclusive start user address.
 * @end_addr: The exclusive end user address.
 *
 * Returns: The first VMA within the provided range, %NULL otherwise.  Assumes
 * start_addr < end_addr.
 */
struct vm_area_struct *find_vma_intersection(struct mm_struct *mm,
					     unsigned long start_addr,
					     unsigned long end_addr);

The function returns a NULL pointer if no such region exists.

Finding a free interval: get_unmapped_area()

unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
		unsigned long pgoff, unsigned long flags)
{
    ......
  	if (file && file->f_op && file->f_op->get_unmapped_area)
		return file->f_op->get_unmapped_area(file, addr, len,
						pgoff, flags);

	return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
}

The get_unmapped_area( ) function searches the process address space to find an available linear address interval. The len parameter specifies the interval length, while a non-null addr parameter specifies the address from which the search must be started. If the search is successful, the function returns the initial address of the new interval; otherwise, it returns the error code -ENOMEM.

basing on whether the linear address interval should be used for a file memory mapping or for an anonymous memory mapping, invoking f_op->get_unmapped_area() or mm->get_unmapped_area().(as code told us)

In the latter case, the function executes the get_unmapped_area method of the memory descriptor. In turn, this method is implemented by either the arch_get_unmapped_area() function, or the arch_get_unmapped_area_topdown() function, according to the memory region layout of the process. every process can have two different layouts for the memory regions allocated through the mmap() system call: either they start from the linear address 0x40000000 and grow towards higher addresses, or they start right above the User Mode stack and grow towards lower addresses.

flow of arch_get_unmapped_area() see page 368.

Inserting a region in the memory descriptor list insert_vm_struct()

/* Insert vm structure into process list sorted by address
 * and into the inode's i_mmap tree.  If vm_file is non-NULL
 * then i_mmap_rwsem is taken here.
 */
int insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vma);

static inline void
__vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
		struct vm_area_struct *prev);

Allocating a Linear Address Interval

the do_mmap( ) function creates and initializes a new memory region for the current process.

static inline unsigned long do_mmap(struct file *file, unsigned long addr,
	unsigned long len, unsigned long prot,
	unsigned long flag, unsigned long offset);

param

  • file and offset

    File object pointer file and file offset offset are used if the new memory region will map a file into memory.(both NULL if no file mapping required)

  • addr

    This linear address specifies where the search for a free interval must start.

  • len

    The length of the linear address interval.

  • prot

    This parameter specifies the access rights of the pages included in the memory region. Possible flags are PROT_READ, PROT_WRITE, PROT_EXEC, and PROT_NONE.

  • flag

    This parameter specifies the remaining memory region flags.

do_mmap_pgoff()

The do_mmap( ) function performs some preliminary checks on the value of offset and then executes the do_mmap_pgoff() function.

steps of the do_mmap_pgoff() for anonymous memory regions:

  1. Checks whether the parameter values are correct and whether the request can be satisfied.(normally, ask the resource exceeded limitation)
  2. Invokes get_unmapped_area() to obtain a linear address interval for the new region.
  3. Computes the flags of the new memory region by combining the values stored in the prot and flags parameters.
  4. Invokes find_vma_prepare() to locate the object of the memory region that shall precede the new interval, as well as the position of the new region in the redblack tree.
  5. Checks whether inserting the new memory region causes the size of the process address space ((mm->total_vm << PAGE_SHIFT) + len) to exceed the threshold.
  6. call vma_merge() if areas can merge.
  7. Allocates a vm_area_struct data structure for the new memory region by invoking the kmem_cache_alloc( ) slab allocator function.
  8. Initializes the new memory region object.
  9. If the MAP_SHARED flag is set (and the new memory region doesn’t map a file on disk), the region is a shared anonymous region: invokes shmem_zero_setup() to initialize it. Shared anonymous regions are mainly used for interprocess communications;
  10. Invokes vma_link() to insert the new region in the memory region list and redblack tree.
  11. Increases the size of the process address space stored in the total_vm field of the memory descriptor.
  12. If the VM_LOCKED flag is set, it invokes make_pages_present( ) to allocate all the pages of the memory region in succession and lock them in RAM.
  13. Finally, it terminates by returning the linear address of the new memory region.

Releasing a Linear Address Interval

The do_munmap() function

int do_munmap(struct mm_struct *mm, unsigned long start, size_t len);

The function goes through two main phases. In the first phase, it scans the list of memory regions owned by the process and unlinks all regions included in the linear address interval from the process address space. In the second phase, the function updates the process Page Tables and removes the memory regions identified in the first phase.

The split_vma() function

/*
 * Split a vma into two pieces at address 'addr', a new vma is allocated
 * either for the first part or the the tail.
 */
int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long addr, int new_below);

The unmap_region() function

/*
 * Get rid of page table information in the indicated region.
 *
 * Called with the page table lock held.
 */
static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma,
	struct vm_area_struct *prev, unsigned long start, unsigned long end);

The unmap_region() function walks through a list of memory regions and releases the page frames belonging to them. It acts on five parameters: a memory descriptor pointer mm, a pointer vma to the descriptor of the first memory region being removed, a pointer prev to the memory region preceding vma in the process’s list, and two addresses start and end that delimit the linear address interval being removed.

Page Fault Exception Handler(vacant, not important now)

Creating and Deleting a Process Address Space

Creating a Process Adress Space

kernel invokes the copy_mm( ) function while creating a new process. This function creates the process address space by setting up all Page Tables and memory descriptors of the new process.

traditional processes inherit the address space of their parent: pages stay shared as long as they are only read. When
one of the processes attempts to write one of them, however, the page is duplicated;

Deleting a process Address Space

标签:Chapter,kernel,struct,Space,mm,region,address,vm,memory
From: https://www.cnblogs.com/syp2023/p/18207659

相关文章

  • Chapter 4 证明技巧
    证明技巧:思路图使用公理系统时,证明的「构思过程」与证明的「书写过程」大相径庭。思考过程往往从最后一步开始,逐步规约。来看两个例子传递律的证明\[A\rightarrowB,B\rightarrowC\vdashA\rightarrowC\]Thinking&Writing...换位律的证明\[\vdash(A\rightarrow(B\ri......
  • 深入探讨Function Calling:在Semantic Kernel中的应用实践
    引言上一章我们熟悉了OpenAI的functioncalling的执行原理,这一章节我们讲解一下functioncalling在SemanticKernel的应用。在OpenAIPromptExecutionSettings跟LLM交互过程中,ToolCallBehavior的属性之前我们的章节有介绍过ToolCallBehavior:属性用于获取或设置如何......
  • Chapter 4 Problems
    T1证明\(\negA\rightarrowB,\negA\rightarrow\negB\vdashA\)可用定理:\(\vdash(\negA\rightarrowA)\rightarrowA\)Proof\[\begin{aligned}A_1:\quad&\negA\rightarrowB&\in\Gamma\\A_2:\quad&\negA\rightarrow......
  • Unleashing Robotics: Mastering Quaternion Kinematics with Python - Chapter7(原创
    UnleashingRobotics:MasteringQuaternionKinematicswithPython-Chapter7(原创系列教程)本系列教程禁止转载,主要是为了有不同见解的同学可以方便联系我,我的邮箱[email protected].使用截断级数的近似方法在状态估计问题中,我们通常使用一个称为状态转移矩阵......
  • 安装centos开机出现Kernel panic - not syncing: Attempted to kill init无法启动解决
    一、安装centos开机出现Kernelpanic-notsyncing:Attemptedtokillinit无法启动的解决方法  装系统总会遇到各种新鲜问题,不过不要紧,只问题才能提升解决问题的能力,今天重新装了个CENTOS6.5的64位版,可能是进行了分区(boot单独挂载到了一个分区),开机时centos报错:Kernelp......
  • WorldSpace下的合批策略与ScreenSpace有什么区别
    1)WorldSpace下的合批策略与ScreenSpace有什么区别2)在iOS上用Metal取代OpenGL的多么3)在动画蓝图中将两个或多个动画同时融合到同一个网格4)Mipmap如何限定层级这是第387篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和......
  • Linux内核Kernel启动过程
    在上一篇计算机启动过程文章中介绍了计算机启动的基本流程,本篇文章主要介绍Linux内核Kernel的启动过程。一、内核启动的基本流程sequenceDiagramparticipantBootloaderparticipantKernelparticipantInitProcessBootloader->>Kernel:加载内核映像Kernel->>Kernel:内......
  • 容器基础-- namespace,Cgroup 和 UnionFS
    Namespace什么是Namespace?这里的“namespace”指的是Linuxnamespace技术,它是Linux内核实现的一种隔离方案。简而言之,Linux操作系统能够为不同的进程分配不同的namespace,每个namespace都具有独立的资源分配,从而实现了进程间的隔离。如果你的Linux安装了GCC......
  • Unleashing Robotics: Mastering Quaternion Kinematics with Python - Chapter6(原创
    UnleashingRobotics:MasteringQuaternionKinematicswithPython-Chapter6(原创系列教程)(最关键一章)本系列教程禁止转载,主要是为了有不同见解的同学可以方便联系我,我的邮箱[email protected]第6章旋转的数值积分方法和角误差理论1.Runge-Kutta数值积分方法我......
  • AoPS - Chapter 19 Probability
    本章介绍了一些概率的基本概念与条件概率。独立与互斥Twoeventsarecalleduncorrelated(orindependent)(独立)iftheyhavenobearingoneachother.\[P(A\capB)=P(A)\timesP(B)\]Twoeventsarecalledmutuallyexclusive(互斥)ifbotheventscannotsimultaneou......