Operating Systems 2020W Lecture 17

From Soma-notes
Jump to navigation Jump to search

Video

The video from the lecture given on March 13, 2020 is now available.

Notes

Lecture 17
----------

- doing things remotely
- discuss /dev/ones
- discuss newgetpid
- clock algorithm?


Understanding user data in the kernel
 - the kernel, like any C program, deals with pointers all the time
 - most of the time, kernel pointers refer to kernel data structures
    - i.e., data that belongs to the kernel, residing in the kernel's
      virtual address space
 - but, the kernel also has to be able to get data from userspace programs,
   particularly as parameters for system calls.  These pass in pointers,
   but these arguments are pointers to *userspace* data structures and
   functions - i.e., ones that are in the calling process's address space
 - so the kernel has to keep track of userspace pointers and handle
   them specially (for safety and security reasons)
     - annotated with __user
     - accessed using special functions such as get_user, put_user
        - NEVER use userspace pointers like regular (kernel) pointers!

Pointers to functions and data in the kernel work just like userspace
 - this includes ones in kernel modules
 - but, they are running in supervisor mode on the CPU so can access
   all hardware, all resources

"current" is a special global variable available whenever the kernel
is processing a system call
 - refers to the task_struct associated with the process making
   the system call
 - many processes can be making system calls at the same time, so
   there are many "current" pointers at any time
 - we don't have to think about current in a kernel module,
   the rest of the kernel takes care of it, it will magically be right

Note that if you are writing a real device driver (dealing with
hardware), your module's code will be called in response to events
(interrupts) generated by the hardware
 - functions called when servicing interrupts have no "current" as
   they aren't being called in the context of a system call

Why not build in code in the kernel?  Why put it in a module?
 - we want everything in a module that we can because modules
   can be removed
 - code that is just part of the initially loaded kernel is always present,
   so you should want it all the time
 - devices vary between systems, so it is natural for device drivers
   to be in kernel modules - but almost any kernel functionality can
   be in a module (and most is)

Traditional UNIX kernels had no notion of modules
 - instead, you specify configuration options at compile time and
   build a single kernel image
 - different systems would have different specialized kernels
 - could work because those kernels ran on relatively few kinds of hardware
   (all proprietary, specific to one company generally)

If you want to look at interrupts and how they work, look in the textbook
 - http://pages.cs.wisc.edu/~remzi/OSTEP/file-devices.pdf
 - look at for context!

Kernel modules are kernel version specific
 - some source-level portability, but very little binary portability
 - new kernel -> compile modules from source

What functionality cannot be put into a module?
 - well, anything needed to actualy load modules...
 - so basic processes, memory management, etc need to all be built in


What if modules have the code needed to get the root filesystem online?
 - filesystem drivers, hard drive drivers, others?
 - solution: initial ram disks (initrd)

initrd allows you to limit what is in the base kernel

Idea: boot loader loads a RAM disk with kernel modules along with
      main kernel image

Note that kernel modules are mostly loaded and unloaded via userspace
 - but the kernel can generate events that cause userspace programs
   to load modules
 - example: insert a USB device, kernel will send an event to a userspace
   daemon to make sure the modules are loaded to handle the device
   (actually, that used to be the case, not sure if udev does that now...)

Can kernel modules spawn processes?  Not quite, as a new process requires a system call.
 - there are kernel threads, you can see them in a process listing
   (the ones in [])

The standard boot loader for Linux systems is GRUB
 - is the first thing that loads on boot
 - GRUB loads the chosen kernel and associated initrd
 - provides a menu interface so you can choose which kernel to boot
   (or on multi-os setups, another OS to boot)

(Before GRUB there was LILO.  GRUB is better!)

If you break GRUB your system won't boot.  Remember that!

Every OS has its own boot loader
 - Windows has its own
 - MacOS has its own
 - the *BSDs have their own

Sometimes you have to use a boot loader to load a boot loader
 - use GRUB to load the windows boot loader which loads windows
 - can get...convoluted

Linux tries to be flexible, but not all boot loaders can load it directly

initrd is a small Linux system (minus the kernel), purpose is just to load
kernel modules