INFR100792023 CW2 slides

Operating Systems Coursework 2

Operating Systems
Coursework 2

Coursework 2: Memory management/mapping
DUE: 19/03/2024 12:00PM

All deadlines are strict and fall on a Tuesday at 12PM GMT

Marking & Late submission

Last version of submission will be marked

Coursework 2

● Managing and Manipulating the Memory subsystem of Linux

● Modifying Linux kernel source code

● Develop a Kernel module

Background

● Linux kernel version: 6.1

● Use DICE machines

● Role of the VM: for testing and user-space applications

● All dependencies are installed

● What do you learn for this coursework?

● virtual memory, physical memory, page tables, memory mapping,

memory allocation, and page walking

Basically, it maps files or devices into memory

Faster: replace IO operations to memory operation, because the file is loaded into memory.

Shared: multiple process’s virtual memory can be mapped to point the same memory content

void *mmap(void addr[.length], size_t length, int prot, int flags, int fd, off_t offset);

Addr: the starting mapping address, could be NULL

Length: the mapping range size

Prot: expected protected flag for mapped memory

flags: Type of mmapping memory

Fd: File descriptor

Offset: The offset of mapping are, for example, map a range in the mid of a file

mmap EXAMPLE:

int EXAMPLE_FD =open(EXAMPLE_FILE, EXAMPLE_FLAG, EXAMPLE_MODE); EXAMPLE_LEN=2024; EXAMPLE_OFFSET=0305;

