Operating Systems 2014F: Tutorial 7

From Soma-notes
Revision as of 17:29, 11 November 2014 by Soma (talk | contribs)
Jump to navigation Jump to search

This tutorial is not yet finalized.

In this tutorial you will be learning about the basics of Linux kernel modules and character devices.

Building and running your first module

  1. Download the source for this simple module, unpack, and build it by typing "make".
  2. Install the module using "sudo insmod simple.ko". The hello message is recorded in the kernel logs. How do you view the kernel logs?
  3. Check to see that the module has been loaded. How do you do this?
  4. Remove the module from the kernel. What did you do?

Devices

  1. Look at the details of files in /dev. What kind of filesystem stores these files? (Hint: look at the output of df.)
  2. How can you tell the difference between block and character devices using ls?
  3. What are the major and minor numbers of the loopback block devices (loopX)?
  4. What block device is used for the root filesystem on your system (the class VM or other Linux system)?
  5. When you type commands in a terminal window, you are interacting with a "pseudo tty" character device. Specifically, what device file(s) are being used by the terminal window, and what are the permissions and special file attributes (major, minor numbers) of these files? Are the permissions important?

A character device module

  1. Download the source for ones, a kernel module implementing a character device that ouputs an unbounded string of "1"'s. Build, compile, and run it as before.
  2. Use mknod (with sudo) to make a character device "onesdev" that connects to the ones kernel module. What command do you use? (Hint: the minor number doesn't matter.)
  3. What happens when you "cat" the device? How can you limit the output?
  4. How can you modify your module to generate a kernel "Oops" as reported in the kernel logs or outright crash the kernel?


Simple module

simple.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int __init simple_init(void)
{
        printk ("Hello kernel world!\n");
        return 0;
}

static void __exit simple_exit(void)
{
        printk ("Goodbye kernel world.\n");
        return;
}

module_init(simple_init);
module_exit(simple_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Somayaji <soma@scs.carleton.ca>");
MODULE_DESCRIPTION("A simple module");


Makefile

obj-m := simple.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules


Ones module

ones.c

/* Code derived from https://appusajeev.wordpress.com/2011/06/18/writing-a-linux-character-device-driver/ */

#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>

static int major;

static int ones_open(struct inode *the_inode, struct file *f)
{
        return 0;
}

static ssize_t ones_read(struct file *f, char *buf, size_t len, loff_t *offset)
{
        size_t i;

        for (i = 0; i < len; i++) {
                put_user('1', buf++);
        }

        return i;
}

static int ones_release(struct inode *the_inode, struct file *f)
{
        printk(KERN_ALERT "Ones device closed\n");
        return 0;
}


static struct file_operations ones_fops = {
        .open = ones_open,
        .read = ones_read,
        .release = ones_release,
};

static int __init ones_init(void)
{
        major = register_chrdev(0, "ones", &ones_fops);

        if (major<0) {
                printk(KERN_ALERT "Ones device registration failed.\n");
                return major;
        } else {
                printk(KERN_ALERT "Ones device registered using major %d.\n",
                       major);
                return 0;
        }
}

static void __exit ones_exit(void)
{
        unregister_chrdev(major, "ones");
        printk(KERN_ALERT "Unloading Ones module.\n");
        return;
}

module_init(ones_init);
module_exit(ones_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Somayaji <soma@scs.carleton.ca>");
MODULE_DESCRIPTION("A write ones character device module");


Makefile

obj-m := ones.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules