YOU ARE DOWNLOADING DOCUMENT

Please tick the box to continue:

Transcript
Page 1: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

kernel module programmingkernel module programming

Nezer J. ZaidenbergNezer J. Zaidenberg

Page 2: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

reference

• This guide is built on top of The Linux Kernel Module Programming Guide

• The guide is available from http://tldp.org/LDP/lkmpg/2.6/html/index.html

• I have also put references to other sources

Page 3: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

First class in kernel

• We will cover kernel programming

• I assume you now master the user space portion of this course.

Page 4: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Agenda

• What is kernel module

• How to code simple kernel modules

• char devices

• adding system calls

• ioctls

• netlink sockets

Page 5: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Next week

• Using procfs and sysfs

• Blocking

• Using timers to implement periodical tasks

• Interrupt handling

Page 6: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Kernel module

• Pluggable module to the operating system that adds functionality

• Device driver

• New features

• Since we don’t have hardware we focus on features

Page 7: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Kernel modules

• Can be added on the fly

• Allow us to change functionality on the fly

• Allow us to read and write

Page 8: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

SIMPLEST MODULE

• #include <linux/module.h> /* Needed by all modules */

• #include <linux/kernel.h> /* Needed for KERN_INFO */

• int init_module(void){

• printk(KERN_INFO "Hello world 1.\n");

• /*

• * A non 0 return means init_module failed; module can't be loaded.

Page 9: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

SIMPLEST MODULE

• */

• return 0;

• }

• void cleanup_module(void) {

• printk(KERN_INFO "Goodbye world 1.\n");

• }

Page 10: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

EXPLAINING

• module init is called when module is loaded

• module cleanup is called when module is unloaded

Page 11: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

printk

• The server can’t use stdlib due to userspace/kernel space issues

• Most of C library is implemented in the kernel

• printk is printf for kernel programs.

Page 12: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Makefile

• obj-m += hello-1.o

• all:

• make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

• clean:

• make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Page 13: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Inserting and removing module

• To insert

• insmod <modname>

• modprobe <modname> <args>

• To remove

• rmmod <modname>

• modprobe -r <modname>

Page 14: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

hello-2.c

• #include <linux/module.h> /* Needed by all modules */

• #include <linux/kernel.h> /* Needed for KERN_INFO */

• #include <linux/init.h> /* Needed for the macros */

• static int __init hello_2_init(void)

• {

• printk(KERN_INFO "Hello, world 2\n");

• return 0;

Page 15: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

hello-2.c

• }

• static void __exit hello_2_exit(void)

• {

• printk(KERN_INFO "Goodbye, world 2\n");

• }

• module_init(hello_2_init);

• module_exit(hello_2_exit);

Page 16: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

What does it do

• __init macro and __exit macro tells the kernel when we use this function

• This allows to free kernel memory that is used only at init

Page 17: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

hello-3.c• #include <linux/module.h> /* Needed by all modules */

• #include <linux/kernel.h> /* Needed for KERN_INFO */

• #include <linux/init.h> /* Needed for the macros */

• static int hello3_data __initdata = 3;

• static int __init hello_3_init(void)

• {

• printk(KERN_INFO "Hello, world %d\n", hello3_data);

Page 18: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

hello-3.c• return 0;

• }

• static void __exit hello_3_exit(void)

• {

• printk(KERN_INFO "Goodbye, world 3\n");

• }

• module_init(hello_3_init);

• module_exit(hello_3_exit);

Page 19: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Hello-4.c• #define DRIVER_AUTHOR "Peter Jay Salzman <[email protected]>"

• #define DRIVER_DESC "A sample driver"

• static int __init init_hello_4(void)

• {

• printk(KERN_INFO "Hello, world 4\n");

• return 0;

• }

• static void __exit cleanup_hello_4(void)

Page 20: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Hello-4.c• {

• printk(KERN_INFO "Goodbye, world 4\n");

• }

• module_init(init_hello_4);

• module_exit(cleanup_hello_4);

• MODULE_LICENSE("GPL");

• MODULE_SUPPORTED_DEVICE("testdevice");

• MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */

• MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */

Page 21: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Additions in hello-4.c

• We added licensing and information that removes the “kernel is tainted message”

• We also added some more info

Page 22: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Hello-5.c (simplified)• static int myint = 420;

• module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

• MODULE_PARM_DESC(myint, "An integer");

• static int __init hello_5_init(void)

