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

Slides:



Advertisements
Similar presentations
DEVICE DRIVER VINOD KAMATH CS691X PROJECT WORK. Introduction How to write/install device drivers Systems, Kernel Programming Character, Block and Network.
Advertisements

Linux device-driver issues
Device Drivers. Linux Device Drivers Linux supports three types of hardware device: character, block and network –character devices: R/W without buffering.
RT_FIFO, Device driver.
Sogang University Advanced Operating Systems (Linux Device Drivers) Advanced Operating Systems (Linux Device Drivers) Sang Gue Oh, Ph.D.
Lecture for Lab 3, Exp1 of EE505 (Developing Device Driver) T.A. Chulmin Kim CoreLab. Mar, 11, 2011 [XenSchedulerPaper_Hotcloud-commits] r21 - /
Computer System Laboratory
USERSPACE I/O Reporter: R 張凱富.
R4 Dynamically loading processes. Overview R4 is closely related to R3, much of what you have written for R3 applies to R4 In R3, we executed procedures.
CSCC69: Operating Systems
Building and Running Modules Sarah Diesburg COP 5641.
Building and Running Modules Linux Kernel Programming CIS 4930/COP 5641.
1 CMSC421: Principles of Operating Systems Nilanjan Banerjee Principles of Operating Systems Assistant Professor, University of Maryland Baltimore County.
Embedded Systems Programming Writing Device Drivers.
63 UQC152H3 Advanced OS Writing a Device Driver. 64 The SCULL Device Driver Simple Character Utility for Loading Localities 6 devices types –Scull-03.
Embedded System Programming Introduction to Device Drivers.
CSE 451 Section 4 Project 2 Design Considerations.
Tutorial and Demos on Linux Virtual Machine
1 Netfilter in Linux Bing Qi Department of Computer Science and Engineering Auburn university.
Processes in Unix, Linux, and Windows CS-502 Fall Processes in Unix, Linux, and Windows CS502 Operating Systems (Slides include materials from Operating.
Process. Process Concept Process – a program in execution Textbook uses the terms job and process almost interchangeably A process includes: – program.
POSIX: Files Introduction to Operating Systems: Discussion 1 Read Solaris System Interface Guide: Ch. 5.1 Basic File I/O.
Loadable Kernel Modules Dzintars Lepešs The University of Latvia.
1 Week 6 Intro to Kernel Modules, Project 2 Sarah Diesburg Florida State University.
Kernel module programming Nezer J. Zaidenberg. reference This guide is built on top of The Linux Kernel Module Programming Guide The guide is available.
Operating System Program 5 I/O System DMA Device Driver.
Sockets and intro to IO multiplexing. Goals We are going to study sockets programming as means to introduce IO multiplexing problem. We will revisit socket.
For OS Experiments. What Do We Need? A Computer &
Introduction to Processes CS Intoduction to Operating Systems.
COMP 3438 – Part I - Lecture 4 Introduction to Device Drivers Dr. Zili Shao Department of Computing The Hong Kong Polytechnic Univ.
LWIP TCP/IP Stack 김백규.
Sogang University Advanced Operating Systems (Linux Module Programming) Sang Gue Oh, Ph.D.
Lecture 2: Linux devices Roei Ben-Harush Agenda 1 1 Linux Devices About next Assignment Roei Ben-Harush 2015 Reminder.
Kernel Modules. Kernel Module Pieces of code that can be loaded and unloaded into the kernel upon demand. Compiled as an independent program With appropriate.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 8: Opening Files and Starting Processes.
The Socket Interface Chapter 21. Application Program Interface (API) Interface used between application programs and TCP/IP protocols Interface used between.
UNIX Files File organization and a few primitives.
Implementation of Embedded OS Lab3 Linux Kernel Modules.
LOGO System Call. Introduction System call is the mechanism used by an application program to request service from the OS. Users use it to communicate.
Operating Systems CSE 411 CPU Management Sept Lecture 10 Instructor: Bhuvan Urgaonkar.
Interfacing Device Drivers with the Kernel
CSC414 “Introduction to UNIX/ Linux” Lecture 2. Schedule 1. Introduction to Unix/ Linux 2. Kernel Structure and Device Drivers. 3. System and Storage.
4P13 Week 12 Talking Points Device Drivers 1.Auto-configuration and initialization routines 2.Routines for servicing I/O requests (the top half)
Lab 12 Department of Computer Science and Information Engineering National Taiwan University Lab12 – Driver 2014/12/16 1 /21.
COMP 3438 – Part I - Lecture 5 Character Device Drivers
Week 4 - Monday.  What did we talk about last time?  Precedence  Selection statements  Loops  Lab 3.
Kernel Structure and Infrastructure David Ferry, Chris Gill CSE 522S - Advanced Operating Systems Washington University in St. Louis St. Louis, MO
1 Intro to Kernel Modules and /proc Sarah Diesburg CS 3430 Operating Systems.
Finish up OS topics Group plans. Today Finish up and review Linux device driver stuff – Walk example again – See how it all goes together – Discuss talking.
Lecture 3 Module Programming and Device Driver (Homework#1 included) Kyu Ho Park Sept. 15, 2015.
File table: a list of opened files Each entry contains: – Index: file descriptors – Pointer to the file in memory – Access mode File descriptor is a positive.
Lecture 1 Page 1 CS 111 Summer 2013 Important OS Properties For real operating systems built and used by real people Differs depending on who you are talking.
Virtual Memory Mohammad H. Mofrad February 23, 2016
OS – Ex 1 Nezer J. Zaidenberg.
Lecture 3 Module Programming and Device Driver (Homework#1 included)
CS 6560: Operating Systems Design
Protection of System Resources
Computer System Laboratory
Linux Kernel Driver.
Intro to Kernel Modules and /proc
Kernel Structure and Infrastructure
CS 6560 Operating System Design
Kernel – Device Drivers (part 2)
Lab 4 Kernel Module Operating System Lab.
CSE 333 – Section 3 POSIX I/O Functions.
CS 6560 Operating System Design Kernel Loadable Modules
Implementation of Embedded OS
Computer System Laboratory
Loadable Kernel Modules
Presentation transcript:

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 I have also put references to other sources

First class in kernel We will cover kernel programming I assume you now master the user space portion of this course.

Agenda What is kernel module How to code simple kernel modules char devices adding system calls ioctls netlink sockets

Next week Using procfs and sysfs Blocking Using timers to implement periodical tasks Interrupt handling

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

Kernel modules Can be added on the fly Allow us to change functionality on the fly Allow us to read and write

SIMPLEST MODULE #include /* Needed by all modules */ #include /* 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"); }

EXPLAINING module init is called when module is loaded module cleanup is called when module is unloaded

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.

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

Inserting and removing module To insert insmod modprobe To remove rmmod modprobe -r

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

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

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…

Hello-4.c #define DRIVER_AUTHOR "Peter Jay Salzman #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"); }

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 */

Additions in hello-4.c We added licensing and information that removes the “kernel is tainted message” We also added some more info

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

passing args We demonstrate the effect of passing args The tutorial demonstrate how more args (from different types can be given)

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

Multiple files We build a module using two files start.c stop.c

start.c #include /* We're doing kernel work */ #include /* Specifically, a module */ int init_module(void) { printk(KERN_INFO "Hello, world - this is the kernel speaking\n"); return 0; }

stop.c #include /* We're doing kernel work */ #include /* Specifically, a module */ void cleanup_module() { printk(KERN_INFO "Short is the life of a kernel module\n"); }

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

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)

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.

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.

Struct file operations Char device/Block device is an ABC We inherit and implement the functions we need using struct file operations.

Example struct file_operations fops = {.read = device_read,.write = device_write,.open = device_open,.release = device_release };

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)

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.

Examples - blank char device #include #include /* 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 *);

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

Example 3 int 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; }

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

