Download - kernel module programming
![Page 1: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/1.jpg)
kernel module programmingkernel module programming
Nezer J. ZaidenbergNezer J. Zaidenberg
![Page 2: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/2.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/3.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/4.jpg)
Agenda
• What is kernel module
• How to code simple kernel modules
• char devices
• adding system calls
• ioctls
• netlink sockets
![Page 5: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/5.jpg)
Next week
• Using procfs and sysfs
• Blocking
• Using timers to implement periodical tasks
• Interrupt handling
![Page 6: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/6.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/7.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/8.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/9.jpg)
EXPLAINING
• module init is called when module is loaded
• module cleanup is called when module is unloaded
![Page 10: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/10.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/11.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/12.jpg)
Inserting and removing module
• To insert
• insmod <modname>
• modprobe <modname> <args>
• To remove
• rmmod <modname>
• modprobe -r <modname>
![Page 13: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/13.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/14.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/15.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/16.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/17.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/18.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/19.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/20.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/21.jpg)
Getting info
• modinfo <modname>
• gives info on running modules we will get info for our modules 4 and 5.
![Page 22: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/22.jpg)
Multiple files
• We build a module using two files
• start.c
• stop.c
![Page 23: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/23.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/24.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/25.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/26.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/27.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/28.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/29.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/30.jpg)
Example
• struct file_operations fops = {
• .read = device_read,
• .write = device_write,
• .open = device_open,
• .release = device_release
• };
![Page 31: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/31.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/32.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/33.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/34.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/35.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/36.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/37.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/38.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/39.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/40.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/41.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/42.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/43.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/44.jpg)
Chapter 8Replacing
System calls
Chapter 8Replacing
System callsThis chapter is very
dangerous!This chapter is very
dangerous!
![Page 45: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/45.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/46.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/47.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/48.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/49.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/50.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/51.jpg)
Using IOCTL(2)Using IOCTL(2)
![Page 52: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/52.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/53.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/54.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/55.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/56.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/57.jpg)
![Page 58: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/58.jpg)
Camera driverCamera driverFor ex. 3!For ex. 3!
![Page 59: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/59.jpg)
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](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/60.jpg)
About V4L spec
• Not very interesting.
• Available from bytesex and thedirks
• Just API documentation
![Page 61: kernel module programming](https://reader033.vdocument.in/reader033/viewer/2022051418/56815563550346895dc32cd0/html5/thumbnails/61.jpg)
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