• {

• int i;

• printk(KERN_INFO "Hello, world 5\n=============\n");

• printk(KERN_INFO "myint is an integer: %d\n", myint);

• return 0;

Page 23: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Hello-5.c (simplified)• }

• static void __exit hello_5_exit(void)

• {

• printk(KERN_INFO "Goodbye, world 5\n");

• }

• module_init(hello_5_init);

• module_exit(hello_5_exit);

Page 24: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

passing args

• We demonstrate the effect of passing args

• The tutorial demonstrate how more args (from different types can be given)

Page 25: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Getting info

• modinfo <modname>

• gives info on running modules we will get info for our modules 4 and 5.

Page 26: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Multiple files

• We build a module using two files

• start.c

• stop.c

Page 27: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

start.c

• #include <linux/kernel.h>/* We're doing kernel work */

• #include <linux/module.h>/* Specifically, a module */

• int init_module(void)

• {

• printk(KERN_INFO "Hello, world - this is the kernel speaking\n");

• return 0;

• }

Page 28: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

stop.c

• #include <linux/kernel.h>/* We're doing kernel work */

• #include <linux/module.h>/* Specifically, a module */

• void cleanup_module()

• {

• printk(KERN_INFO "Short is the life of a kernel module\n");

• }

Page 29: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Makefile for multiple files

• obj-m += startstop.o

• startstop-objs := start.o stop.o

• all:

• make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

• clean:

• make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Page 30: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

What do we do with KM

• Everything the OS can do

• Create drivers

• Virtual devices

• New system calls

• New OS abilities (support new file systems? implement something differently/more efficiently? etc)

Page 31: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Devices

• All devices happen to exist under the /dev file system and represented as a file that we can work with.

• This include I/O devices, virtual devices etc.

Page 32: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

I/O Devices

• I/O devices in Linux are specified as block and char device

• Block devices support lseek(2) : Example - disk

• Char devices don’t support lseek(2) : Example - keyboard.

Page 33: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Struct file operations

• We inherit and implement the functions we need using struct file operations.

Page 34: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example

• struct file_operations fops = {

• .read = device_read,

• .write = device_write,

• .open = device_open,

• .release = device_release

• };

Page 35: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Registering

• int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

• regiser = puts the driver handler in the factory

• Major = which driver handles this device.

• Minor = if we have several devices of the same type this distinguish them (like two HD on a box)

Page 36: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Unregistering

• Is done using unregister_chardev function

• If we try to rmmod and somebody is using the module - it will fail.

• Otherwise it will be successful.

• Usage count for our module is managed by the kernel.

• To help the kernel we have try_module_get and module_put functions.

Page 37: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Examples - blank char device

#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <asm/uaccess.h> /* for put_user */

int init_module(void);void cleanup_module(void);static int device_open(struct inode *, struct file *);static int device_release(struct inode *, struct file *);static ssize_t device_read(struct file *, char *, size_t, loff_t *);static ssize_t device_write(struct file *, const char *, size_t, loff_t *);

Page 38: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 2#define SUCCESS 0#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices */#define BUF_LEN 80 /* Max length of the message from the device */static int Major; /* Major number assigned to our device driver */

static int Device_Open = 0;static char msg[BUF_LEN]; /* The msg the device will give when asked */static char *msg_Ptr;

static struct file_operations fops = {.read = device_read,.write = device_write,.open = device_open,.release = device_release

};

