Linux Device Drivers

Linux Device Drivers


Linux
Modules
Character drivers
IO & Memory
Linux Kernel
Process Management
Process Address space

Linux Scheduler
Memory Management
Interrupts
Signals
System Calls
Kernel Synchronization
Linux Inter Process Communications




Serial Ports
Parallel Ports
Introduction to Hardware
Linux Timers
DMA in Linux
Linux Threads
Linux Thread Synchronization

Linux Multi Threading
Debugging in Linux
GDB GNU Debugger
KDB Kernel Debugger
KGDB Kernel GNU Debugger
Example Ethernet Driver




 

Modules

 

Each piece of code that can be added to the kernel at runtime is called a "module". The linux kernel offers support for quiet a few different types of modules, including, but not limited to device drivers.

A module is "object code" (not linked to a complete executable) that can be dynamically linked to the running kernel and can be unlinked.

 

Uses of Modules

ü     Allow third party commercial development of drivers

ü     Minimize kernel size

ü     Allow smaller generic kernels

 

Modutils:

insmod; modprobe; depmod; lsmod; modinfo; rmmod; ksyms; kerneld;

 

insmod

ü     Installs a loadable module in the running kernel.

ü     Load time parameters can be passed to the module, to customize its operation ( eg. I/O ports, IRQ Nosetc)

 

modprobe

Uses a “makefile”-like dependency file (created by "depmod") to automatically load the relevant modules from the set of modules available in predefined directory trees.

 

ü     Used to load a module, either a single module, a stack of dependent modules

ü     Will try to load a module out of a list and stops loading as soon as one module loads successfully.

 

depmod

Makes a “Makefile”-like dependency file, which is later used by modprobe.

 

lsmod

Shows information about all loaded modules

(name, size, use count, list of referring modules etc..)

 

modinfo

Displays information about a kernel module (from object file)

 

rmmod

Tries to unload a (set of ) module(s) from the running kernel with the restriction that they are not in use and that they are not referred to by other modules.

 

 

 

hello moduleinitialization and cleanup

 

/* hello.c*/

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

 

static int__init hello_init(void)

