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.

Passing data to a kernel module – module_param

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<