Kernel Modules

Post on 13-Jan-2016

83 views 0 download

Tags:

description

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 flags to indicate that it is kernel code. Can be linked into the kernel by installation. Static/Dynamic loading - PowerPoint PPT Presentation

transcript

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 flags to indicate that it is kernel

code.• Can be linked into the kernel by installation.

– Static/Dynamic loading– “/proc/modules” or “lsmod”

• Enhance the functionality of the kernel.• Example:

– Device Drivers

Functions in Kernel Module

• int init_module(void) – Invoked when the module is inserted to kernel– Return 0 if success.

• void cleanup_module(void) – Invoked when the module is removed from kernel

• printk() – /usr/src/linux-2.6.5-1.358/include/linux/kernel.h

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

int init_module(void){

printk(KERN_ALERT "Hello world.\n“);

return 0;}

void cleanup_module(void){

printk(KERN_ALERT "Goodbye world.\n");}

MODULE_LICENSE("GPL"); //GNU Public License v2 or later

Makefile

ifneq ($(KERNELRELEASE),)

obj-m += hello.o

else

KDIR := /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

default:$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

endif

• insmod hello.ko• lsmod or “/proc/modules”• tail -f /var/log/messages• rmmod hello

Modules vs. Programs

• Programs– main()

– performs a single task from beginning to end

– Run in user mode

– Can call the libc functions

• Modules– init_module & cleanup_module

– registers itself in order to serve future requests

– Run in kernel mode• Part of kernel program

– Only can call the ones exported by the kernel.

• include/linux

• include/asm

• Export all non-static symbols

Device Drivers

• Character devices– one that can be accessed as a stream of

bytes – Keyboard driver

• Block devices– One that can be accessed as multiples of a

block, usually 1KB per block– Disk driver

Device Drivers

• To communicate with hardware– Each piece of hardware is represented by a file located in /dev– An application do some operations on that file– The kernel finds corresponding device driver for that file.– Each operation on that file will trigger a function in the device dri

ver for that hardware– The file in /dev is not regular file

• To find the device driver for that file– ls -l /dev/b*– Major number

• Match with driver– Minor number

• used by the driver to distinguish between the various hardware it controls

• ls -l /dev/fd0u*

Device Drivers

• Defines functions on the file operation– Read, write, open, close, etc

• Register the device to kernel

• creates a file in “/dev” using “mknod”

Device Drivers

• Function mapping

struct file_operations fops = {

.read = device_read,

.write = device_write,

.open = device_open,

.release = device_release

};

• vi /usr/src/linux-2.6.5-1.358/include/linux/fs.h• int register_chrdev(unsigned int major, const char *name, struct file_

operations *fops); • int unregister_chrdev(unsigned int major, const char *name);

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

#define DEVICE_NAME "chardev"#define BUF_LEN 80

static int Major;static char msg[BUF_LEN];static char *msg_Ptr;

static int device_open(struct inode *inode, struct file *file)

{static int counter = 0;sprintf(msg, "This device is opened %d times!\n", counter++);msg_Ptr = msg;try_module_get(THIS_MODULE);

return 0;}

static int device_release(struct inode *inode, struct file *file)

{module_put(THIS_MODULE);return 0;

}

• We cannot remove the device driver while device file is opened by a process.

• There's a counter which keeps track of how many processes are using your module – the 3rd column in lsmod

• try_module_get(THIS_MODULE);– Increment the use count

• module_put(THIS_MODULE);– Decrement the use count

static ssize_t device_read(struct file *filp,char *buffer, size_t length,

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

• put_user(char src, char* dst);– src is in kernel code segment– dst is in user code segment

• get_user(char dst, char* src);– src is in user code segment– dst is in kernel code segment

• A pointer into userspace should never be simply dereferenced

• #include <asm/uaccess.h>

• buffer is in user data segment• length: length of the buffer

static ssize_t

device_write(struct file *filp, const char *buff, size_t len, loff_t * off)

{

printk("<1>This operation isn't supported.\n");

return -EINVAL;

}

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

};

int init_module(void){

Major = register_chrdev(0, DEVICE_NAME, &fops);

if (Major < 0) {printk("Failed to register char device.\n");return Major;

}

printk(KERN_ALERT "chardev is assigned to major number %d.\n", Major);

return 0;}

void cleanup_module(void){

int ret = unregister_chrdev(Major, DEVICE_NAME);if (ret < 0)

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

mknod

• Create a file in /dev

• And match the file with a device driver• mknod /dev/hello c Major 0

– This Major number is from the output of /var/log/messages

References

• Linux Device Drivers, 2nd Edition – http://www.xml.com/ldd/chapter/book/index.html

• The Linux Kernel Module Programming Guide – http://tldp.org/LDP/lkmpg/2.6/html/