Operating Systems 2018F Lecture 12: Difference between revisions

From Soma-notes
 
Line 62: Line 62:
** some may conflict
** some may conflict
** many are unnecessary
** many are unnecessary
** memory used by kernel is physically used - never virtual
** memory used by kernel cannot be swapped to disk
*** so we minimize this by only loading necessary kernel modules
*** so we minimize this by only loading necessary kernel modules



Latest revision as of 18:59, 23 November 2018

Video

Video from the lecture given on October 17, 2018 is now available.

Notes

Today: Kernel modules

First, Anil's ssh setup:

student@anil-vm: // openstack

  • why is it named anil-vm?
    • edit /etc/hosts and /etc/hostname

anilclass@sutherland: // local machine

  • edit /etc/hosts
    • add the IP of your VM and give it name
    • distributed DNS does this for URLs
  • login without password
    • ssh key pair, private and public
    • files in ~/.ssh/

Public keys?

  • sharing won't compromise security

Running X-windows programs on vm:

  • ssh -X student@anil-vm // works natively in linux
  • on macOS, you can run X-server separately
  • on Windows, use x2go

Whats a kernel module?

  • kernel code, that you load, into the kernel
  • same privileges as other kernel code
  • dangerous! load kernel module = anything can happen
    • only superuser (root) can load
  • NOT a system call

Kernel Oops:

  • kernel catches the bad memory access

Kernel crash:

  • didn't catch it

Build kernel from scratch? Not usually - everything is in modules now

What modules are running? lsmod

  • gets info from /proc/modules
  • /proc/modules is reading a kernel data structure
  • strace lsmod:
    • shows that it starts with /proc/modules
    • but then goes into /sys/module/
  • /proc : human readable
  • /sys : machine readable
    • wouldn't find a list of modules here, but rather deep directory structure

Where are kernel modules stored?

  • /lib/modules/<kernel version>/
  • why so many kernel versions?
    • ex. 4.15.0-33
      • 4.15.0 is version.
      • -33 = package release (patches etc)

Why so many modules? Why not build them in?

  • originally, everything was built in - now we basically never do that
    • some may conflict
    • many are unnecessary
    • memory used by kernel cannot be swapped to disk
      • so we minimize this by only loading necessary kernel modules

.ko: kernel object .so: shared object (ex. C libraries)

Where is kernel itself? /boot/vmlinuz-4.15.0-33-generic

  • naming is traditional. 'z' is for compressed.
  • variants may have different suffix, ex. 'rt' for realtime, instead of 'generic'
  • kernel is around 8mb

Review tutorial

  • sudo insmod simple.ko // load kernel module
  • dmesg | tail // shows that kernel is loaded
  • sudo rmmod simple.ko // removes kernel module

simple.c

  • Why #include <linux/ ...>?
  • No headers that are familiar, ex. stdlib, etc.
    • You can't use these in kernel modules. Why?
      • You can't use any C library that makes a system call
    • What if you wanted to printf?
      • printk() is a reimplementation, because
        • printf would "bottom out" by making a system call to write()
        • printk is used to generate logs
        • how does it do that?
          • keeps a buffer until they can be printed somewhere
          • bootup messages? produced by printk
      • kernel has its own weird world of standard libraries
  • Some special syntax around declaring init and exit functions..
  • How does kernel actually load a module? (ie. through module_init() call in simple.c)
    • don't worry about it. always something you don't understand...
    • and this is one of these things few people need to understand!
    • you just needs to know how to use it.
  • Why doesn't simple_exit return anything? Nobody cares what it returns!
    • vs. if init failed... we would care

Rule of kernel programming: do as little as possible

  • nicer to write in userspace

ones.c

  • kernel module that implements a device driver for /dev/ones
    • from linux kernels perspective.. same as any other device
    • a module might be a device driver, but might not be
    • and a driver might be baked into the kernel (not a module)
    • but usually, device drivers are implemented as modules
  • makes a character device: register_chrdev()
    • every device has a major and a minor number: the above function returns major number
  • ones_fops { }: important. struct containing function pointers.
    • we never call these functions in ones.c
    • these implement the file operations on /dev/ones
      • after normal syscall dispatcher stuff, it will want to know HOW to open the device, read, etc
      • what if we wanted to do a write?
        • well, /dev/ones is opened read-only. let's chmod a+w /dev/ones.
        • echo 5 > /dev/ones // write error
        • we only have the operations that we've implemented
    • who calls them?
  • class_create() ?
    • can't just create a device from the major number
    • need a class first before running device_create()
    • grouping of all devices that use the same driver
    • see /sys/class/comp3000
  • /sys/devices/virtual/comp3000/ones
    • what's this about? metadata.
    • thankfully we didn't have to create this ourself - device_create() took care of all that
  • failed_devreg, etc:
    • handling failures is really important in kernel programming.
    • if something fails and you don't manually deregister / deallocate memory, it never gets "cleaned up"
      • stays in physical memory until you reboot
  • How did we come up with this code, generally?
    • no manpages
    • the linux kernel source is the ultimate reference for how this works
    • best way to figure it out is to look at existing device drivers, modify to your purpose, trial & error...
  • ones_read():
    • similar to read() in userspace
    • in userspace you take a file descriptor; in kernel you take a pointer to a file struct
    • buf, len just as in read()..
    • offset? point to specific part of the file
    • the file is always going to be /dev/ones in this case (since it is a device driver)
    • why put_user('1', buf++) instead of *buf++ = 1?
      • The 1's are going out into userspace. This is what put_user() is for.

aside: find . -name "ones"

  • will find files named "ones" in current directory (.)

Look at newgetpid.c