{

printk(KERN_ALERT “Hello World\n");

return 0;

}

 

static void __exit hello_exit(void)

{

printk(KERN_ALERT “Good Bye!\n");

}

 

module_init(hello_init);

module_exit(hello_exit);

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Greeting module");

MODULE_AUTHOR(“B R Sahu”);

 

__init:   removed after initialization (static kernel or module).

__exit:       discarded when module compiled statically into the kernel.

 

Compiling kernel modules

Kernel modules need to be compiled with certain gcc options to make them work.

 

The 2.6 compatible Makefilefor the module testmod.ko

obj-m := testmod.o

 

A simple command line for building a module

#make –C /usr/src/linux-2.6.1 SUBDIRS=$PWD modules

 

Assumes, your modules source code and Makefile are located at the same directory

 

Compiling a module

 

The below Makefile should be reusable for any Linux 2.6 module.  Just run make to build the hello.ko file

Caution: make sure there is a [Tab] character at the beginning of the $(MAKE) line (make syntax)

 

# Makefile for the hello module

 

obj-m := hello.o

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

PWD := $(shell pwd)

default:

*$(MAKE) –C $(KDIR) SUBDIRS=$(PWD) modules

 

*[Tab]!(no spaces)

 

**either

-Full kernel source directory (configured and compiled)

-or just kernel headers directory (minimum needed)

 

Running module

 

You can test the module by calling insmod and rmmod (Note that only super-user can load and unload a module).

root# insmod./hello.o

Hello, World

root# rmmod hello

Goodbye

#

 

ü     You can verify the loading of modules using lsmod.

ü     The messages appear only on the console, not on xconsole.

ü     Take a look at /var/log/messages just to see that it got logged toyour system logfile.

 

 

Linking a module to the kernel

 

 

 

Application vs Module

 

ü     An application performs a single task from beginning to end.

ü     A module registers itself in order to serve future requests and its “main” function i.e., init_module terminates immediately.

ü     The second entry point of a module, “cleanup_module” gets invoked just before the module is unloaded by rmmod etc.

ü     A module is linked only to the kernel and the only functions it can call are the ones exported by the kernel. A module is not linked to any standard library like libc etc.

 

Usage Count

The system keeps a usage count for every module in order to determine whether the module can be safely removed. For example you can remove a filesystem type while the filesystem is mounted.

To work with the usage count, use these three macros:

MOD_INC_USE_COUNT: Increments the count for the current module

MOD_DEC_USE_COUNT:  Decrements the count

MOD_IN_USE:         Evaluates to true if the count is not zero

 

Module Configuration Parameters

 

Several parameters that a driver needs to know can change from system to system.

Parameter values can be assigned at load time by insmod. The command accepts the specification of integer and string values on the command line. Thus, if your module were to provide an integer parameter called ival and a string parameter called sval, the parameters could be set at module load time with an insmod command like:

 

#insmod hello.oival=200 sval=”Welcome”

 

However, before insmod can change module parameters, the module must make them available. Parameters are declared with the MODULE_PARM macro, which is defined in module.h.

MODULE_PARM takes two parameters: the name of the variable and a string describing its type. The macro should be placed outside of any function and is typically found near the head of the source file. The two parameters mentioned earlier could be declared with the following lines:

intival=0;

char *sval;

MODULE_PARM(ival, “i”);

MODULE_PARM(sval, “s”);

 

/* module2.c */

#include <linux/module.h>

#include <linux/moduleparam.h>

#include <linux/init.h>

 

int ival=0;

char *sval;

 

module_param(ival, int, S_IRUGO);

module_param(sval, charp, S_IRUGO);

 

int my_init(void) //module entry point

{

printk("#=== Module Initialized ===#\n"); //kernel print function

printk("ival= %d\n val=%s\n", ival, sval); //kernel print function

return 0;

}

 

void my_exit(void) //cleanup function

{

printk("#=== Module removed ===#\n");

}

module_init(my_init);

module_exit(my_exit);

MODULE_LICENSE("GPL");

 

Exporting Symbols

 

A module implements its own functionality without the need to export any symbols. You will need to export symbols, whenever other modules may benefit from using them. You may also need to include specific instructions to avoid exporting all non-static symbols, as most versions of modutils export all of them by default.  The Linux kernel header files provide a convenient way to manage the visibility of your symbols, thus reducing namespace pollution and promoting proper information hiding. If your module exports no symbols at all, you might want to make that explicit by placing a line with this macro call in source file: EXPORT_NO_SYMBOLS;

 

Creating stacked loadable modules

You can stack new modules on top of other modules, and new modules can use symbols exported by your module. Module stacking is implemented in the main stream kernel sources as well: each input USB device module stacks on the usbcore and input modules.

Module stacking is useful in complex projects. If a new abstraction is implemented in the form of a device driver, it might offer a plug for hardware-specific implementations

 

Stacking of parallel port driver modules

 

 

Module Implementation

 

Modules are stored in the filesystem as ELF object files. Module is loaded into RAM by /sbin/insmod. The kernel allocates memory area containing the following data:

 

ü     A module object

ü     A null-terminated string that represents the name of the module.

ü     The code that implements the functions of the module.

The module object describes a module. A simple linked list collects all module objects. The first element of the list is addressed by the module_list variable.

 

Module Object

 

size_of_struct:                 size of module object

next:                      next list element

name:                      pointer to module name

size:                      module size

uc.usecount:               module usage counter

flags:                     module flags

nsyms:                     number of exported symbols

ndeps:                     number of referenced modules

syms:                      table of exported symbols

deps:                      list of referenced modules

refs:                      list of referencing modules

init:                      initialization method

cleanup:                          cleanup method

ex_table_start:                 start of exception table

ex_table_end:              end of exception table

 

Linking and unlinking modules

 

A user can link a module into running kernel by executing /sbin/insmod:

 

1.     Reads the name of module from the command line

2.     Locates the file containing module’s object code

3.     Computes the size of memory area needed

4.     Invokes the create_module() system call

5.     Invokes the query_module() system call

6.     Using the kernel symbol table, relocates object code included in the module’s file

7.     Allocates a memory area in the user mode address space, loads it with a copy of the module object. Sets init and cleanup fields.

8.     Invokes the init_module()

9.     Releases the user mode memory area and terminates.

 

 

Linking and unlinking modules…

 

A user can unlink a module from running kernel by executing /sbin/rmmod:

 

1.     Reads the name of module from the command line

2.     Invokes the query_module() system call to get list of linked modules.

3.     Invokes the query_module() system call to retrieve dependency information.

4.     Invokes the delete_module() system call, passing the module’s name.