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 Proc interface per pid The /proc/ 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 virtual memory you can just use it, you can search in kernel to understand how to use it. How to use for_each_vma ● Go https://elixir.bootlin.com/linux/v6.1.7/A/ident/for_each_vma https://elixir.bootlin.com/linux/v6.1.7/A/ident/for_each_vma How to Walk Page with the PAGE_SIZE, so you can get each page’s virtual address table and to get each level address, p4d, pud, pmd, then pte. x86_64, the page table code is architecture dependent, you would find them ● 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 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? ‘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 Questions? Slide 1: Operating Systems Coursework 2
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
● struct vm_area_struct> virtual memory area, each area is a range of continues
● VMA structure is managed by maple tree, there is API called for_each_vma
● We want you to get the memory info from each VMA structure of the task
● You can see function define and function reference
● We pick a random one, for example, mm/fork.c
● Learn how it is used
● For each VMA, there are multiple pages, because the VMA size will be align
● 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
● There are page table operation API in kernel, BECASE WE ARE USING
here arch/x86/include/asm/pgtable.h
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
In the folder named ‘Task1‘, you should include the following files:
– by Alan Nair
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?