• 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