Saturday 3 December 2016

Introduction to kernel modules


       Objectives
        Understanding Kernel modules
       Writing a simple kernel module
       Compiling the kernel module
       Loading and unloading of modules
       Kernel log
        Module dependencies
       Modules vs Programs

Kernel modules
       Linux kernel has the ability to extend at runtime the set of features offered by the kernel. This means that you can add functionality to the kernel while the system is up and running.
       Each piece of code that can be loaded and unloaded into the kernel at runtime is called a module.
       Module extends the functionality of the kernel without the need to reboot the system.
       The Linux kernel offers support for quite a few different types (or classes) of modules, including, but not limited to, device drivers.
       Each module is made up of object code (not linked into a complete executable) that can be dynamically linked to the running kernel.

Advantages of modules
       Modules  make it easy to develop drivers without rebooting: load, test, unload, rebuild & again load and so on.
       Useful to keep the kernel size to the minimum (essential in embedded systems). Without modules , would need to build monolithic kernel and add new functionality directly into the kernel image.
       Also useful to reduce boot time, you don’t need to spend time initializing device that may not be needed at boot time.
       Once loaded, modules have full control and privileges in the system. That’s why only the root user can load and unload the modules.

Hello module
/* hello.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_init(void)
{
                printk(“Hello :This is my first kernle module\n");
                return 0;
}
static void __exit hello_exit(void)
{
                printk(“Bye, unloading the module\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_DESCRIPTION("Greeting module");
MODULE_AUTHOR(VSalve");
MODULE_LICENSE("GPL");

Module explanation
       Headers specific to the linux  kernel <linux/xxx.h>
       No access to the usual C library
       An initialization function
       Called when the module is loaded, returns an error code (0- success, negative value on failure)
       Declared by the module_init() macro:
       A cleanup function
       Called when the module is unloaded.
       Declared by the module_exit() macro.
       Metadata information declared used MODULE_DESCRIPTION and MODULE_AUTHOR

Compiling a module
       Out of tree
      When the code is outside of the kernel source tree, in a different directory.
      Advantage:  Easier to handle than modifications to the kernel itself.
      Disadv: Not integrated to the kernel configuration/compilation process, needs to be build separately, driver cannot be built statistically if needed.
       Inside the kernel tree
      Well integrated into the kernel configuration/compilation process.
      Driver can be build statistically if needed

Compiling an out-of-tree module
       Makefile to compile module
       KDIR := /path/to/kernel/sources
obj-m := hello.o
all:
                make -C $(KDIR) M=$(PWD)  modules
clean:
                make –C $(KDIR) M=$(PWD) clean


Module utilities
       modinfo <module_name>
       Gets information about the module: parameters, license, descriptions and dependencies
        insmod <module_name>.ko
       Load the given module. Full path of module is needed
        rmmod <module_name>
       Unloads the given module
        lsmod <module_name>
       Displays the list of modules loaded.
       Check cat /proc/modules

Kernel log
       When a new module is loaded, related information is available in the kernel log.
      The kernel keeps its messages in a circular buffer.
      Kernel log messages are available through the ‘dmesg’ command
      Kernel log messages can be seen in /var/log/messages file

Module dependencies
       Some kernel module can depend on other modules, which need to be loaded first.
       Dependencies are described in
                /lib/modules/<kernel-version>/modules.dep
       This file is generated when you run make modules_install
       sudo modprobe <module_name>
      Loads all the modules the given module depends on. Modprobe looks into /lib/modules/<kernel-version> for the object file corresponding to the given module
       Sudo modprobe –r <module_name>
      Remove the module and all dependent modules, which are no longer needed.

Applications Vs. Kernel modules
Application
Kernel module
Performs single task from beginning to end
Module registers itself to serve the future request and its ‘main’ function terminates on loading.
Application can call functions, which it doesn’t define. The linking stage resolves the external references loading the appropriate libraries. E.g libc for ‘printf’ function.
The module is linked only to the kernel and it can only the functions that are exported by the kernel.
No C library is linked with the kernel.


Passing command line arguments
       Modules can take command line arguments, but not with the argc/argv you might be used to.
       To allow arguments to be passed to your module, declare the variables that will take the values of the command line arguments as global and then use the module_param() macro, to set the mechanism up.
       At runtime, insmod will fill the variables with any command line arguments that are given, like ./insmod mymodule.ko myvariable=5. The variable declarations and macros should be placed at the beginning of the module for clarity.
       The module_param() macro takes 3 arguments: the name of the variable, its type and permissions for the corresponding file in sysfs. Integer types can be signed as usual or unsigned.
       int myint = 3; module_param(myint, int, 0);
       If you'd like to use arrays of integers or strings see module_param_array() and module_param_string().
       module_param(foo, int, 0000)
       The first param is the parameters name.
       The second param is it's data type
       The final argument is the permissions bits, for exposing parameters in sysfs (if non-zero) at a later stage.
        Example
       static short int myshort = 1;
       static int myint = 420;
       module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
       module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
       module_param_array(name, type, num, perm);
       The first param is the parameter's (in this case the array's) name
       The second param is the data type of the elements of the array
       The third argument is a pointer to the variable that will store the number of elements of the array initialized by the user at module loading time
       The fourth argument is the permission bits
       static int myintArray[2] = { -1, -1 };
       static int arr_argc = 0;
       module_param_array(myintArray, int, &arr_argc, 0000);

Modules spanning multiple files
/*hello_start.c*/
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
        printk("Hello :This is my first kernle module\n");
        return 0;
}
/*hello_stop.c*/
#include <linux/module.h>
#include <linux/kernel.h>
void module_cleanup(void)
{
        printk("Bye, unloading the module\n");
}
MODULE_DESCRIPTION("Greeting module");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("VSalve");

Makefile
KDIR:=/lib/modules/2.6.35-31-generic/build/
obj-m += startstop.o
startstop-objs := hello_start.o hello_stop.o
all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean

Functions available to modules
       In the hello world example, you might have noticed that we used a function, printk() but didn't include a standard I/O library.
       That's because modules are object files whose symbols get resolved upon insmod'ing.
       The definition for the symbols comes from the kernel itself; the only external functions you can use are the ones provided by the kernel.
       If you're curious about what symbols have been exported by your kernel, take a look at /proc/kallsyms.


No comments:

Post a Comment