Page 39: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 3int init_module(void){ Major = register_chrdev(0, DEVICE_NAME, &fops);

if (Major < 0) { printk(KERN_ALERT "Registering char device failed

with %d\n", Major); return Major;}

printk(KERN_INFO "the driver, create a dev file with\n");printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);printk(KERN_INFO "Remove the device file and module when done.\n");

return SUCCESS;}

Page 40: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 4

void cleanup_module(void){

/* * Unregister the device */int ret = unregister_chrdev(Major, DEVICE_NAME);if (ret < 0)

printk(KERN_ALERT "Error in unregister_chrdev: %d\n", ret);}

Page 41: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 5static int device_open(struct inode *inode, struct file *file){

static int counter = 0;

if (Device_Open)return -EBUSY;

Device_Open++;sprintf(msg, "I already told you %d times Hello

world!\n", counter++);msg_Ptr = msg;try_module_get(THIS_MODULE);

return SUCCESS;}

Page 42: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 6static int device_release(struct inode *inode, struct file *file){

Device_Open--; /* We're now ready for our next caller */

/* * Decrement the usage count, or else once you

opened the file, you'll * never get get rid of the module. */module_put(THIS_MODULE);

return 0;}

Page 43: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 7

static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */

char *buffer, /* buffer to fill with data */ size_t length, /* length of the buffer */ loff_t * offset)

{int bytes_read = 0;if (*msg_Ptr == 0)

return 0;

while (length && *msg_Ptr) {put_user(*(msg_Ptr++), buffer++);length--;bytes_read++;

}

return bytes_read;}

Page 44: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Explaining

• Normally kernel memory is kept after the MMU

• When we go through the MMU to put stuff in a user data we use put_user

Page 45: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Example 8static ssize_tdevice_write(struct file *filp, const char *buff, size_t len, loff_t * off){

printk(KERN_ALERT "Sorry, this operation isn't supported.\n");

return -EINVAL;}

Page 46: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Communicating with user space

• Kernel modules communicate with user space programs in several methods

• new system calls

• dev file interface and functions (and ioctls)

• kernel netlink socket

• /proc fs

Page 47: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

New system calls

• we can add new system calls to the linux kernel

• system calls have their os function table and we can register new ones

• we must supply header files off course (and man page if we are nice)

Page 48: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Chapter 8Replacing

System calls

Chapter 8Replacing

System callsThis chapter is very

dangerous!This chapter is very

dangerous!

Page 49: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

switching open - chapter 8

• This is an example to replacing open(2) in the system call table.

• It’s dangerous(!)

• We can add new system calls if we want in similar way

• We don’t do it in our homework

Page 50: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

taken from chapter 8

int init_module(){

original_call = sys_call_table[__NR_open];

sys_call_table[__NR_open] = our_sys_open;

return 0;}

Page 51: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Explaining

• We save the original open function pointer from the system call table (NR_Open = open index)

• We put our own function

• Similarly, one can add a function (just find unused number)

Page 52: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Again taken from chapter 8

void cleanup_module(){

if (sys_call_table[__NR_open] != our_sys_open) {printk(KERN_ALERT "Somebody else also played with the ");printk(KERN_ALERT "open system call\n");printk(KERN_ALERT "The system may be left in ");printk(KERN_ALERT "an unstable state.\n");

}

sys_call_table[__NR_open] = original_call;}

Page 53: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Completely new system calls

• Tutorials

• http://www.linuxjournal.com/article/3326

• http://tldp.org/HOWTO/html_single/Implement-Sys-Call-Linux-2.6-i386/

• IMHO – The Linux journal tutorial is better written but its old. the 2nd tutorial is more accurate...

• Read BOTH

Page 54: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

We will not cover new system calls but..

• Take note - that you register the system call in the table and add name

• You register the name and handler

• You must recompile the entire kernel

• Using ioctl(2) is usually better if you can

Page 55: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Using IOCTL(2)Using IOCTL(2)

Page 56: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

ioctl(2)

• IOCTL is like “a joker” system call.

• it gets two or more parameters.

• The file descriptor to work on (like device file)

• The operation number (like function number)

• Argument lists for the operation

Page 57: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

IOCTL(2) - usages

• Add kernel operations - without adding system calls

• Add kernel operations - without recompiling

• Add kernel operations - that can be removed with the module - on the fly.

Page 58: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

Parital example from chapter 7

struct file_operations Fops = {.read = device_read,.write = device_write,.ioctl = device_ioctl,.open = device_open,.release = device_release, /* a.k.a. close */

};

Page 59: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

ioctl(2) implementationint device_ioctl(struct inode *inode,

/* see include/linux/fs.h */ struct file *file, /* ditto

*/ unsigned int ioctl_num, /*

number and param for ioctl */ unsigned long ioctl_param)

{int i;char *temp;char ch;

switch (ioctl_num) {case IOCTL_SET_MSG:

temp = (char *)ioctl_param;

get_user(ch, temp);for (i = 0; ch && i <

BUF_LEN; i++, temp++)get_user(ch, temp);

device_write(file, (char *)ioctl_param, i, 0);

break;

case IOCTL_GET_MSG:// ...}

Page 60: Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.

CalLing IOCTL from userspace

#include "chardev.h"

#include <stdio.h>#include <stdlib.h>#include <fcntl.h> /* open */#include <unistd.h> /* exit */#include <sys/ioctl.h> /* ioctl */

ioctl_set_msg(int file_desc, char *message){

int ret_val;

ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

if (ret_val < 0) {printf("ioctl_set_msg failed:%d\n",

ret_val);exit(-1);

}}


Related Documents