if(EXAMPLE_FD <0) return DEAD; Pointer=mmap(NULL, EXAMPLE_LEN , EXAMPLE_PROT, EXAMPLE_MAP_FLAG, EXAMPLE_FD , EXAMPLE_OFFSET); Hardware devices are accessed by the user through special device files. These files are grouped into the /dev directory, and system calls open, read, write, close, lseek, mmap etc. are redirected by the operating system to the device driver associated with the physical device. To create a device type file, use the mknod command; the command receives the type (block or character), major and minor of the device (mknod name type major minor) For the driver code, you need reimplement the file operations static int system_nut_example_mmap_that_does_nothing(struct file *filp) static struct file_operations system_nut_fops = { .mmap = system_nut_example_mmap_that_does_nothing, EXAMPLE_OFFSET EXAMPLE_LEN Pointer1=mmap(NULL, EXAMPLE_LEN , EXAMPLE_PROT, EXAMPLE_MAP_FLAG, EXAMPLE_FD , EXAMPLE_OFFSET); Pointer2=mmap(NULL, EXAMPLE_LEN , EXAMPLE_PROT, EXAMPLE_MAP_FLAG, EXAMPLE_FD , EXAMPLE_OFFSET); Task1 Shared Memory ● Develop a kernel module ● Create a char device and allow memory mapping from multiple user-space applications ● Customized the mmap function in kernel module for triggering the shared memory though the char device ● Kernel module allocate a PAGE_SIZE shared memory upon init for sharing ● Insert your kernel module and create the char dev ● Develop a user space application that mmap to the char dev ● Launch 2 apps to mmap the dev to test your changes Proc interface We have inserted modules to the kernel and can get them do something useful. But how to get some information from the kernel. We need to be able to get some information from the kernel. Proc interface is being used by kernel to communicate information to the userspace and take input from the userspace. For example: file /proc/mounts is a file which lists the file systems which are mounted on the system. Proc interface example /fs/proc/example_that_does_nothing.c // SPDX-License-Identifier: GPL-2.0 #include

#include

#include

#include

static int system_nut_does_nothing_open(struct inode *inode, struct file *file) { return 0;}

static const struct proc_ops system_nut_proc_ops = {

.proc_open = system_nut_does_nothing_open,

static int init proc_cpuinfo_init(void) {

proc_create(“system_nut_does_nothing_proc_interface”, 0, NULL, &system_nut_proc_ops);

fs_initcall(proc_cpuinfo_init);

https://elixir.bootlin.com/linux/v6.1.7/source/include/linux/fs.h
https://elixir.bootlin.com/linux/v6.1.7/source/include/linux/init.h
https://elixir.bootlin.com/linux/v6.1.7/source/include/linux/proc_fs.h
https://elixir.bootlin.com/linux/v6.1.7/source/include/linux/seq_file.h
https://elixir.bootlin.com/linux/v6.1.7/C/ident/cpuinfo_open
https://elixir.bootlin.com/linux/v6.1.7/C/ident/inode
https://elixir.bootlin.com/linux/v6.1.7/C/ident/inode
https://elixir.bootlin.com/linux/v6.1.7/C/ident/file
https://elixir.bootlin.com/linux/v6.1.7/C/ident/file
https://elixir.bootlin.com/linux/v6.1.7/C/ident/proc_ops
https://elixir.bootlin.com/linux/v6.1.7/C/ident/proc_open
https://elixir.bootlin.com/linux/v6.1.7/C/ident/proc_cpuinfo_init
https://elixir.bootlin.com/linux/v6.1.7/C/ident/fs_initcall
https://elixir.bootlin.com/linux/v6.1.7/C/ident/proc_cpuinfo_init

Proc interface per pid

The /proc// has many process related proc interface

Those are implemented in /fs/proc/base.c, same idea for normal proc interface

In the tid_base_stuff[], it defines the process related proc interface files

In the tgid_base_stuff[], it defines the thread related proc interface files

However, we will do this for you!

You need to implement the function, in another file, the fs/proc/memstats.c

int proc_pid_memstats(struct seq_file *m, sturuct pid_namespace *ns, struct pid

*pid, struct task_struct *task)

How to Walk VMA

● Walk the VMA by hand
● struct vm_area_struct> virtual memory area, each area is a range of continues

virtual memory
● VMA structure is managed by maple tree, there is API called for_each_vma

you can just use it, you can search in kernel to understand how to use it.
● We want you to get the memory info from each VMA structure of the task

How to use for_each_vma

● Go https://elixir.bootlin.com/linux/v6.1.7/A/ident/for_each_vma
● You can see function define and function reference
● We pick a random one, for example, mm/fork.c
● Learn how it is used

https://elixir.bootlin.com/linux/v6.1.7/A/ident/for_each_vma

How to Walk Page
● For each VMA, there are multiple pages, because the VMA size will be align

with the PAGE_SIZE, so you can get each page’s virtual address
● For EXAMPLE, 0 is page 0, 0x1000 is page 1, and 0x2000 is page 2, etc.
● You can get the pgd the root address of the page directory entry in mm_struct
● So you can start with there, use the page virtual address to walk the page

table and to get each level address, p4d, pud, pmd, then pte.
● There are page table operation API in kernel, BECASE WE ARE USING

x86_64, the page table code is architecture dependent, you would find them
here arch/x86/include/asm/pgtable.h

● For example, pte_present() will show the if the pte present bit is set or not

https://elixir.bootlin.com/linux/v6.1.7/source/arch
https://elixir.bootlin.com/linux/v6.1.7/source/arch/x86
https://elixir.bootlin.com/linux/v6.1.7/source/arch/x86/include
https://elixir.bootlin.com/linux/v6.1.7/source/arch/x86/include/asm
https://elixir.bootlin.com/linux/v6.1.7/source/arch/x86/include/asm/pgtable.h

Example output

cat memstats

Virtual Memory Area Stats:

Total VMAs: 152

Biggest VMA Size: 66973696

Readable VMAs: 148

Writable VMAs: 42

Executable VMAs: 27

Shared VMAs: 0

Private VMAs: 152

Locked VMAs: 0

Executable Image VMAs: 26

File Backed VMAs: 130

Anonymous VMAs: 22

Physical Pages Stats:

Total Physical Pages: 2978

Number of Pages Swapped Out: 0

Read-Only Pages: 2839

Writable Pages: 139

Number of Shared Pages: 0

Number of Special Pages: 1

Number of Huge Pages: 0

Most VMA you can use with VMA flag, for example:

& VM_SHARED return TRUE indicate the VMA is shared VMA, not

private VMA

For pages, you can use the page operation API, for example:

pte_special() return TRUE indicates the page is Special Page

Task 2 Memory Analyzer

● Create a proc interface named memstats, /proc/[pid]/memstat

● Create a new file, memstats.c : core functionality for computing and displaying memory statistics

● To compile memstats.c, Update Makefile and Kconfig

● Compile Kernel

● Boot kernel

● What should you deliver?
In the folder named ‘Task1‘, you should include the following files:

‘shmem.c‘ file which is your shared memory kernel module.

In the folder named ‘Task2‘, the following should be included:

Your memstats.c source code. Place this inside a folder named ‘fs/proc‘.

It is crucial that your file is correctly located in this folder for it to be compiled.

NO OFFICE HOURS
– by Alan Nair

Questions?

Slide 1: Operating Systems Coursework 2
Slide 2: Deadlines
Slide 3: Marking & Late submission
Slide 4: Coursework 2
Slide 5: Goal
Slide 6: Background
Slide 7: mmap
Slide 8: Char dev
Slide 10: Task1 Shared Memory
Slide 11: Proc interface
Slide 12: Proc interface example
Slide 13: Proc interface per pid
Slide 14: How to Walk VMA
Slide 15: How to use for_each_vma
Slide 18: How to Walk Page
Slide 20: Example output
Slide 21: Task 2 Memory Analyzer
Slide 22: Delievery
Slide 23: Questions?