Example 5 static 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; }

Example 6 static 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; }

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

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

Example 8 static ssize_t device_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; }

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

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)

Chapter 8 Replacing System calls This chapter is very dangerous!

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

taken from chapter 8 int init_module() { original_call = sys_call_table[__NR_open]; sys_call_table[__NR_open] = our_sys_open; return 0; }

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)

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

Completely new system calls Tutorials ent-Sys-Call-Linux-2.6-i386/ ent-Sys-Call-Linux-2.6-i386/ IMHO - Linux journal tutorial is better written but its old. the 2nd tutorial is more accurate... Read BOTH

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

Using IOCTL(2)

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

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.

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 */ };

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: //... }

CalLing IOCTL from userspace #include "chardev.h" #include #include /* open */ #include /* exit */ #include /* 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); }

Camera driver For ex. 3!

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.

About V4L spec Not very interesting. Available from bytesex and thedirks Just API documentation

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

Kernel netlink sockets

Tutorial

what is netlink socket new domain of sockets (like AF_INET, AF_UNIX) one end in the kernel space one end in userland DGRAM or RAW (raw messages - like IP) only. no STREAM

USER SPACE SIDE Protocol for sockets is used (protocol is used to define communication type) We may want to add new communication type In user mode we probably will under stand API easily

USER EXAMPLE 1 From linux journal #include #define MAX_PAYLOAD 1024 /* maximum payload size*/ struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; int sock_fd; void main() { sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);

