+ All Categories
Home > Documents > kernel module programming

kernel module programming

Date post: 27-Jan-2016
Category:
Upload: annora
View: 47 times
Download: 1 times
Share this document with a friend
Description:
kernel module programming. Nezer J. Zaidenberg. 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. First class in kernel. - PowerPoint PPT Presentation
Popular Tags:
61
kernel module programming Nezer J. Zaidenberg
Transcript
Page 1: kernel module programming

kernel module programmingkernel module programming

Nezer J. ZaidenbergNezer J. Zaidenberg

Page 2: kernel module programming

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

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

Agenda

• What is kernel module

• How to code simple kernel modules

• char devices

• adding system calls

• ioctls

• netlink sockets

Page 5: kernel module programming

Next week

• Using procfs and sysfs

• Blocking

• Using timers to implement periodical tasks

• Interrupt handling

Page 6: kernel module programming

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

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

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");

• return 0;

• }

• void cleanup_module(void)

• {

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

• }

Page 9: kernel module programming

EXPLAINING

• module init is called when module is loaded

• module cleanup is called when module is unloaded

Page 10: kernel module programming

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 11: kernel module programming

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 12: kernel module programming

Inserting and removing module

• To insert

• insmod <modname>

• modprobe <modname> <args>

• To remove

• rmmod <modname>

• modprobe -r <modname>

Page 13: kernel module programming

hello-2.c•static int __init hello_2_init(void)

•{

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

• return 0;

•}

•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 14: kernel module programming

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 15: kernel module programming

hello-3.c•static int hello3_data __initdata = 3;

•static int __init hello_3_init(void)

•{

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

• return 0;

•}

•static void __exit hello_3_exit(void)

•{

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

•}

•//init … exit…

Page 16: kernel module programming

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)

• {

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

• }

Page 17: kernel module programming

Hello-4.c (cont)

• 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 18: kernel module programming

Additions in hello-4.c

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

• We also added some more info

Page 19: kernel module programming

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 20: kernel module programming

passing args

• We demonstrate the effect of passing args

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

Page 21: kernel module programming

Getting info

• modinfo <modname>

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

Page 22: kernel module programming

Multiple files

• We build a module using two files

• start.c

• stop.c

Page 23: kernel module programming

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 24: kernel module programming

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 25: kernel module programming

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 26: kernel module programming

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 27: kernel module programming

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 28: kernel module programming

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 29: kernel module programming

Struct file operations

• Char device/Block device is an ABC

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

Page 30: kernel module programming

Example

• struct file_operations fops = {

• .read = device_read,

• .write = device_write,

• .open = device_open,

• .release = device_release

• };

Page 31: kernel module programming

Registering

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

• regiser = puts the driver handler in the factory (same as ffmpeg codecs)

• 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 32: kernel module programming

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 33: kernel module programming

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 34: kernel module programming

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 35: kernel module programming

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 36: kernel module programming

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 37: kernel module programming

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 38: kernel module programming

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 39: kernel module programming

Example 7static 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 40: kernel module programming

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 41: kernel module programming

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 42: kernel module programming

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 43: kernel module programming

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 44: kernel module programming

Chapter 8Replacing

System calls

Chapter 8Replacing

System callsThis chapter is very

dangerous!This chapter is very

dangerous!

Page 45: kernel module programming

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 46: kernel module programming

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 47: kernel module programming

Explaining

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

• We put our own function

• We can do similar ways to add function (just find unused number)

Page 48: kernel module programming

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 49: kernel module programming

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 - Linux journal tutorial is better written but its old. the 2nd tutorial is more accurate...

• Read BOTH

Page 50: kernel module programming

I 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 51: kernel module programming

Using IOCTL(2)Using IOCTL(2)

Page 52: kernel module programming

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 53: kernel module programming

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 54: kernel module programming

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 55: kernel module programming

ioctl(2) implementation

int 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 56: kernel module programming

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);

}}

Page 57: kernel module programming
Page 58: kernel module programming

Camera driverCamera driverFor ex. 3!For ex. 3!

Page 59: kernel module programming

What is camera driver

• Camera driver is just another block device or char device that produces frames.

• Linux has a spec that all camera drivers must follow called V4L2 (Video 4(for) Linux 2)

• This spec is nothing but how to use read(2),write(2), ioctl(2), mmap.

Page 60: kernel module programming

About V4L spec

• Not very interesting.

• Available from bytesex and thedirks

• Just API documentation

Page 61: kernel module programming

About EX3

• You have to code frame grabber, a kernel quasi-webcam driver(getting the frames from flv file) and a user process that communicates with the kernel driver.

• We will discuss next class how to communicate between user and kernel


Recommended