CSE 330: Operating Systems - Fall 2022
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
Project 3: Memory Management
CSE 330: Operating Systems - Fall 2022
Due by 22nd November, 11:59 pm
Summary
To support multiprogramming, modern OSes present virtual memory to processes so that each process sees a contiguous logical memory address space which may not be contiguous in physical memory and may not be completely in memory. The OS maintains the mapping between a process’ virtual memory and the computer’s physical memory through the process’ page table. Every page table entry stores the mapping information of a virtual page, indicating whether the page is present in memory and, if yes, the physical frame number it is mapped to. Additional data structures track the temporarily swapped pages from memory to disk.
In Project 3, we will implement new kernel functions to reveal the “magic” that the kernel does to virtualize memories, using the same virtual machine environment you prepared in the previous projects. This project will help you understand how a real-world OS like Linux performs memory management and master the skills to implement it in kernel space
Description
In this project; you will implement a kernel module to walk the page tables of a given process and find out how many of the process’ pages are present in the physical memory (resident set size--RSS), how many are swapped out to disk (swap size--SWAP), and how many pages are in the process working set (working set size--WSS).
1. Module interface and module_init
You must name your module “memory_manager”. It takes a process ID as the only command-line input argument. Name your input argument “pid”. Like Project 2, you will use the module_param() macro to pass the input argument to your kernel module. Call this macro at the beginning of your module code.
module_param(name, type, perm) /* macro for module command line parameters. name is the name of the parameter, type is the type of the parameter, and perm sets the visibility in sysfs. For example, module_param(buff_size, int, 0) defines an input argument named buffer_size, type is int, and the default value is 0.*/ |
Reference on passing command line arguments to a kernel module.
2. Traverse Memory regions
Linux organises process memory using the mm_structdata structure, which is a member of task_struct. It contains information regarding all memory regions for that process, organised as a list, mmap. Memory regions are the kernel representation of allocated address intervals, characterised by a starting address, a length, and access rights. Each memory region is described by a vm_area_struct (VMA). Each VMA contains a starting (vm_start) and ending address (vm_end) for its region. The general organisation of these structures is shown in Figure 1. In your code, you must go through each VMA, and within each VMA, you must check each page. Make sure to loop through this address range by PAGE_SIZE.
Figure 1
task_struct *task;
task->mm->mmap
/* the list of VMAs. struct mm_struct is located in
include/linux/mm_types.h */
3. Walk Page Tables
For each valid page in the given process’ address space; you need to walk the process’ page tables to find out if the page is present in physical memory or in the swap.
The Linux kernel (5.16) implements a 5-level page table with the following five levels: PGD, P4D, PUD, PMD, and PTE (see Figure 2). The following tables can be accessed in order, starting from the mm_struct of the process. The mm_struct can be found in the process task_struct.
Figure 2
pgd_offset(mm, address) /* Return pointer to the PGD. mm is the mm_struct of the process, address is the logical address in the virtual memory space*/
p4d_offset(pgd_t *pgd, unsigned long address) /* Return pointer to the P4D. pgd is the pointer of PGD, address is the logical address in the virtual memory space.*/
pud_offset(pgd_t *p4d, unsigned long address) /* Return pointer to the PUD. p4d is the pointer of P4D, address is the logical address in the virtual memory space.*/
pmd_offset(pgd_t *pud, unsigned long address) /* Return pointer to the PMD. pud is the pointer of PUD, address is the logical address in the virtual memory space.*/
pte_offset_map(pgd_t *pmd, unsigned long address) /* Return pointer to the PTE. pmd is the pointer of PMD, address is the logical address in the virtual memory space*/ pte_present(pte) /* Return 1 if a page table entry is in the main memory, pte is a pointer to the page table entry.*/
/*Required header file: <linux/mm.h>*/ |
A simple example of the page table walk is the function __follow_pte_pmd() in mm/memory.c
pgd_t *pgd; p4d_t *p4d; pmd_t *pmd; pud_t *pud; pte_t *ptep, pte;
pgd = pgd_offset(mm, address); // get pgd from mm and the page address if (pgd_none(*pgd) | | pgd_bad(*pgd)) { // check if pgd is bad or does not exist return; } p4d = p4d_offset(pgd, address); //get p4d from from pgd and the page address if (p4d_none(*p4d) | | p4d_bad(*p4d)) { // check if p4d is bad or does not exist return; } pud = pud_offset(p4d, address); // get pud from from p4d and the page address if (pud_none(*pud) | | pud_bad(*pud)) { // check if pud is bad or does not exist< |
2022-11-06