USER EXAMPLE 2 From linux journal memset(&src_addr, 0, sizeof(src_addr)); src__addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); /* self pid */ src_addr.nl_groups = 0; /* not in mcast groups */ bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; /* For Linux Kernel */ dest_addr.nl_groups = 0; /* unicast */

USER EXAMPLE 3 From linux journal nlh=(struct nlmsghdr *)malloc( NLMSG_SPACE(MAX_PAYLOAD)); /* Fill the netlink message header */ nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); /* self pid */ nlh->nlmsg_flags = 0; /* Fill in the netlink message payload */ strcpy(NLMSG_DATA(nlh), "Hello you!"); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void *)&dest_addr; msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; sendmsg(fd, &msg, 0);

USER EXAMPLE 4 From linux journal /* Read message from kernel */ memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); recvmsg(fd, &msg, 0); printf(" Received message payload: %s\n", NLMSG_DATA(nlh)); /* Close Netlink Socket */ close(sock_fd); }

now the kernel side... We have to register ourselves. (to support socket from the right type) Everything else is straight forward

Kernel netlink example 1 (LJ) struct sock *nl_sk = NULL; void nl_data_ready (struct sock *sk, int len) { wake_up_interruptible(sk->sleep); } void netlink_test() { struct sk_buff *skb = NULL; struct nlmsghdr *nlh = NULL; int err; u32 pid;

Kernel netlink example 2 (LJ) nl_sk = netlink_kernel_create(NETLINK_TEST, nl_data_ready); /* wait for message coming down from user-space */ skb = skb_recv_datagram(nl_sk, 0, 0, &err); nlh = (struct nlmsghdr *)skb->data; printk("%s: received netlink message payload:%s\n", __FUNCTION__, NLMSG_DATA(nlh)); pid = nlh->nlmsg_pid; /*pid of sending process */ NETLINK_CB(skb).groups = 0; /* not in mcast group */ NETLINK_CB(skb).pid = 0; /* from kernel */ NETLINK_CB(skb).dst_pid = pid; NETLINK_CB(skb).dst_groups = 0; /* unicast */ netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); sock_release(nl_sk->socket); }

Homework 3 Tape library

what is vtl In many case we work with disks to implement tape libraries faster and cheaper then robuts but backup application still want tape API so we create VIRTUAL TAPE LIBRARY a char device - that writes to real disk that acts as tape library

In the homework You have been requested to write a user space program that manages a tape library (bunch of files each representing a tape) A kernel application that acts as the tape The two programmes communicate via netlink socket The kernel application gets commands via ioctl(2)

Goal - VTL We implement a virtual tape library We create a char device - the virtual tape We communicate with the char device via ioctls, read, write

how to communicate read, write = read from tape, write to tape ioctl = rewind, start new tape, destroy tape, replace tape

what to implement 3 programs Userland programme that handles the virtual library - compress and decompress tapes and files (talk to kernel via netlink socket) Kernel module that communicate with Userland programmes Test utility - talk to kernel with read/write and ioctls

Details I will implement over the weekend and put exact implementation details for automatic checking I will also publish my test programmes

VTL companies IBM VTS on mainframe Falconstor Sepaton (no-tapes) - now sungate Diligent (now IBM) It’s a major industry in storage world!

Compression Libbz2

Is easy bzip has a buffer compression function and assortment of file functions