commit 88c8d41f6e36850da7b7a122899dec8e03baea11 Author: jserv Date: Mon Aug 2 06:20:38 2021 +0000 deploy: 859af5f7279b1ce7f0cf1baf66d8aed29ed75808 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/index.html b/index.html new file mode 100644 index 0000000..fe5018c --- /dev/null +++ b/index.html @@ -0,0 +1,5148 @@ + + + The Linux Kernel Module Programming Guide + + + + + + +
+ + + + + + + +

The Linux Kernel Module Programming Guide

+
Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang

+
August 2, 2021
+ + + +
+
+  0.1 Introduction +
  0.1.1 Authorship +
  0.1.2 Acknowledgements +
  0.1.3 What Is A Kernel Module? +
  0.1.4 Kernel module package +
  0.1.5 What Modules are in my Kernel? +
  0.1.6 Do I need to download and compile the kernel? +
  0.1.7 Before We Begin +
 0.2 Headers +
 0.3 Examples +
 0.4 Hello World +
  0.4.1 The Simplest Module +
  0.4.2 Hello and Goodbye +
  0.4.3 The __init and __exit Macros +
  0.4.4 Licensing and Module Documentation +
  0.4.5 Passing Command Line Arguments to a Module +
  0.4.6 Modules Spanning Multiple Files +
  0.4.7 Building modules for a precompiled kernel +
 0.5 Preliminaries +
  0.5.1 How modules begin and end +
  0.5.2 Functions available to modules +
  0.5.3 User Space vs Kernel Space +
  0.5.4 Name Space +
  0.5.5 Code space +
  0.5.6 Device Drivers +
 0.6 Character Device drivers +
  0.6.1 The proc_ops Structure +
  0.6.2 The file structure +
  0.6.3 Registering A Device +
  0.6.4 Unregistering A Device +
  0.6.5 chardev.c +
  0.6.6 Writing Modules for Multiple Kernel Versions +
 0.7 The /proc File System +
  0.7.1 Read and Write a /proc File +
  0.7.2 Manage /proc file with standard filesystem +
  0.7.3 Manage /proc file with seq_file +
 0.8 sysfs: Interacting with your module +
 0.9 Talking To Device Files +
 0.10 System Calls +
 0.11 Blocking Processes and threads +
  0.11.1 Sleep + + + +
  0.11.2 Completions +
 0.12 Avoiding Collisions and Deadlocks +
  0.12.1 Mutex +
  0.12.2 Spinlocks +
  0.12.3 Read and write locks +
  0.12.4 Atomic operations +
 0.13 Replacing Print Macros +
  0.13.1 Replacement +
  0.13.2 Flashing keyboard LEDs +
 0.14 Scheduling Tasks +
  0.14.1 Tasklets +
  0.14.2 Work queues +
 0.15 Interrupt Handlers +
  0.15.1 Interrupt Handlers +
  0.15.2 Detecting button presses +
  0.15.3 Bottom Half +
 0.16 Crypto +
  0.16.1 Hash functions +
  0.16.2 Symmetric key encryption +
 0.17 Standardising the interfaces: The Device Model +
 0.18 Optimizations +
  0.18.1 Likely and Unlikely conditions +
 0.19 Common Pitfalls +
  0.19.1 Using standard libraries +
  0.19.2 Disabling interrupts +
  0.19.3 Sticking your head inside a large carnivore +
 0.20 Where To Go From Here? +
+

0.1 Introduction

+

The Linux Kernel Module Programming Guide is a free book; you may reproduce +and/or modify it under the terms of the Open Software License, version +3.0. +

This book is distributed in the hope it will be useful, but without any warranty, +without even the implied warranty of merchantability or fitness for a particular +purpose. +

The author encourages wide distribution of this book for personal or commercial +use, provided the above copyright notice remains intact and the method adheres to +the provisions of the Open Software License. In summary, you may copy and +distribute this book free of charge or for a profit. No explicit permission is required +from the author for reproduction of this book in any medium, physical or +electronic. +

Derivative works and translations of this document must be placed under the +Open Software License, and the original copyright notice must remain intact. If you +have contributed new material to this book, you must make the material and source +code available for your revisions. Please make revisions and updates available directly + + + +to the document maintainer, Peter Jay Salzman <p@dirac.org>. This will allow +for the merging of updates and provide consistent revisions to the Linux +community. +

If you publish or distribute this book commercially, donations, royalties, and/or +printed copies are greatly appreciated by the author and the Linux Documentation +Project (LDP). Contributing in this way shows your support for free software and +the LDP. If you have questions or comments, please contact the address +above. +

+

+

0.1.1 Authorship

+

The Linux Kernel Module Programming Guide was originally written for the 2.2 +kernels by Ori Pomerantz. Eventually, Ori no longer had time to maintain the +document. After all, the Linux kernel is a fast moving target. Peter Jay Salzman took +over maintenance and updated it for the 2.4 kernels. Eventually, Peter no longer had +time to follow developments with the 2.6 kernel, so Michael Burian became a +co-maintainer to update the document for the 2.6 kernels. Bob Mottram updated the +examples for 3.8+ kernels. Jim Huang upgraded to recent kernel versions (v5.x) and +revise LaTeX scripts. +

+

+

0.1.2 Acknowledgements

+

The following people have contributed corrections or good suggestions: Ignacio +Martin, David Porter, Daniele Paolo Scarpazza, Dimo Velev, Francois Audeon, Horst +Schirmeier, and Roman Lakeev. +

+

+

0.1.3 What Is A Kernel Module?

+

So, you want to write a kernel module. You know C, you have written a few normal +programs to run as processes, and now you want to get to where the real action is, to +where a single wild pointer can wipe out your file system and a core dump means a +reboot. +

What exactly is a kernel module? Modules are pieces of code that can be loaded +and unloaded into the kernel upon demand. They extend the functionality of the +kernel without the need to reboot the system. For example, one type of module is the +device driver, which allows the kernel to access hardware connected to the system. +Without modules, we would have to build monolithic kernels and add new +functionality directly into the kernel image. Besides having larger kernels, this has +the disadvantage of requiring us to rebuild and reboot the kernel every time we want + + + +new functionality. +

+

+

0.1.4 Kernel module package

+

Linux distributions provide the commands modprobe, insmod and depmod within a +package. +

On Ubuntu/Debian: +

+
1sudo apt-get install build-essential kmod
+

On Arch Linux: +

+
1sudo pacman -S gcc kmod
+

+

+

0.1.5 What Modules are in my Kernel?

+

To discover what modules are already loaded within your current kernel use the +command lsmod. +

+
1sudo lsmod
+

Modules are stored within the file /proc/modules, so you can also see them with: +

+
1sudo cat /proc/modules
+

This can be a long list, and you might prefer to search for something particular. +To search for the fat module: +

+
1sudo lsmod | grep fat
+ + + +

+

+

0.1.6 Do I need to download and compile the kernel?

+

For the purposes of following this guide you don’t necessarily need to do that. +However, it would be wise to run the examples within a test distribution running +on a virtual machine in order to avoid any possibility of messing up your +system. +

+

+

0.1.7 Before We Begin

+

Before we delve into code, there are a few issues we need to cover. Everyone’s system +is different and everyone has their own groove. Getting your first "hello world" +program to compile and load correctly can sometimes be a trick. Rest assured, after +you get over the initial hurdle of doing it for the first time, it will be smooth sailing +thereafter. +

+

    +
  1. Modversioning. A module compiled for one kernel will not load if you boot + a different kernel unless you enable CONFIG_MODVERSIONS in the kernel. + We will not go into module versioning until later in this guide. Until + we cover modversions, the examples in the guide may not work if you + are running a kernel with modversioning turned on. However, most stock + Linux distribution kernels come with it turned on. If you are having trouble + loading the modules because of versioning errors, compile a kernel with + modversioning turned off. +
  2. +
  3. +

    Using X Window System. It is highly recommended that you extract, + compile and load all the examples this guide discusses. It is also highly + recommended you do this from a console. You should not be working on + this stuff in X Window System. +

    Modules can not print to the screen like printf() can, but they can log + information and warnings, which ends up being printed on your screen, but + only on a console. If you insmod a module from an xterm, the information + and warnings will be logged, but only to your systemd journal. You will + not see it unless you look through your journalctl. See 0.4 for details. + To have immediate access to this information, do all your work from the + console.

+ + + +

+

+

0.2 Headers

+

Before you can build anything you’ll need to install the header files for your +kernel. +

On Ubuntu/Debian: +

+
1sudo apt-get update 
+2apt-cache search linux-headers-`uname -r`
+

On Arch Linux: +

+
1sudo pacman -S linux-libre-headers
+

This will tell you what kernel header files are available. Then for example: +

+
1sudo apt-get install kmod linux-headers-5.4.0-80-generic
+

+

+

0.3 Examples

+

All the examples from this document are available within the examples subdirectory. +

If there are any compile errors then you might have a more recent kernel version +or need to install the corresponding kernel header files. +

+

+

0.4 Hello World

+ + + +

+

+

0.4.1 The Simplest Module

+

Most people learning programming start out with some sort of "hello world" +example. I don’t know what happens to people who break with this tradition, but I +think it is safer not to find out. We will start with a series of hello world +programs that demonstrate the different aspects of the basics of writing a kernel +module. +

Here is the simplest module possible. +

Make a test directory: +

+
1mkdir -p ~/develop/kernel/hello-1 
+2cd ~/develop/kernel/hello-1
+

Paste this into you favorite editor and save it as hello-1.c: +

+

+
1/* 
+2 *  hello-1.c - The simplest kernel module. 
+3 */ 
+4#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+5#include <linux/module.h> /* Needed by all modules */ 
+6 
+7int init_module(void) 
+8{ 
+9    pr_info("Hello world 1.\n"); 
+10 
+11    /* 
+12     * A non 0 return means init_module failed; module can't be loaded. 
+13     */ 
+14    return 0; 
+15} 
+16 
+17void cleanup_module(void) 
+18{ 
+19    pr_info("Goodbye world 1.\n"); 
+20} 
+21 
+22MODULE_LICENSE("GPL");
+

Now you will need a Makefile. If you copy and paste this, change the indentation +to use tabs, not spaces. +

+

+
1obj-m += hello-1.o 
+2 
+3all: 
+4              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+5 
+6clean: 
+7              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

And finally just: +

+
1make
+

If all goes smoothly you should then find that you have a compiled hello-1.ko +module. You can find info on it with the command: +

+
1sudo modinfo hello-1.ko
+

At this point the command: +

+
1sudo lsmod | grep hello
+

should return nothing. You can try loading your shiny new module with: + + + +

+
1sudo insmod hello-1.ko
+

The dash character will get converted to an underscore, so when you again try: +

+
1sudo lsmod | grep hello
+

you should now see your loaded module. It can be removed again with: +

+
1sudo rmmod hello_1
+

Notice that the dash was replaced by an underscore. To see what just happened in +the logs: +

+
1journalctl --since "1 hour ago" | grep kernel
+

You now know the basics of creating, compiling, installing and removing modules. +Now for more of a description of how this module works. +

Kernel modules must have at least two functions: a "start" (initialization) +function called init_module() which is called when the module is insmoded into +the kernel, and an "end" (cleanup) function called cleanup_module() which is +called just before it is removed from the kernel. Actually, things have changed +starting with kernel 2.3.13. You can now use whatever name you like for the start and +end functions of a module, and you will learn how to do this in Section 2.3. +In fact, the new method is the preferred method. However, many people +still use init_module() and cleanup_module() for their start and end +functions. +

Typically, init_module() either registers a handler for something with the kernel, +or it replaces one of the kernel functions with its own code (usually code to do +something and then call the original function). The cleanup_module() function is +supposed to undo whatever init_module() did, so the module can be unloaded +safely. +

Lastly, every kernel module needs to include linux/module.h. We needed to +include linux/kernel.h only for the macro expansion for the pr_alert() log level, +which you’ll learn about in Section 2.1.1. +

+

    + + + +
  1. A point about coding style. Another thing which may not be immediately + obvious to anyone getting started with kernel programming is that + indentation within your code should be using tabs and not spaces. It is + one of the coding conventions of the kernel. You may not like it, but you’ll + need to get used to it if you ever submit a patch upstream. +
  2. +
  3. Introducing print macros. In the beginning there was printk, usually + followed by a priority such as KERN_INFO or KERN_DEBUG. More recently + this can also be expressed in abbreviated form using a set of print macros, + such as pr_info and pr_debug. This just saves some mindless keyboard + bashing and looks a bit neater. They can be found within linux/printk.h. + Take time to read through the available priority macros. +
  4. +
  5. +

    About Compiling. Kernel modules need to be compiled a bit differently + from regular userspace apps. Former kernel versions required us to + care much about these settings, which are usually stored in Makefiles. + Although hierarchically organized, many redundant settings accumulated + in sublevel Makefiles and made them large and rather difficult to maintain. + Fortunately, there is a new way of doing these things, called kbuild, and + the build process for external loadable modules is now fully integrated into + the standard kernel build mechanism. To learn more on how to compile + modules which are not part of the official kernel (such as all the examples + you will find in this guide), see file Documentation/kbuild/modules.rst. +

    Additional details about Makefiles for kernel modules are available in + Documentation/kbuild/makefiles.rst. Be sure to read this and the + related files before starting to hack Makefiles. It will probably save you + lots of work. +

    +

    +

    Here is another exercise for the reader. See that comment above + the return statement in init_module()? Change the return + value to something negative, recompile and load the module + again. What happens?

    +
+ + + +

+

+

0.4.2 Hello and Goodbye

+

In early kernel versions you had to use the init_module and cleanup_module +functions, as in the first hello world example, but these days you can name those +anything you want by using the module_init and module_exit macros. +These macros are defined in linux/init.h. The only requirement is that +your init and cleanup functions must be defined before calling the those +macros, otherwise you’ll get compilation errors. Here is an example of this +technique: +

+

+
1/* 
+2 *  hello-2.c - Demonstrating the module_init() and module_exit() macros. 
+3 *  This is preferred over using init_module() and cleanup_module(). 
+4 */ 
+5#include <linux/init.h>   /* Needed for the macros */ 
+6#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+7#include <linux/module.h> /* Needed by all modules */ 
+8 
+9static int __init hello_2_init(void) 
+10{ 
+11    pr_info("Hello, world 2\n"); 
+12    return 0; 
+13} 
+14 
+15static void __exit hello_2_exit(void) 
+16{ 
+17    pr_info("Goodbye, world 2\n"); 
+18} 
+19 
+20module_init(hello_2_init); 
+21module_exit(hello_2_exit); 
+22 
+23MODULE_LICENSE("GPL");
+

So now we have two real kernel modules under our belt. Adding another module +is as simple as this: +

+

+
1obj-m += hello-1.o 
+2obj-m += hello-2.o 
+3 
+4all: 
+5              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+6 
+7clean: 
+8              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

Now have a look at linux/drivers/char/Makefile for a real world example. As +you can see, some things get hardwired into the kernel (obj-y) but where are all +those obj-m gone? Those familiar with shell scripts will easily be able to spot them. +For those not, the obj-$(CONFIG_FOO) entries you see everywhere expand into obj-y +or obj-m, depending on whether the CONFIG_FOO variable has been set to y or m. +While we are at it, those were exactly the kind of variables that you have set in the +linux/.config file, the last time when you said make menuconfig or something like +that. +

+

+

0.4.3 The __init and __exit Macros

+

This demonstrates a feature of kernel 2.2 and later. Notice the change in the +definitions of the init and cleanup functions. The __init macro causes the init +function to be discarded and its memory freed once the init function finishes for +built-in drivers, but not loadable modules. If you think about when the init function +is invoked, this makes perfect sense. +

There is also an __initdata which works similarly to __init but for init +variables rather than functions. +

The __exit macro causes the omission of the function when the module is +built into the kernel, and like __init, has no effect for loadable modules. +Again, if you consider when the cleanup function runs, this makes complete +sense; built-in drivers do not need a cleanup function, while loadable modules +do. + + + +

These macros are defined in linux/init.h and serve to free up kernel memory. +When you boot your kernel and see something like Freeing unused kernel memory: +236k freed, this is precisely what the kernel is freeing. +

+

+
1/* 
+2 *  hello-3.c - Illustrating the __init, __initdata and __exit macros. 
+3 */ 
+4#include <linux/init.h>   /* Needed for the macros */ 
+5#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+6#include <linux/module.h> /* Needed by all modules */ 
+7 
+8static int hello3_data __initdata = 3; 
+9 
+10static int __init hello_3_init(void) 
+11{ 
+12    pr_info("Hello, world %d\n", hello3_data); 
+13    return 0; 
+14} 
+15 
+16static void __exit hello_3_exit(void) 
+17{ 
+18    pr_info("Goodbye, world 3\n"); 
+19} 
+20 
+21module_init(hello_3_init); 
+22module_exit(hello_3_exit); 
+23 
+24MODULE_LICENSE("GPL");
+

+

+

0.4.4 Licensing and Module Documentation

+

Honestly, who loads or even cares about proprietary modules? If you do then you +might have seen something like this: + + + +

+
+$ sudo insmod xxxxxx.ko
+loading out-of-tree module taints kernel.
+module license 'unspecified' taints kernel.
+
+

+

You can use a few macros to indicate the license for your module. Some examples +are "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual +MIT/GPL", "Dual MPL/GPL" and "Proprietary". They are defined within +linux/module.h. +

To reference what license you’re using a macro is available called +MODULE_LICENSE. This and a few other macros describing the module are +illustrated in the below example. +

+

+
1/* 
+2 *  hello-4.c - Demonstrates module documentation. 
+3 */ 
+4#include <linux/init.h>   /* Needed for the macros */ 
+5#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+6#include <linux/module.h> /* Needed by all modules */ 
+7 
+8MODULE_LICENSE("GPL"); 
+9MODULE_AUTHOR("LKMPG"); 
+10MODULE_DESCRIPTION("A sample driver"); 
+11MODULE_SUPPORTED_DEVICE("testdevice"); 
+12 
+13static int __init init_hello_4(void) 
+14{ 
+15    pr_info("Hello, world 4\n"); 
+16    return 0; 
+17} 
+18 
+19static void __exit cleanup_hello_4(void) 
+20{ 
+21    pr_info("Goodbye, world 4\n"); 
+22} 
+23 
+24module_init(init_hello_4); 
+25module_exit(cleanup_hello_4);
+

+

+

0.4.5 Passing Command Line Arguments to a Module

+

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, (defined in linux/moduleparam.h) 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 example code should clear up my admittedly lousy +explanation. +

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. If you’d like to use arrays of integers or strings see +module_param_array() and module_param_string(). +

+

+
1int myint = 3; 
+2module_param(myint, int, 0);
+

Arrays are supported too, but things are a bit different now than they were in the +olden days. To keep track of the number of parameters you need to pass a + + + +pointer to a count variable as third parameter. At your option, you could +also ignore the count and pass NULL instead. We show both possibilities +here: +

+

+
1int myintarray[2]; 
+2module_param_array(myintarray, int, NULL, 0); /* not interested in count */ 
+3 
+4short myshortarray[4]; 
+5int count; 
+6module_param_array(myshortarray, short, &count, 0); /* put count into "count" variable */
+

A good use for this is to have the module variable’s default values set, like an port +or IO address. If the variables contain the default values, then perform autodetection +(explained elsewhere). Otherwise, keep the current value. This will be made clear +later on. +

Lastly, there’s a macro function, MODULE_PARM_DESC(), that is used to +document arguments that the module can take. It takes two parameters: a variable +name and a free form string describing that variable. +

+

+
1/* 
+2 *  hello-5.c - Demonstrates command line argument passing to a module. 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/moduleparam.h> 
+8#include <linux/stat.h> 
+9 
+10MODULE_LICENSE("GPL"); 
+11 
+12static short int myshort = 1; 
+13static int myint = 420; 
+14static long int mylong = 9999; 
+15static char *mystring = "blah"; 
+16static int myintArray[2] = {-1, -1}; 
+17static int arr_argc = 0; 
+18 
+19/* 
+20 * module_param(foo, int, 0000) 
+21 * The first param is the parameters name 
+22 * The second param is it's data type 
+23 * The final argument is the permissions bits, 
+24 * for exposing parameters in sysfs (if non-zero) at a later stage. 
+25 */ 
+26 
+27module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 
+28MODULE_PARM_DESC(myshort, "A short integer"); 
+29module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 
+30MODULE_PARM_DESC(myint, "An integer"); 
+31module_param(mylong, long, S_IRUSR); 
+32MODULE_PARM_DESC(mylong, "A long integer"); 
+33module_param(mystring, charp, 0000); 
+34MODULE_PARM_DESC(mystring, "A character string"); 
+35 
+36/* 
+37 * module_param_array(name, type, num, perm); 
+38 * The first param is the parameter's (in this case the array's) name 
+39 * The second param is the data type of the elements of the array 
+40 * The third argument is a pointer to the variable that will store the number 
+41 * of elements of the array initialized by the user at module loading time 
+42 * The fourth argument is the permission bits 
+43 */ 
+44module_param_array(myintArray, int, &arr_argc, 0000); 
+45MODULE_PARM_DESC(myintArray, "An array of integers"); 
+46 
+47static int __init hello_5_init(void) 
+48{ 
+49    int i; 
+50    pr_info("Hello, world 5\n=============\n"); 
+51    pr_info("myshort is a short integer: %hd\n", myshort); 
+52    pr_info("myint is an integer: %d\n", myint); 
+53    pr_info("mylong is a long integer: %ld\n", mylong); 
+54    pr_info("mystring is a string: %s\n", mystring); 
+55 
+56    for (i = 0; i < (sizeof myintArray / sizeof(int)); i++) 
+57        pr_info("myintArray[%d] = %d\n", i, myintArray[i]); 
+58 
+59    pr_info("got %d arguments for myintArray.\n", arr_argc); 
+60    return 0; 
+61} 
+62 
+63static void __exit hello_5_exit(void) 
+64{ 
+65    pr_info("Goodbye, world 5\n"); 
+66} 
+67 
+68module_init(hello_5_init); 
+69module_exit(hello_5_exit);
+

I would recommend playing around with this code: +

+
1$ sudo insmod hello-5.ko mystring="bebop" myintArray=-1 
+2myshort is a short integer: 1 
+3myint is an integer: 20 
+4mylong is a long integer: 9999 
+5mystring is a string: bebop 
+6myintArray is -1 and 420 
+7 
+8$ sudo rmmod hello-5 
+9Goodbye, world 5 
+10 
+11$ sudo insmod hello-5.ko mystring="supercalifragilisticexpialidocious" myintArray=-1,-1 
+12myshort is a short integer: 1 
+13myint is an integer: 20 
+14mylong is a long integer: 9999 
+15mystring is a string: supercalifragilisticexpialidocious 
+16myintArray is -1 and -1 
+17 
+18$ sudo rmmod hello-5 
+19Goodbye, world 5 
+20 
+21$ sudo insmod hello-5.ko mylong=hello 
+22hello-5.o: invalid argument syntax for mylong: 'h'
+

+

+

0.4.6 Modules Spanning Multiple Files

+

Sometimes it makes sense to divide a kernel module between several source +files. +

Here is an example of such a kernel module. +

+
1/* 
+2 *  start.c - Illustration of multi filed modules 
+3 */ 
+4 
+5#include <linux/kernel.h> /* We're doing kernel work */ 
+6#include <linux/module.h> /* Specifically, a module */ 
+7 
+8int init_module(void) 
+9{ 
+10    pr_info("Hello, world - this is the kernel speaking\n"); 
+11    return 0; 
+12} 
+13 
+14MODULE_LICENSE("GPL");
+

The next file: +

+
1/* 
+2 *  stop.c - Illustration of multi filed modules 
+3 */ 
+4 
+5#include <linux/kernel.h> /* We're doing kernel work */ 
+6#include <linux/module.h> /* Specifically, a module  */ 
+7 
+8void cleanup_module() 
+9{ 
+10    pr_info("Short is the life of a kernel module\n"); 
+11} 
+12 
+13MODULE_LICENSE("GPL");
+

And finally, the makefile: +

+

+
1obj-m += hello-1.o 
+2obj-m += hello-2.o 
+3obj-m += hello-3.o 
+4obj-m += hello-4.o 
+5obj-m += hello-5.o 
+6obj-m += startstop.o 
+7startstop-objs := start.o stop.o 
+8 
+9all: 
+10              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+11 
+12clean: 
+13              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

This is the complete makefile for all the examples we have seen so far. The first +five lines are nothing special, but for the last example we will need two lines. First we +invent an object name for our combined module, second we tell make what object +files are part of that module. + + + +

+

+

0.4.7 Building modules for a precompiled kernel

+

Obviously, we strongly suggest you to recompile your kernel, so that you can enable +a number of useful debugging features, such as forced module unloading +(MODULE_FORCE_UNLOAD): when this option is enabled, you can force the +kernel to unload a module even when it believes it is unsafe, via a sudo rmmod -f +module command. This option can save you a lot of time and a number of reboots +during the development of a module. If you do not want to recompile your kernel +then you should consider running the examples within a test distribution on a virtual +machine. If you mess anything up then you can easily reboot or restore the virtual +machine (VM). +

There are a number of cases in which you may want to load your module into a +precompiled running kernel, such as the ones shipped with common Linux +distributions, or a kernel you have compiled in the past. In certain circumstances you +could require to compile and insert a module into a running kernel which you are not +allowed to recompile, or on a machine that you prefer not to reboot. If you +can’t think of a case that will force you to use modules for a precompiled +kernel you might want to skip this and treat the rest of this chapter as a big +footnote. +

Now, if you just install a kernel source tree, use it to compile your kernel module +and you try to insert your module into the kernel, in most cases you would obtain an +error as follows: + + + +

+
+insmod: error inserting 'poet_atkm.ko': -1 Invalid module format
+
+

+

Less cryptical information are logged to the systemd journal: + + + +

+
+Jun  4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
+REGPARM 4KSTACKS gcc-3.3' should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'
+
+

+

In other words, your kernel refuses to accept your module because version strings +(more precisely, version magics) do not match. Incidentally, version magics are stored +in the module object in the form of a static string, starting with vermagic:. Version +data are inserted in your module when it is linked against the init/vermagic.o file. +To inspect version magics and other strings stored in a given module, issue the +modinfo module.ko command: + + + +

+
+$ modinfo hello-4.ko
+description:    A sample driver
+author:         LKMPG
+license:        GPL
+srcversion:     B2AA7FBFCC2C39AED665382
+depends:
+retpoline:      Y
+name:           hello_4
+vermagic:       5.4.0-70-generic SMP mod_unload modversions
+
+

+

To overcome this problem we could resort to the –force-vermagic option, but +this solution is potentially unsafe, and unquestionably inacceptable in production +modules. Consequently, we want to compile our module in an environment which was +identical to the one in which our precompiled kernel was built. How to do this, is the +subject of the remainder of this chapter. +

First of all, make sure that a kernel source tree is available, having exactly the +same version as your current kernel. Then, find the configuration file which was used +to compile your precompiled kernel. Usually, this is available in your current boot +directory, under a name like config-2.6.x. You may just want to copy it to your kernel +source tree: cp /boot/config-`uname -r` .config. +

Let’s focus again on the previous error message: a closer look at the version magic +strings suggests that, even with two configuration files which are exactly the same, a +slight difference in the version magic could be possible, and it is sufficient to prevent +insertion of the module into the kernel. That slight difference, namely the custom +string which appears in the module’s version magic and not in the kernel’s one, +is due to a modification with respect to the original, in the makefile that +some distribution include. Then, examine your /usr/src/linux/Makefile, +and make sure that the specified version information matches exactly the +one used for your current kernel. For example, you makefile could start as +follows: + + + +

+
+VERSION = 5
+PATCHLEVEL = 14
+SUBLEVEL = 0
+EXTRAVERSION = -rc2
+
+

+

In this case, you need to restore the value of symbol EXTRAVERSION to +-rc2. We suggest to keep a backup copy of the makefile used to compile +your kernel available in /lib/modules/5.14.0-rc2/build. A simple cp +/lib/modules/‘uname-r‘/build/Makefile /usr/src/linux-‘uname -r‘ should +suffice. Additionally, if you already started a kernel build with the previous (wrong) +Makefile, you should also rerun make, or directly modify symbol UTS_RELEASE in +file /usr/src/linux-5.14.0/include/linux/version.h according to contents of file +/lib/modules/5.14.0/build/include/linux/version.h, or overwrite the latter +with the first. +

Now, please run make to update configuration and version headers and +objects: + + + +

+
+$ make
+CHK     include/linux/version.h
+UPD     include/linux/version.h
+SYMLINK include/asm -> include/asm-i386
+SPLIT   include/linux/autoconf.h -> include/config/*
+HOSTCC  scripts/basic/fixdep
+HOSTCC  scripts/basic/split-include
+HOSTCC  scripts/basic/docproc
+HOSTCC  scripts/conmakehash
+HOSTCC  scripts/kallsyms
+CC      scripts/empty.o
+
+

+

If you do not desire to actually compile the kernel, you can interrupt the build +process (CTRL-C) just after the SPLIT line, because at that time, the files you need +will be are ready. Now you can turn back to the directory of your module and +compile it: It will be built exactly according to your current kernel settings, and it +will load into it without any errors. +

+

+

0.5 Preliminaries

+

+

+

0.5.1 How modules begin and end

+

A program usually begins with a main() function, executes a bunch of instructions +and terminates upon completion of those instructions. Kernel modules work a bit +differently. A module always begin with either the init_module or the function you +specify with module_init call. This is the entry function for modules; it tells the +kernel what functionality the module provides and sets up the kernel to run the +module’s functions when they are needed. Once it does this, entry function returns +and the module does nothing until the kernel wants to do something with the code +that the module provides. +

All modules end by calling either cleanup_module or the function you specify +with the module_exit call. This is the exit function for modules; it undoes +whatever entry function did. It unregisters the functionality that the entry function +registered. + + + +

Every module must have an entry function and an exit function. Since there’s +more than one way to specify entry and exit functions, I’ll try my best to use the +terms “entry function” and “exit function”, but if I slip and simply refer +to them as init_module and cleanup_module, I think you’ll know what I +mean. +

+

+

0.5.2 Functions available to modules

+

Programmers use functions they do not define all the time. A prime example of +this is printf(). You use these library functions which are provided by the +standard C library, libc. The definitions for these functions do not actually +enter your program until the linking stage, which insures that the code (for +printf() for example) is available, and fixes the call instruction to point to that +code. +

Kernel modules are different here, too. In the hello world example, you might +have noticed that we used a function, pr_info() but did not include a standard I/O +library. That is 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. +

One point to keep in mind is the difference between library functions +and system calls. Library functions are higher level, run completely in user +space and provide a more convenient interface for the programmer to the +functions that do the real work — system calls. System calls run in kernel +mode on the user’s behalf and are provided by the kernel itself. The library +function printf() may look like a very general printing function, but all it +really does is format the data into strings and write the string data using +the low-level system call write(), which then sends the data to standard +output. +

Would you like to see what system calls are made by printf()? It is easy! Compile +the following program: +

+

+
1#include <stdio.h> 
+2 
+3int main(void) 
+4{ 
+5    printf("hello"); 
+6    return 0; 
+7}
+

with gcc -Wall -o hello hello.c. Run the exectable with strace ./hello. Are +you impressed? Every line you see corresponds to a system call. strace is a handy +program that gives you details about what system calls a program is making, +including which call is made, what its arguments are and what it returns. It is an +invaluable tool for figuring out things like what files a program is trying to access. +Towards the end, you will see a line which looks like write(1, "hello", 5hello). +There it is. The face behind the printf() mask. You may not be familiar with write, +since most people use library functions for file I/O (like fopen, fputs, fclose). If that + + + +is the case, try looking at man 2 write. The 2nd man section is devoted +to system calls (like kill() and read()). The 3rd man section is devoted to +library calls, which you would probably be more familiar with (like cosh() and +random()). +

You can even write modules to replace the kernel’s system calls, which we will do +shortly. Crackers often make use of this sort of thing for backdoors or trojans, but +you can write your own modules to do more benign things, like have the kernel +write Tee hee, that tickles! everytime someone tries to delete a file on your +system. +

+

+

0.5.3 User Space vs Kernel Space

+

A kernel is all about access to resources, whether the resource in question happens to +be a video card, a hard drive or even memory. Programs often compete for the same +resource. As I just saved this document, updatedb started updating the locate +database. My vim session and updatedb are both using the hard drive concurrently. +The kernel needs to keep things orderly, and not give users access to resources +whenever they feel like it. To this end, a CPU can run in different modes. Each mode +gives a different level of freedom to do what you want on the system. The Intel 80386 +architecture had 4 of these modes, which were called rings. Unix uses only +two rings; the highest ring (ring 0, also known as “supervisor mode” where +everything is allowed to happen) and the lowest ring, which is called “user +mode”. +

Recall the discussion about library functions vs system calls. Typically, you use a +library function in user mode. The library function calls one or more system calls, +and these system calls execute on the library function’s behalf, but do so in +supervisor mode since they are part of the kernel itself. Once the system call +completes its task, it returns and execution gets transfered back to user +mode. +

+

+

0.5.4 Name Space

+

When you write a small C program, you use variables which are convenient and make +sense to the reader. If, on the other hand, you are writing routines which will be part +of a bigger problem, any global variables you have are part of a community of other +peoples’ global variables; some of the variable names can clash. When a program has +lots of global variables which aren’t meaningful enough to be distinguished, you get +namespace pollution. In large projects, effort must be made to remember reserved +names, and to find ways to develop a scheme for naming unique variable names and +symbols. +

When writing kernel code, even the smallest module will be linked against the + + + +entire kernel, so this is definitely an issue. The best way to deal with this is to declare +all your variables as static and to use a well-defined prefix for your symbols. By +convention, all kernel prefixes are lowercase. If you do not want to declare everything +as static, another option is to declare a symbol table and register it with a kernel. We +will get to this later. +

The file /proc/kallsyms holds all the symbols that the kernel knows about and +which are therefore accessible to your modules since they share the kernel’s +codespace. +

+

+

0.5.5 Code space

+

Memory management is a very complicated subject and the majority of O’Reilly’s +"Understanding The Linux Kernel" exclusively covers memory management! +We are not setting out to be experts on memory managements, but we do +need to know a couple of facts to even begin worrying about writing real +modules. +

If you have not thought about what a segfault really means, you may be surprised +to hear that pointers do not actually point to memory locations. Not real +ones, anyway. When a process is created, the kernel sets aside a portion of +real physical memory and hands it to the process to use for its executing +code, variables, stack, heap and other things which a computer scientist +would know about. This memory begins with 0x00000000 and extends up to +whatever it needs to be. Since the memory space for any two processes do not +overlap, every process that can access a memory address, say 0xbffff978, would +be accessing a different location in real physical memory! The processes +would be accessing an index named 0xbffff978 which points to some kind of +offset into the region of memory set aside for that particular process. For +the most part, a process like our Hello, World program can’t access the +space of another process, although there are ways which we will talk about +later. +

The kernel has its own space of memory as well. Since a module is code which +can be dynamically inserted and removed in the kernel (as opposed to a +semi-autonomous object), it shares the kernel’s codespace rather than having its own. +Therefore, if your module segfaults, the kernel segfaults. And if you start writing +over data because of an off-by-one error, then you’re trampling on kernel +data (or code). This is even worse than it sounds, so try your best to be +careful. +

By the way, I would like to point out that the above discussion is true for any +operating system which uses a monolithic kernel. This is not quite the same thing as +"building all your modules into the kernel", although the idea is the same. There are +things called microkernels which have modules which get their own codespace. The +GNU Hurd and the Zircon kernel of Google Fuchsia are two examples of a +microkernel. + + + +

+

+

0.5.6 Device Drivers

+

One class of module is the device driver, which provides functionality for hardware +like a serial port. On Unix, each piece of hardware is represented by a file located in +/dev named a device file which provides the means to communicate with the +hardware. The device driver provides the communication on behalf of a +user program. So the es1370.ko sound card device driver might connect the +/dev/sound device file to the Ensoniq IS1370 sound card. A userspace program like +mp3blaster can use /dev/sound without ever knowing what kind of sound card is +installed. +

Let’s look at some device files. Here are device files which represent the first three +partitions on the primary master IDE hard drive: + + + +

+
+$ ls -l /dev/hda[1-3]
+brw-rw----  1 root  disk  3, 1 Jul  5  2000 /dev/hda1
+brw-rw----  1 root  disk  3, 2 Jul  5  2000 /dev/hda2
+brw-rw----  1 root  disk  3, 3 Jul  5  2000 /dev/hda3
+
+

+

Notice the column of numbers separated by a comma. The first number is called +the device’s major number. The second number is the minor number. The major +number tells you which driver is used to access the hardware. Each driver is assigned +a unique major number; all device files with the same major number are controlled +by the same driver. All the above major numbers are 3, because they’re all controlled +by the same driver. +

The minor number is used by the driver to distinguish between the various +hardware it controls. Returning to the example above, although all three devices are +handled by the same driver they have unique minor numbers because the driver sees +them as being different pieces of hardware. +

Devices are divided into two types: character devices and block devices. The +difference is that block devices have a buffer for requests, so they can choose the best +order in which to respond to the requests. This is important in the case of storage +devices, where it is faster to read or write sectors which are close to each other, +rather than those which are further apart. Another difference is that block devices +can only accept input and return output in blocks (whose size can vary according to +the device), whereas character devices are allowed to use as many or as few bytes +as they like. Most devices in the world are character, because they don’t +need this type of buffering, and they don’t operate with a fixed block size. +You can tell whether a device file is for a block device or a character device +by looking at the first character in the output of ls -l. If it is ‘b’ then it +is a block device, and if it is ‘c’ then it is a character device. The devices +you see above are block devices. Here are some character devices (the serial +ports): + + + +

+
+crw-rw----  1 root  dial 4, 64 Feb 18 23:34 /dev/ttyS0
+crw-r-----  1 root  dial 4, 65 Nov 17 10:26 /dev/ttyS1
+crw-rw----  1 root  dial 4, 66 Jul  5  2000 /dev/ttyS2
+crw-rw----  1 root  dial 4, 67 Jul  5  2000 /dev/ttyS3
+
+

+

If you want to see which major numbers have been assigned, you can look at +Documentation/devices.txt. +

When the system was installed, all of those device files were created by the +mknod command. To create a new char device named ‘coffee’ with major/minor +number 12 and 2, simply do mknod /dev/coffee c 12 2. You do not have to put your +device files into /dev, but it is done by convention. Linus put his device files in /dev, +and so should you. However, when creating a device file for testing purposes, it is +probably OK to place it in your working directory where you compile the kernel +module. Just be sure to put it in the right place when you’re done writing the device +driver. +

I would like to make a few last points which are implicit from the above +discussion, but I would like to make them explicit just in case. When a device file is +accessed, the kernel uses the major number of the file to determine which driver +should be used to handle the access. This means that the kernel doesn’t really need +to use or even know about the minor number. The driver itself is the only thing that +cares about the minor number. It uses the minor number to distinguish between +different pieces of hardware. +

By the way, when I say "hardware", I mean something a bit more abstract +than a PCI card that you can hold in your hand. Look at these two device +files: + + + +

+
+$ ls -l /dev/sda /dev/sdb
+brw-rw---- 1 root disk 8,  0 Jan  3 09:02 /dev/sda
+brw-rw---- 1 root disk 8, 16 Jan  3 09:02 /dev/sdb
+
+

+

By now you can look at these two device files and know instantly that they are +block devices and are handled by same driver (block major 8). Sometimes two device +files with the same major but different minor number can actually represent the same +piece of physical hardware. So just be aware that the word “hardware” in our +discussion can mean something very abstract. +

+

+

0.6 Character Device drivers

+

+

+

0.6.1 The proc_ops Structure

+

The proc_ops structure is defined in /usr/include/linux/fs.h, and holds pointers +to functions defined by the driver that perform various operations on the device. +Each field of the structure corresponds to the address of some function defined by the +driver to handle a requested operation. +

For example, every character driver needs to define a function that reads from the +device. The proc_ops structure holds the address of the module’s function that +performs that operation. Here is what the definition looks like for kernel +3.0: +

+

+
1struct proc_ops { 
+2    struct module *owner; 
+3    loff_t (*llseek) (struct file *, loff_t, int); 
+4    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 
+5    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 
+6    ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); 
+7    ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); 
+8    int (*iterate) (struct file *, struct dir_context *); 
+9    unsigned int (*poll) (struct file *, struct poll_table_struct *); 
+10    long (*unlocked_ioctl) (struct file *, unsigned intunsigned long); 
+11    long (*compat_ioctl) (struct file *, unsigned intunsigned long); 
+12    int (*mmap) (struct file *, struct vm_area_struct *); 
+13    int (*open) (struct inode *, struct file *); 
+14    int (*flush) (struct file *, fl_owner_t id); 
+15    int (*release) (struct inode *, struct file *); 
+16    int (*fsync) (struct file *, loff_t, loff_t, int datasync); 
+17    int (*aio_fsync) (struct kiocb *, int datasync); 
+18    int (*fasync) (intstruct file *, int); 
+19    int (*lock) (struct file *, intstruct file_lock *); 
+20    ssize_t (*sendpage) (struct file *, struct page *, intsize_t, loff_t *, int); 
+21    unsigned long (*get_unmapped_area)(struct file *, unsigned longunsigned longunsigned longunsigned long); 
+22    int (*check_flags)(int); 
+23    int (*flock) (struct file *, intstruct file_lock *); 
+24    ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_tunsigned int); 
+25    ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_tunsigned int); 
+26    int (*setlease)(struct file *, longstruct file_lock **); 
+27    long (*fallocate)(struct file *file, int mode, loff_t offset, 
+28                    loff_t len); 
+29    int (*show_fdinfo)(struct seq_file *m, struct file *f); 
+30};
+

Some operations are not implemented by a driver. For example, a driver that +handles a video card will not need to read from a directory structure. The +corresponding entries in the proc_ops structure should be set to NULL. +

There is a gcc extension that makes assigning to this structure more convenient. +You will see it in modern drivers, and may catch you by surprise. This is what the +new way of assigning to the structure looks like: +

+

+
1struct proc_ops fops = { 
+2              proc_read: device_read, 
+3              proc_write: device_write, 
+4              proc_open: device_open, 
+5              proc_release: device_release 
+6};
+ + + +

However, there is also a C99 way of assigning to elements of a structure, +designated initializers, and this is definitely preferred over using the GNU extension. +You should use this syntax in case someone wants to port your driver. It will help +with compatibility: +

+

+
1struct proc_ops fops = { 
+2              .proc_read = device_read, 
+3              .proc_write = device_write, 
+4              .proc_open = device_open, 
+5              .proc_release = device_release 
+6};
+

The meaning is clear, and you should be aware that any member of the +structure which you do not explicitly assign will be initialized to NULL by +gcc. +

An instance of struct proc_ops containing pointers to functions that are used to +implement read, write, open, … syscalls is commonly named fops. +

+

+

0.6.2 The file structure

+

Each device is represented in the kernel by a file structure, which is defined in +linux/fs.h. Be aware that a file is a kernel level structure and never appears in a +user space program. It is not the same thing as a FILE, which is defined by glibc and +would never appear in a kernel space function. Also, its name is a bit misleading; it +represents an abstract open ‘file’, not a file on a disk, which is represented by a +structure named inode. +

An instance of struct file is commonly named filp. You’ll also see it refered to as +struct file file. Resist the temptation. +

Go ahead and look at the definition of file. Most of the entries you see, like struct +dentry are not used by device drivers, and you can ignore them. This is because +drivers do not fill file directly; they only use structures contained in file which are +created elsewhere. +

+

+

0.6.3 Registering A Device

+

As discussed earlier, char devices are accessed through device files, usually located in +/dev. This is by convention. When writing a driver, it is OK to put the +device file in your current directory. Just make sure you place it in /dev for a +production driver. The major number tells you which driver handles which +device file. The minor number is used only by the driver itself to differentiate +which device it is operating on, just in case the driver handles more than one +device. +

Adding a driver to your system means registering it with the kernel. +This is synonymous with assigning it a major number during the module’s +initialization. You do this by using the register_chrdev function, defined by + + + +linux/fs.h. +

+

+
1int register_chrdev(unsigned int major, const char *name, struct proc_ops *fops);
+

where unsigned int major is the major number you want to request, const char +*name is the name of the device as it will appear in /proc/devices and struct +proc_ops *fops is a pointer to the proc_ops table for your driver. A negative return +value means the registration failed. Note that we didn’t pass the minor number to +register_chrdev. That is because the kernel doesn’t care about the minor number; +only our driver uses it. +

Now the question is, how do you get a major number without hijacking one that’s +already in use? The easiest way would be to look through Documentation +/devices.txt and pick an unused one. That is a bad way of doing things +because you will never be sure if the number you picked will be assigned later. +The answer is that you can ask the kernel to assign you a dynamic major +number. +

If you pass a major number of 0 to register_chrdev, the return value will be the +dynamically allocated major number. The downside is that you ca not make a device +file in advance, since you don’t know what the major number will be. There are a +couple of ways to do this. First, the driver itself can print the newly assigned number +and we can make the device file by hand. Second, the newly registered device will +have an entry in /proc/devices, and we can either make the device file by hand or +write a shell script to read the file in and make the device file. The third method is +we can have our driver make the the device file using the device_create +function after a successful registration and device_destroy during the call to +cleanup_module. +

+

+

0.6.4 Unregistering A Device

+

We can not allow the kernel module to be rmmod’ed whenever root feels like it. If the +device file is opened by a process and then we remove the kernel module, using the +file would cause a call to the memory location where the appropriate function +(read/write) used to be. If we are lucky, no other code was loaded there, and we’ll get +an ugly error message. If we are unlucky, another kernel module was loaded into the +same location, which means a jump into the middle of another function within the +kernel. The results of this would be impossible to predict, but they can not be very +positive. +

Normally, when you don’t want to allow something, you return an error code +(a negative number) from the function which is supposed to do it. With +cleanup_module that’s impossible because it is a void function. However, there is a +counter which keeps track of how many processes are using your module. You can see +what its value is by looking at the 3rd field of /proc/modules. If this number isn’t +zero, rmmod will fail. Note that you don’t have to check the counter from within + + + +cleanup_module because the check will be performed for you by the system call +sys_delete_module, defined in linux/module.c. You should not use this counter +directly, but there are functions defined in linux/module.h which let you increase, +decrease and display this counter: +

+ +

It is important to keep the counter accurate; if you ever do lose track of the +correct usage count, you will never be able to unload the module; it’s now reboot +time, boys and girls. This is bound to happen to you sooner or later during a +module’s development. +

+

+

0.6.5 chardev.c

+

The next code sample creates a char driver named chardev. You can cat its device +file. +

+

+
1cat /proc/devices
+

(or open the file with a program) and the driver will put the number of times the +device file has been read from into the file. We do not support writing to the file +(like echo "hi" > /dev/hello), but catch these attempts and tell the user +that the operation is not supported. Don’t worry if you don’t see what we +do with the data we read into the buffer; we don’t do much with it. We +simply read in the data and print a message acknowledging that we received +it. +

+

+
1/* 
+2 *  chardev.c: Creates a read-only char device that says how many times 
+3 *  you've read from the dev file 
+4 */ 
+5 
+6#include <linux/cdev.h> 
+7#include <linux/delay.h> 
+8#include <linux/device.h> 
+9#include <linux/fs.h> 
+10#include <linux/init.h> 
+11#include <linux/irq.h> 
+12#include <linux/kernel.h> 
+13#include <linux/module.h> 
+14#include <linux/poll.h> 
+15 
+16/* 
+17 *  Prototypes - this would normally go in a .h file 
+18 */ 
+19int init_module(void); 
+20void cleanup_module(void); 
+21static int device_open(struct inode *, struct file *); 
+22static int device_release(struct inode *, struct file *); 
+23static ssize_t device_read(struct file *, char *, size_t, loff_t *); 
+24static ssize_t device_write(struct file *, const char *, size_t, loff_t *); 
+25 
+26#define SUCCESS 0 
+27#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices   */ 
+28#define BUF_LEN 80            /* Max length of the message from the device */ 
+29 
+30/* 
+31 * Global variables are declared as static, so are global within the file. 
+32 */ 
+33 
+34static int Major;           /* Major number assigned to our device driver */ 
+35static int Device_Open = 0; /* Is device open? 
+36                             * Used to prevent multiple access to device */ 
+37static char msg[BUF_LEN];   /* The msg the device will give when asked */ 
+38static char *msg_Ptr; 
+39 
+40static struct class *cls; 
+41 
+42static struct file_operations chardev_fops = {.read = device_read, 
+43                                              .write = device_write, 
+44                                              .open = device_open, 
+45                                              .release = device_release}; 
+46 
+47/* 
+48 * This function is called when the module is loaded 
+49 */ 
+50int init_module(void) 
+51{ 
+52    Major = register_chrdev(0, DEVICE_NAME, &chardev_fops); 
+53 
+54    if (Major < 0) { 
+55        pr_alert("Registering char device failed with %d\n", Major); 
+56        return Major; 
+57    } 
+58 
+59    pr_info("I was assigned major number %d.\n", Major); 
+60 
+61    cls = class_create(THIS_MODULE, DEVICE_NAME); 
+62    device_create(cls, NULL, MKDEV(Major, 0), NULL, DEVICE_NAME); 
+63 
+64    pr_info("Device created on /dev/%s\n", DEVICE_NAME); 
+65 
+66    return SUCCESS; 
+67} 
+68 
+69/* 
+70 * This function is called when the module is unloaded 
+71 */ 
+72void cleanup_module(void) 
+73{ 
+74    device_destroy(cls, MKDEV(Major, 0)); 
+75    class_destroy(cls); 
+76 
+77    /* 
+78     * Unregister the device 
+79     */ 
+80    unregister_chrdev(Major, DEVICE_NAME); 
+81} 
+82 
+83/* 
+84 * Methods 
+85 */ 
+86 
+87/* 
+88 * Called when a process tries to open the device file, like 
+89 * "sudo cat /dev/chardev" 
+90 */ 
+91static int device_open(struct inode *inode, struct file *file) 
+92{ 
+93    static int counter = 0; 
+94 
+95    if (Device_Open) 
+96        return -EBUSY; 
+97 
+98    Device_Open++; 
+99    sprintf(msg, "I already told you %d times Hello world!\n", counter++); 
+100    msg_Ptr = msg; 
+101    try_module_get(THIS_MODULE); 
+102 
+103    return SUCCESS; 
+104} 
+105 
+106/* 
+107 * Called when a process closes the device file. 
+108 */ 
+109static int device_release(struct inode *inode, struct file *file) 
+110{ 
+111    Device_Open--; /* We're now ready for our next caller */ 
+112 
+113    /* 
+114     * Decrement the usage count, or else once you opened the file, you'll 
+115     * never get get rid of the module. 
+116     */ 
+117    module_put(THIS_MODULE); 
+118 
+119    return SUCCESS; 
+120} 
+121 
+122/* 
+123 * Called when a process, which already opened the dev file, attempts to 
+124 * read from it. 
+125 */ 
+126static ssize_t device_read(struct file *filp, /* see include/linux/fs.h   */ 
+127                           char *buffer,      /* buffer to fill with data */ 
+128                           size_t length,     /* length of the buffer     */ 
+129                           loff_t *offset) 
+130{ 
+131    /* 
+132     * Number of bytes actually written to the buffer 
+133     */ 
+134    int bytes_read = 0; 
+135 
+136    /* 
+137     * If we're at the end of the message, 
+138     * return 0 signifying end of file 
+139     */ 
+140    if (*msg_Ptr == 0) 
+141        return 0; 
+142 
+143    /* 
+144     * Actually put the data into the buffer 
+145     */ 
+146    while (length && *msg_Ptr) { 
+147        /* 
+148         * The buffer is in the user data segment, not the kernel 
+149         * segment so "*" assignment won't work.  We have to use 
+150         * put_user which copies data from the kernel data segment to 
+151         * the user data segment. 
+152         */ 
+153        put_user(*(msg_Ptr++), buffer++); 
+154 
+155        length--; 
+156        bytes_read++; 
+157    } 
+158 
+159    /* 
+160     * Most read functions return the number of bytes put into the buffer 
+161     */ 
+162    return bytes_read; 
+163} 
+164 
+165/* 
+166 * Called when a process writes to dev file: echo "hi" > /dev/hello 
+167 */ 
+168static ssize_t device_write(struct file *filp, 
+169                            const char *buff, 
+170                            size_t len, 
+171                            loff_t *off) 
+172{ 
+173    pr_alert("Sorry, this operation isn't supported.\n"); 
+174    return -EINVAL; 
+175} 
+176 
+177MODULE_LICENSE("GPL");
+ + + +

+

+

0.6.6 Writing Modules for Multiple Kernel Versions

+

The system calls, which are the major interface the kernel shows to the processes, +generally stay the same across versions. A new system call may be added, but +usually the old ones will behave exactly like they used to. This is necessary for +backward compatibility – a new kernel version is not supposed to break regular +processes. In most cases, the device files will also remain the same. On the other +hand, the internal interfaces within the kernel can and do change between +versions. +

There are differences between different kernel versions, and if you want to support +multiple kernel versions, you will find yourself having to code conditional compilation +directives. The way to do this to compare the macro LINUX_VERSION_CODE to the +macro KERNEL_VERSION. In version a.b.c of the kernel, the value of this macro would +be 216a + 28b+ c  . +

While previous versions of this guide showed how you can write backward +compatible code with such constructs in great detail, we decided to break with this +tradition for the better. People interested in doing such might now use a LKMPG +with a version matching to their kernel. +

+

+

0.7 The /proc File System

+

In Linux, there is an additional mechanism for the kernel and kernel modules to send +information to processes — the /proc file system. Originally designed to allow easy +access to information about processes (hence the name), it is now used by every bit +of the kernel which has something interesting to report, such as /proc/modules +which provides the list of modules and /proc/meminfo which stats memory usage +statistics. +

The method to use the proc file system is very similar to the one used with device +drivers — a structure is created with all the information needed for the /proc file, +including pointers to any handler functions (in our case there is only one, the +one called when somebody attempts to read from the /proc file). Then, +init_module registers the structure with the kernel and cleanup_module unregisters +it. +

Normal file systems are located on a disk, rather than just in memory (which is +where /proc is), and in that case the inode number is a pointer to a disk +location where the file’s index-node (inode for short) is located. The inode +contains information about the file, for example the file’s permissions, together +with a pointer to the disk location or locations where the file’s data can be +found. +

Because we don’t get called when the file is opened or closed, there’s nowhere for +us to put try_module_get and try_module_put in this module, and if the +file is opened and then the module is removed, there’s no way to avoid the + + + +consequences. +

Here a simple example showing how to use a /proc file. This is the HelloWorld +for the /proc filesystem. There are three parts: create the file proc helloworld +in the function init_module, return a value (and a buffer) when the file +/proc/helloworld is read in the callback function procfile_read, and delete the +file /proc/helloworld in the function cleanup_module. +

The /proc/helloworld is created when the module is loaded with the function +proc_create. The return value is a struct proc_dir_entry , and it will be used +to configure the file /proc/helloworld (for example, the owner of this file). A null +return value means that the creation has failed. +

Each time, everytime the file /proc/helloworld is read, the function +procfile_read is called. Two parameters of this function are very important: the +buffer (the first parameter) and the offset (the third one). The content of the +buffer will be returned to the application which read it (for example the +cat command). The offset is the current position in the file. If the return +value of the function is not null, then this function is called again. So be +careful with this function, if it never returns zero, the read function is called +endlessly. + + + +

+
+$ cat /proc/helloworld
+HelloWorld!
+
+

+

+

+
1/* 
+2 *  procfs1.c 
+3 */ 
+4 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/proc_fs.h> 
+8#include <linux/uaccess.h> 
+9#include <linux/version.h> 
+10 
+11#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+12#define HAVE_PROC_OPS 
+13#endif 
+14 
+15#define procfs_name "helloworld" 
+16 
+17struct proc_dir_entry *Our_Proc_File; 
+18 
+19 
+20ssize_t procfile_read(struct file *filePointer, 
+21                      char *buffer, 
+22                      size_t buffer_length, 
+23                      loff_t *offset) 
+24{ 
+25    char s[13] = "HelloWorld!\n"; 
+26    int len = sizeof(s); 
+27    ssize_t ret = len; 
+28 
+29    if (*offset >= len || copy_to_user(buffer, s, len)) { 
+30                  pr_info("copy_to_user failed\n"); 
+31                  ret = 0; 
+32    } 
+33    else { 
+34        pr_info("procfile read %s\n", filePointer->f_path.dentry->d_name.name); 
+35        *offset += len; 
+36    } 
+37 
+38    return ret; 
+39} 
+40 
+41#ifdef HAVE_PROC_OPS 
+42static const struct proc_ops proc_file_fops = { 
+43    .proc_read = procfile_read, 
+44}; 
+45#else 
+46static const struct file_operations proc_file_fops = { 
+47    .read = procfile_read, 
+48}; 
+49#endif 
+50 
+51int init_module() 
+52{ 
+53    Our_Proc_File = proc_create(procfs_name, 0644, NULL, &proc_file_fops); 
+54    if (NULL == Our_Proc_File) { 
+55        proc_remove(Our_Proc_File); 
+56        pr_alert("Error:Could not initialize /proc/%s\n", procfs_name); 
+57        return -ENOMEM; 
+58    } 
+59 
+60    pr_info("/proc/%s created\n", procfs_name); 
+61    return 0; 
+62} 
+63 
+64void cleanup_module() 
+65{ 
+66    proc_remove(Our_Proc_File); 
+67    pr_info("/proc/%s removed\n", procfs_name); 
+68} 
+69 
+70MODULE_LICENSE("GPL");
+

+

+

0.7.1 Read and Write a /proc File

+

We have seen a very simple example for a /proc file where we only read the +file /proc/helloworld. It is also possible to write in a /proc file. It works +the same way as read, a function is called when the /proc file is written. +But there is a little difference with read, data comes from user, so you have +to import data from user space to kernel space (with copy_from_user or +get_user) +

The reason for copy_from_user or get_user is that Linux memory (on Intel +architecture, it may be different under some other processors) is segmented. This +means that a pointer, by itself, does not reference a unique location in memory, only +a location in a memory segment, and you need to know which memory segment it is +to be able to use it. There is one memory segment for the kernel, and one for each of +the processes. +

The only memory segment accessible to a process is its own, so when +writing regular programs to run as processes, there is no need to worry about +segments. When you write a kernel module, normally you want to access +the kernel memory segment, which is handled automatically by the system. +However, when the content of a memory buffer needs to be passed between +the currently running process and the kernel, the kernel function receives a +pointer to the memory buffer which is in the process segment. The put_user +and get_user macros allow you to access that memory. These functions +handle only one caracter, you can handle several caracters with copy_to_user +and copy_from_user. As the buffer (in read or write function) is in kernel +space, for write function you need to import data because it comes from +user space, but not for the read function because data is already in kernel +space. +

+

+
1/* 
+2 *  procfs2.c -  create a "file" in /proc 
+3 */ 
+4 
+5#include <linux/kernel.h>  /* We're doing kernel work */ 
+6#include <linux/module.h>  /* Specifically, a module */ 
+7#include <linux/proc_fs.h> /* Necessary because we use the proc fs */ 
+8#include <linux/uaccess.h> /* for copy_from_user */ 
+9#include <linux/version.h> 
+10 
+11#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+12#define HAVE_PROC_OPS 
+13#endif 
+14 
+15#define PROCFS_MAX_SIZE 1024 
+16#define PROCFS_NAME "buffer1k" 
+17 
+18/** 
+19 * This structure hold information about the /proc file 
+20 * 
+21 */ 
+22static struct proc_dir_entry *Our_Proc_File; 
+23 
+24/** 
+25 * The buffer used to store character for this module 
+26 * 
+27 */ 
+28static char procfs_buffer[PROCFS_MAX_SIZE]; 
+29 
+30/** 
+31 * The size of the buffer 
+32 * 
+33 */ 
+34static unsigned long procfs_buffer_size = 0; 
+35 
+36/** 
+37 * This function is called then the /proc file is read 
+38 * 
+39 */ 
+40ssize_t procfile_read(struct file *filePointer, 
+41                      char *buffer, 
+42                      size_t buffer_length, 
+43                      loff_t *offset) 
+44{ 
+45    char s[13] = "HelloWorld!\n"; 
+46    int len = sizeof(s); 
+47    ssize_t ret = len; 
+48 
+49    if (*offset >= len || copy_to_user(buffer, s, len)) { 
+50                  pr_info("copy_to_user failed\n"); 
+51                  ret = 0; 
+52    } 
+53    else { 
+54        pr_info("procfile read %s\n", filePointer->f_path.dentry->d_name.name); 
+55        *offset += len; 
+56    } 
+57 
+58    return ret; 
+59} 
+60 
+61 
+62/** 
+63 * This function is called with the /proc file is written 
+64 * 
+65 */ 
+66static ssize_t procfile_write(struct file *file, 
+67                              const char *buff, 
+68                              size_t len, 
+69                              loff_t *off) 
+70{ 
+71    procfs_buffer_size = len; 
+72    if (procfs_buffer_size > PROCFS_MAX_SIZE) 
+73        procfs_buffer_size = PROCFS_MAX_SIZE; 
+74 
+75    if (copy_from_user(procfs_buffer, buff, procfs_buffer_size)) 
+76        return -EFAULT; 
+77 
+78    procfs_buffer[procfs_buffer_size] = '\0'; 
+79    return procfs_buffer_size; 
+80} 
+81 
+82#ifdef HAVE_PROC_OPS 
+83static const struct proc_ops proc_file_fops = { 
+84    .proc_read = procfile_read, 
+85    .proc_write = procfile_write, 
+86}; 
+87#else 
+88static const struct file_operations proc_file_fops = { 
+89    .read = procfile_read, 
+90    .write = procfile_write, 
+91}; 
+92#endif 
+93 
+94/** 
+95 *This function is called when the module is loaded 
+96 * 
+97 */ 
+98int init_module() 
+99{ 
+100    Our_Proc_File = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_fops); 
+101    if (NULL == Our_Proc_File) { 
+102        proc_remove(Our_Proc_File); 
+103        pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME); 
+104        return -ENOMEM; 
+105    } 
+106 
+107    pr_info("/proc/%s created\n", PROCFS_NAME); 
+108    return 0; 
+109} 
+110 
+111/** 
+112 *This function is called when the module is unloaded 
+113 * 
+114 */ 
+115void cleanup_module() 
+116{ 
+117    proc_remove(Our_Proc_File); 
+118    pr_info("/proc/%s removed\n", PROCFS_NAME); 
+119} 
+120 
+121MODULE_LICENSE("GPL");
+ + + +

+

+

0.7.2 Manage /proc file with standard filesystem

+

We have seen how to read and write a /proc file with the /proc interface. But it is +also possible to manage /proc file with inodes. The main concern is to use advanced +functions, like permissions. +

In Linux, there is a standard mechanism for file system registration. Since every +file system has to have its own functions to handle inode and file operations, there is +a special structure to hold pointers to all those functions, struct inode_operations, +which includes a pointer to struct proc_ops. +

The difference between file and inode operations is that file operations deal with +the file itself whereas inode operations deal with ways of referencing the file, such as +creating links to it. +

In /proc, whenever we register a new file, we’re allowed to specify which struct +inode_operations will be used to access to it. This is the mechanism we use, a struct +inode_operations which includes a pointer to a struct proc_ops which includes +pointers to our procfs_read and procfs_write functions. +

Another interesting point here is the module_permission function. This function +is called whenever a process tries to do something with the /proc file, and it +can decide whether to allow access or not. Right now it is only based on +the operation and the uid of the current user (as available in current, a +pointer to a structure which includes information on the currently running +process), but it could be based on anything we like, such as what other +processes are doing with the same file, the time of day, or the last input we +received. +

It is important to note that the standard roles of read and write are reversed in +the kernel. Read functions are used for output, whereas write functions are used for +input. The reason for that is that read and write refer to the user’s point of view — if +a process reads something from the kernel, then the kernel needs to output it, and +if a process writes something to the kernel, then the kernel receives it as +input. +

+

+
1/* 
+2 *  procfs3.c 
+3 */ 
+4 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/proc_fs.h> 
+8#include <linux/sched.h> 
+9#include <linux/uaccess.h> 
+10#include <linux/version.h> 
+11 
+12#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+13#define HAVE_PROC_OPS 
+14#endif 
+15 
+16#define PROCFS_MAX_SIZE 2048 
+17#define PROCFS_ENTRY_FILENAME "buffer2k" 
+18 
+19struct proc_dir_entry *Our_Proc_File; 
+20static char procfs_buffer[PROCFS_MAX_SIZE]; 
+21static unsigned long procfs_buffer_size = 0; 
+22 
+23static ssize_t procfs_read(struct file *filp, 
+24                           char *buffer, 
+25                           size_t length, 
+26                           loff_t *offset) 
+27{ 
+28    static int finished = 0; 
+29    if (finished) { 
+30        pr_debug("procfs_read: END\n"); 
+31        finished = 0; 
+32        return 0; 
+33    } 
+34    finished = 1; 
+35    if (copy_to_user(buffer, procfs_buffer, procfs_buffer_size)) 
+36        return -EFAULT; 
+37    pr_debug("procfs_read: read %lu bytes\n", procfs_buffer_size); 
+38    return procfs_buffer_size; 
+39} 
+40static ssize_t procfs_write(struct file *file, 
+41                            const char *buffer, 
+42                            size_t len, 
+43                            loff_t *off) 
+44{ 
+45    if (len > PROCFS_MAX_SIZE) 
+46        procfs_buffer_size = PROCFS_MAX_SIZE; 
+47    else 
+48        procfs_buffer_size = len; 
+49    if (copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) 
+50        return -EFAULT; 
+51    pr_debug("procfs_write: write %lu bytes\n", procfs_buffer_size); 
+52    return procfs_buffer_size; 
+53} 
+54int procfs_open(struct inode *inode, struct file *file) 
+55{ 
+56    try_module_get(THIS_MODULE); 
+57    return 0; 
+58} 
+59int procfs_close(struct inode *inode, struct file *file) 
+60{ 
+61    module_put(THIS_MODULE); 
+62    return 0; 
+63} 
+64 
+65#ifdef HAVE_PROC_OPS 
+66static struct proc_ops File_Ops_4_Our_Proc_File = { 
+67    .proc_read = procfs_read, 
+68    .proc_write = procfs_write, 
+69    .proc_open = procfs_open, 
+70    .proc_release = procfs_close, 
+71}; 
+72#else 
+73static const struct file_operations File_Ops_4_Our_Proc_File = { 
+74    .read = procfs_read, 
+75    .write = procfs_write, 
+76    .open = procfs_open, 
+77    .release = procfs_close, 
+78}; 
+79#endif 
+80 
+81int init_module() 
+82{ 
+83    Our_Proc_File = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL, 
+84                                &File_Ops_4_Our_Proc_File); 
+85    if (Our_Proc_File == NULL) { 
+86        remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); 
+87        pr_debug("Error: Could not initialize /proc/%s\n", 
+88                 PROCFS_ENTRY_FILENAME); 
+89        return -ENOMEM; 
+90    } 
+91    proc_set_size(Our_Proc_File, 80); 
+92    proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); 
+93 
+94    pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME); 
+95    return 0; 
+96} 
+97void cleanup_module() 
+98{ 
+99    remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); 
+100    pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME); 
+101} 
+102 
+103MODULE_LICENSE("GPL");
+

Still hungry for procfs examples? Well, first of all keep in mind, there are rumors +around, claiming that procfs is on its way out, consider using sysfs instead. Consider +using this mechanism, in case you want to document something kernel related +yourself. +

+

+

0.7.3 Manage /proc file with seq_file

+

As we have seen, writing a /proc file may be quite “complex”. So to help people +writting /proc file, there is an API named seq_file that helps formating a /proc file + + + +for output. It is based on sequence, which is composed of 3 functions: start(), next(), +and stop(). The seq_file API starts a sequence when a user read the /proc +file. +

A sequence begins with the call of the function start(). If the return is a non +NULL value, the function next() is called. This function is an iterator, the goal is to +go thought all the data. Each time next() is called, the function show() is also called. +It writes data values in the buffer read by the user. The function next() is called until +it returns NULL. The sequence ends when next() returns NULL, then the function +stop() is called. +

BE CAREFUL: when a sequence is finished, another one starts. That means that +at the end of function stop(), the function start() is called again. This loop finishes +when the function start() returns NULL. You can see a scheme of this in the +Figure 1. +

+
+ + + + + + + + +

srYrsNNYtaeenetoooertusetupstrxr((ntn))( tis)istrr teeaNreNatUaUtmLtLmeLmLen?e?ntntt  +

+
Figure 1:How seq_file works
+ + + +
+

The seq_file provides basic functions for proc_ops, such as seq_read, +seq_lseek, and some others. But nothing to write in the /proc file. Of course, you can +still use the same way as in the previous example. +

+
1/* 
+2 *  procfs4.c -  create a "file" in /proc 
+3 *  This program uses the seq_file library to manage the /proc file. 
+4 * 
+5 */ 
+6 
+7#include <linux/kernel.h>   /* We're doing kernel work */ 
+8#include <linux/module.h>   /* Specifically, a module */ 
+9#include <linux/proc_fs.h>  /* Necessary because we use proc fs */ 
+10#include <linux/seq_file.h> /* for seq_file */ 
+11#include <linux/version.h> 
+12 
+13#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+14#define HAVE_PROC_OPS 
+15#endif 
+16 
+17#define PROC_NAME "iter" 
+18 
+19MODULE_LICENSE("GPL"); 
+20 
+21/** 
+22 * This function is called at the beginning of a sequence. 
+23 * ie, when: 
+24 *      - the /proc file is read (first time) 
+25 *      - after the function stop (end of sequence) 
+26 * 
+27 */ 
+28static void *my_seq_start(struct seq_file *s, loff_t *pos) 
+29{ 
+30    static unsigned long counter = 0; 
+31 
+32    /* beginning a new sequence ? */ 
+33    if (*pos == 0) { 
+34        /* yes => return a non null value to begin the sequence */ 
+35        return &counter; 
+36    } else { 
+37        /* no => it's the end of the sequence, return end to stop reading */ 
+38        *pos = 0; 
+39        return NULL; 
+40    } 
+41} 
+42 
+43/** 
+44 * This function is called after the beginning of a sequence. 
+45 * It's called untill the return is NULL (this ends the sequence). 
+46 * 
+47 */ 
+48static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos) 
+49{ 
+50    unsigned long *tmp_v = (unsigned long *) v; 
+51    (*tmp_v)++; 
+52    (*pos)++; 
+53    return NULL; 
+54} 
+55 
+56/** 
+57 * This function is called at the end of a sequence 
+58 * 
+59 */ 
+60static void my_seq_stop(struct seq_file *s, void *v) 
+61{ 
+62    /* nothing to do, we use a static value in start() */ 
+63} 
+64 
+65/** 
+66 * This function is called for each "step" of a sequence 
+67 * 
+68 */ 
+69static int my_seq_show(struct seq_file *s, void *v) 
+70{ 
+71    loff_t *spos = (loff_t *) v; 
+72 
+73    seq_printf(s, "%Ld\n", *spos); 
+74    return 0; 
+75} 
+76 
+77/** 
+78 * This structure gather "function" to manage the sequence 
+79 * 
+80 */ 
+81static struct seq_operations my_seq_ops = {.start = my_seq_start, 
+82                                           .next = my_seq_next, 
+83                                           .stop = my_seq_stop, 
+84                                           .show = my_seq_show}; 
+85 
+86/** 
+87 * This function is called when the /proc file is open. 
+88 * 
+89 */ 
+90static int my_open(struct inode *inode, struct file *file) 
+91{ 
+92    return seq_open(file, &my_seq_ops); 
+93}; 
+94 
+95/** 
+96 * This structure gather "function" that manage the /proc file 
+97 * 
+98 */ 
+99#ifdef HAVE_PROC_OPS 
+100static const struct proc_ops my_file_ops = { 
+101    .proc_open = my_open, 
+102    .proc_read = seq_read, 
+103    .proc_lseek = seq_lseek, 
+104    .proc_release = seq_release, 
+105}; 
+106#else 
+107static const struct file_operations my_file_ops = { 
+108    .open = my_open, 
+109    .read = seq_read, 
+110    .llseek = seq_lseek, 
+111    .release = seq_release, 
+112}; 
+113#endif 
+114 
+115/** 
+116 * This function is called when the module is loaded 
+117 * 
+118 */ 
+119int init_module(void) 
+120{ 
+121    struct proc_dir_entry *entry; 
+122 
+123    entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops); 
+124    if (entry == NULL) { 
+125        remove_proc_entry(PROC_NAME, NULL); 
+126        pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME); 
+127        return -ENOMEM; 
+128    } 
+129 
+130    return 0; 
+131} 
+132 
+133/** 
+134 * This function is called when the module is unloaded. 
+135 * 
+136 */ 
+137void cleanup_module(void) 
+138{ 
+139    remove_proc_entry(PROC_NAME, NULL); 
+140    pr_debug("/proc/%s removed\n", PROC_NAME); 
+141}
+

If you want more information, you can read this web page: +

+ +

You can also read the code of fs/seq_file.c in the linux kernel. +

+

0.8 sysfs: Interacting with your module

+

sysfs allows you to interact with the running kernel from userspace by reading or +setting variables inside of modules. This can be useful for debugging purposes, or just +as an interface for applications or scripts. You can find sysfs directories and files +under the sys directory on your system. +

+

+
1ls -l /sys
+

An example of a hello world module which includes the creation of a variable +accessible via sysfs is given below. +

+

+
1/* 
+2 *  hello-sysfs.c sysfs example 
+3 */ 
+4#include <linux/fs.h> 
+5#include <linux/init.h> 
+6#include <linux/kobject.h> 
+7#include <linux/module.h> 
+8#include <linux/string.h> 
+9#include <linux/sysfs.h> 
+10 
+11MODULE_LICENSE("GPL"); 
+12 
+13static struct kobject *mymodule; 
+14 
+15/* the variable you want to be able to change */ 
+16static int myvariable = 0; 
+17 
+18static ssize_t myvariable_show(struct kobject *kobj, 
+19                               struct kobj_attribute *attr, 
+20                               char *buf) 
+21{ 
+22    return sprintf(buf, "%d\n", myvariable); 
+23} 
+24 
+25static ssize_t myvariable_store(struct kobject *kobj, 
+26                                struct kobj_attribute *attr, 
+27                                char *buf, 
+28                                size_t count) 
+29{ 
+30    sscanf(buf, "%du", &myvariable); 
+31    return count; 
+32} 
+33 
+34 
+35static struct kobj_attribute myvariable_attribute = 
+36    __ATTR(myvariable, 0660, myvariable_show, (void *) myvariable_store); 
+37 
+38static int __init mymodule_init(void) 
+39{ 
+40    int error = 0; 
+41 
+42    pr_info("mymodule: initialised\n"); 
+43 
+44    mymodule = kobject_create_and_add("mymodule", kernel_kobj); 
+45    if (!mymodule) 
+46        return -ENOMEM; 
+47 
+48    error = sysfs_create_file(mymodule, &myvariable_attribute.attr); 
+49    if (error) { 
+50        pr_info( 
+51            "failed to create the myvariable file " 
+52            "in /sys/kernel/mymodule\n"); 
+53    } 
+54 
+55    return error; 
+56} 
+57 
+58static void __exit mymodule_exit(void) 
+59{ 
+60    pr_info("mymodule: Exit success\n"); 
+61    kobject_put(mymodule); 
+62} 
+63 
+64module_init(mymodule_init); 
+65module_exit(mymodule_exit);
+

Make and install the module: +

+

+
1make 
+2sudo insmod hello-sysfs.ko
+

Check that it exists: +

+ + + +

+
1sudo lsmod | grep hello_sysfs
+

What is the current value of myvariable ? +

+

+
1cat /sys/kernel/mymodule/myvariable
+

Set the value of myvariable and check that it changed. +

+

+
1echo "32" > /sys/kernel/mymodule/myvariable 
+2cat /sys/kernel/mymodule/myvariable
+

Finally, remove the test module: +

+

+
1sudo rmmod hello_sysfs
+

+

+

0.9 Talking To Device Files

+

Device files are supposed to represent physical devices. Most physical devices are +used for output as well as input, so there has to be some mechanism for +device drivers in the kernel to get the output to send to the device from +processes. This is done by opening the device file for output and writing to it, +just like writing to a file. In the following example, this is implemented by +device_write. +

This is not always enough. Imagine you had a serial port connected to a modem +(even if you have an internal modem, it is still implemented from the CPU’s +perspective as a serial port connected to a modem, so you don’t have to tax +your imagination too hard). The natural thing to do would be to use the +device file to write things to the modem (either modem commands or data to +be sent through the phone line) and read things from the modem (either +responses for commands or the data received through the phone line). However, +this leaves open the question of what to do when you need to talk to the +serial port itself, for example to send the rate at which data is sent and +received. +

The answer in Unix is to use a special function called ioctl (short for +Input Output ConTroL). Every device can have its own ioctl commands, +which can be read ioctl’s (to send information from a process to the kernel), +write ioctl’s (to return information to a process), both or neither. Notice + + + +here the roles of read and write are reversed again, so in ioctl’s read is to +send information to the kernel and write is to receive information from the +kernel. +

The ioctl function is called with three parameters: the file descriptor of the +appropriate device file, the ioctl number, and a parameter, which is of type +long so you can use a cast to use it to pass anything. You will not be able +to pass a structure this way, but you will be able to pass a pointer to the +structure. +

The ioctl number encodes the major device number, the type of the ioctl, the +command, and the type of the parameter. This ioctl number is usually created by a +macro call (_IO, _IOR, _IOW or _IOWR — depending on the type) in a header +file. This header file should then be included both by the programs which will use +ioctl (so they can generate the appropriate ioctl’s) and by the kernel module (so it +can understand it). In the example below, the header file is chardev.h and the +program which uses it is ioctl.c. +

If you want to use ioctls in your own kernel modules, it is best to receive an +official ioctl assignment, so if you accidentally get somebody else’s ioctls, or if they +get yours, you’ll know something is wrong. For more information, consult the kernel +source tree at Documentation/ioctl-number.txt. +

+

+
1/* 
+2 *  chardev2.c - Create an input/output character device 
+3 */ 
+4 
+5#include <linux/cdev.h> 
+6#include <linux/delay.h> 
+7#include <linux/device.h> 
+8#include <linux/fs.h> 
+9#include <linux/init.h> 
+10#include <linux/irq.h> 
+11#include <linux/kernel.h> /* We're doing kernel work */ 
+12#include <linux/module.h> /* Specifically, a module */ 
+13#include <linux/poll.h> 
+14 
+15#include "chardev.h" 
+16#define SUCCESS 0 
+17#define DEVICE_NAME "char_dev" 
+18#define BUF_LEN 80 
+19 
+20/* 
+21 * Is the device open right now? Used to prevent 
+22 * concurent access into the same device 
+23 */ 
+24static int Device_Open = 0; 
+25 
+26/* 
+27 * The message the device will give when asked 
+28 */ 
+29static char Message[BUF_LEN]; 
+30 
+31/* 
+32 * How far did the process reading the message get? 
+33 * Useful if the message is larger than the size of the 
+34 * buffer we get to fill in device_read. 
+35 */ 
+36static char *Message_Ptr; 
+37 
+38static int Major; /* Major number assigned to our device driver */ 
+39static struct class *cls; 
+40 
+41/* 
+42 * This is called whenever a process attempts to open the device file 
+43 */ 
+44static int device_open(struct inode *inode, struct file *file) 
+45{ 
+46    pr_info("device_open(%p)\n", file); 
+47 
+48    /* 
+49     * We don't want to talk to two processes at the same time 
+50     */ 
+51    if (Device_Open) 
+52        return -EBUSY; 
+53 
+54    Device_Open++; 
+55    /* 
+56     * Initialize the message 
+57     */ 
+58    Message_Ptr = Message; 
+59    try_module_get(THIS_MODULE); 
+60    return SUCCESS; 
+61} 
+62 
+63static int device_release(struct inode *inode, struct file *file) 
+64{ 
+65    pr_info("device_release(%p,%p)\n", inode, file); 
+66 
+67    /* 
+68     * We're now ready for our next caller 
+69     */ 
+70    Device_Open--; 
+71 
+72    module_put(THIS_MODULE); 
+73    return SUCCESS; 
+74} 
+75 
+76/* 
+77 * This function is called whenever a process which has already opened the 
+78 * device file attempts to read from it. 
+79 */ 
+80static ssize_t device_read(struct file *file,   /* see include/linux/fs.h   */ 
+81                           char __user *buffer, /* buffer to be 
+82                                                 * filled with data */ 
+83                           size_t length,       /* length of the buffer     */ 
+84                           loff_t *offset) 
+85{ 
+86    /* 
+87     * Number of bytes actually written to the buffer 
+88     */ 
+89    int bytes_read = 0; 
+90 
+91    pr_info("device_read(%p,%p,%ld)\n", file, buffer, length); 
+92 
+93    /* 
+94     * If we're at the end of the message, return 0 
+95     * (which signifies end of file) 
+96     */ 
+97    if (*Message_Ptr == 0) 
+98        return 0; 
+99 
+100    /* 
+101     * Actually put the data into the buffer 
+102     */ 
+103    while (length && *Message_Ptr) { 
+104        /* 
+105         * Because the buffer is in the user data segment, 
+106         * not the kernel data segment, assignment wouldn't 
+107         * work. Instead, we have to use put_user which 
+108         * copies data from the kernel data segment to the 
+109         * user data segment. 
+110         */ 
+111        put_user(*(Message_Ptr++), buffer++); 
+112        length--; 
+113        bytes_read++; 
+114    } 
+115 
+116    pr_info("Read %d bytes, %ld left\n", bytes_read, length); 
+117 
+118    /* 
+119     * Read functions are supposed to return the number 
+120     * of bytes actually inserted into the buffer 
+121     */ 
+122    return bytes_read; 
+123} 
+124 
+125/* 
+126 * This function is called when somebody tries to 
+127 * write into our device file. 
+128 */ 
+129static ssize_t device_write(struct file *file, 
+130                            const char __user *buffer, 
+131                            size_t length, 
+132                            loff_t *offset) 
+133{ 
+134    int i; 
+135 
+136    pr_info("device_write(%p,%s,%ld)", file, buffer, length); 
+137 
+138    for (i = 0; i < length && i < BUF_LEN; i++) 
+139        get_user(Message[i], buffer + i); 
+140 
+141    Message_Ptr = Message; 
+142 
+143    /* 
+144     * Again, return the number of input characters used 
+145     */ 
+146    return i; 
+147} 
+148 
+149/* 
+150 * This function is called whenever a process tries to do an ioctl on our 
+151 * device file. We get two extra parameters (additional to the inode and file 
+152 * structures, which all device functions get): the number of the ioctl called 
+153 * and the parameter given to the ioctl function. 
+154 * 
+155 * If the ioctl is write or read/write (meaning output is returned to the 
+156 * calling process), the ioctl call returns the output of this function. 
+157 * 
+158 */ 
+159long device_ioctl(struct file *file,      /* ditto */ 
+160                  unsigned int ioctl_num, /* number and param for ioctl */ 
+161                  unsigned long ioctl_param) 
+162{ 
+163    int i; 
+164    char *temp; 
+165    char ch; 
+166 
+167    /* 
+168     * Switch according to the ioctl called 
+169     */ 
+170    switch (ioctl_num) { 
+171    case IOCTL_SET_MSG: 
+172        /* 
+173         * Receive a pointer to a message (in user space) and set that 
+174         * to be the device's message.  Get the parameter given to 
+175         * ioctl by the process. 
+176         */ 
+177        temp = (char *) ioctl_param; 
+178 
+179        /* 
+180         * Find the length of the message 
+181         */ 
+182        get_user(ch, temp); 
+183        for (i = 0; ch && i < BUF_LEN; i++, temp++) 
+184            get_user(ch, temp); 
+185 
+186        device_write(file, (char *) ioctl_param, i, 0); 
+187        break; 
+188 
+189    case IOCTL_GET_MSG: 
+190        /* 
+191         * Give the current message to the calling process - 
+192         * the parameter we got is a pointer, fill it. 
+193         */ 
+194        i = device_read(file, (char *) ioctl_param, 99, 0); 
+195 
+196        /* 
+197         * Put a zero at the end of the buffer, so it will be 
+198         * properly terminated 
+199         */ 
+200        put_user('\0', (char *) ioctl_param + i); 
+201        break; 
+202 
+203    case IOCTL_GET_NTH_BYTE: 
+204        /* 
+205         * This ioctl is both input (ioctl_param) and 
+206         * output (the return value of this function) 
+207         */ 
+208        return Message[ioctl_param]; 
+209        break; 
+210    } 
+211 
+212    return SUCCESS; 
+213} 
+214 
+215/* Module Declarations */ 
+216 
+217/* 
+218 * This structure will hold the functions to be called 
+219 * when a process does something to the device we 
+220 * created. Since a pointer to this structure is kept in 
+221 * the devices table, it can't be local to 
+222 * init_module. NULL is for unimplemented functions. 
+223 */ 
+224struct file_operations Fops = { 
+225    .read = device_read, 
+226    .write = device_write, 
+227    .unlocked_ioctl = device_ioctl, 
+228    .open = device_open, 
+229    .release = device_release, /* a.k.a. close */ 
+230}; 
+231 
+232/* 
+233 * Initialize the module - Register the character device 
+234 */ 
+235int init_module() 
+236{ 
+237    int ret_val; 
+238    /* 
+239     * Register the character device (atleast try) 
+240     */ 
+241    ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops); 
+242 
+243    /* 
+244     * Negative values signify an error 
+245     */ 
+246    if (ret_val < 0) { 
+247        pr_alert("%s failed with %d\n", 
+248                 "Sorry, registering the character device ", ret_val); 
+249        return ret_val; 
+250    } 
+251 
+252    Major = ret_val; 
+253 
+254    cls = class_create(THIS_MODULE, DEVICE_FILE_NAME); 
+255    device_create(cls, NULL, MKDEV(Major, MAJOR_NUM), NULL, DEVICE_FILE_NAME); 
+256 
+257    pr_info("Device created on /dev/%s\n", DEVICE_FILE_NAME); 
+258 
+259    return 0; 
+260} 
+261 
+262/* 
+263 * Cleanup - unregister the appropriate file from /proc 
+264 */ 
+265void cleanup_module() 
+266{ 
+267    device_destroy(cls, MKDEV(Major, 0)); 
+268    class_destroy(cls); 
+269 
+270    /* 
+271     * Unregister the device 
+272     */ 
+273    unregister_chrdev(Major, DEVICE_NAME); 
+274} 
+275 
+276MODULE_LICENSE("GPL");
+ +

+

+
1/* 
+2 *  chardev.h - the header file with the ioctl definitions. 
+3 * 
+4 *  The declarations here have to be in a header file, because 
+5 *  they need to be known both to the kernel module 
+6 *  (in chardev.c) and the process calling ioctl (ioctl.c) 
+7 */ 
+8 
+9#ifndef CHARDEV_H 
+10#define CHARDEV_H 
+11 
+12#include <linux/ioctl.h> 
+13 
+14/* 
+15 * The major device number. We can't rely on dynamic 
+16 * registration any more, because ioctls need to know 
+17 * it. 
+18 */ 
+19#define MAJOR_NUM 100 
+20 
+21/* 
+22 * Set the message of the device driver 
+23 */ 
+24#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *) 
+25/* 
+26 * _IOW means that we're creating an ioctl command 
+27 * number for passing information from a user process 
+28 * to the kernel module. 
+29 * 
+30 * The first arguments, MAJOR_NUM, is the major device 
+31 * number we're using. 
+32 * 
+33 * The second argument is the number of the command 
+34 * (there could be several with different meanings). 
+35 * 
+36 * The third argument is the type we want to get from 
+37 * the process to the kernel. 
+38 */ 
+39 
+40/* 
+41 * Get the message of the device driver 
+42 */ 
+43#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *) 
+44/* 
+45 * This IOCTL is used for output, to get the message 
+46 * of the device driver. However, we still need the 
+47 * buffer to place the message in to be input, 
+48 * as it is allocated by the process. 
+49 */ 
+50 
+51/* 
+52 * Get the n'th byte of the message 
+53 */ 
+54#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int) 
+55/* 
+56 * The IOCTL is used for both input and output. It 
+57 * receives from the user a number, n, and returns 
+58 * Message[n]. 
+59 */ 
+60 
+61/* 
+62 * The name of the device file 
+63 */ 
+64#define DEVICE_FILE_NAME "char_dev" 
+65 
+66#endif
+ +

+

+
1/* 
+2 *  ioctl.c 
+3 */ 
+4#include <linux/cdev.h> 
+5#include <linux/fs.h> 
+6#include <linux/init.h> 
+7#include <linux/ioctl.h> 
+8#include <linux/module.h> 
+9#include <linux/slab.h> 
+10#include <linux/uaccess.h> 
+11 
+12struct ioctl_arg { 
+13    unsigned int reg; 
+14    unsigned int val; 
+15}; 
+16 
+17/* Documentation/ioctl/ioctl-number.txt */ 
+18#define IOC_MAGIC '\x66' 
+19 
+20#define IOCTL_VALSET _IOW(IOC_MAGIC, 0, struct ioctl_arg) 
+21#define IOCTL_VALGET _IOR(IOC_MAGIC, 1, struct ioctl_arg) 
+22#define IOCTL_VALGET_NUM _IOR(IOC_MAGIC, 2, int) 
+23#define IOCTL_VALSET_NUM _IOW(IOC_MAGIC, 3, int) 
+24 
+25#define IOCTL_VAL_MAXNR 3 
+26#define DRIVER_NAME "ioctltest" 
+27 
+28static unsigned int test_ioctl_major = 0; 
+29static unsigned int num_of_dev = 1; 
+30static struct cdev test_ioctl_cdev; 
+31static int ioctl_num = 0; 
+32 
+33struct test_ioctl_data { 
+34    unsigned char val; 
+35    rwlock_t lock; 
+36}; 
+37 
+38static long test_ioctl_ioctl(struct file *filp, 
+39                             unsigned int cmd, 
+40                             unsigned long arg) 
+41{ 
+42    struct test_ioctl_data *ioctl_data = filp->private_data; 
+43    int retval = 0; 
+44    unsigned char val; 
+45    struct ioctl_arg data; 
+46    memset(&data, 0, sizeof(data)); 
+47 
+48    switch (cmd) { 
+49    case IOCTL_VALSET: 
+50 
+51        /* 
+52        if (!capable(CAP_SYS_ADMIN)) { 
+53         retval = -EPERM; 
+54         goto done; 
+55        } 
+56        if (!access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd))) { 
+57         retval = -EFAULT; 
+58         goto done; 
+59        } 
+60        */ 
+61        if (copy_from_user(&data, (int __user *) arg, sizeof(data))) { 
+62            retval = -EFAULT; 
+63            goto done; 
+64        } 
+65 
+66        pr_alert("IOCTL set val:%x .\n", data.val); 
+67        write_lock(&ioctl_data->lock); 
+68        ioctl_data->val = data.val; 
+69        write_unlock(&ioctl_data->lock); 
+70        break; 
+71 
+72    case IOCTL_VALGET: 
+73        /* 
+74        if (!access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd))) { 
+75                                     retval = -EFAULT; 
+76                                     goto done; 
+77                             } 
+78        */ 
+79        read_lock(&ioctl_data->lock); 
+80        val = ioctl_data->val; 
+81        read_unlock(&ioctl_data->lock); 
+82        data.val = val; 
+83 
+84        if (copy_to_user((int __user *) arg, &data, sizeof(data))) { 
+85            retval = -EFAULT; 
+86            goto done; 
+87        } 
+88 
+89        break; 
+90 
+91    case IOCTL_VALGET_NUM: 
+92        retval = __put_user(ioctl_num, (int __user *) arg); 
+93        break; 
+94 
+95    case IOCTL_VALSET_NUM: 
+96        /* 
+97        if (!capable(CAP_SYS_ADMIN)) 
+98         return -EPERM; 
+99        */ 
+100        ioctl_num = arg; 
+101        break; 
+102 
+103    default: 
+104        retval = -ENOTTY; 
+105    } 
+106 
+107done: 
+108    return retval; 
+109} 
+110 
+111ssize_t test_ioctl_read(struct file *filp, 
+112                        char __user *buf, 
+113                        size_t count, 
+114                        loff_t *f_pos) 
+115{ 
+116    struct test_ioctl_data *ioctl_data = filp->private_data; 
+117    unsigned char val; 
+118    int retval; 
+119    int i = 0; 
+120    read_lock(&ioctl_data->lock); 
+121    val = ioctl_data->val; 
+122    read_unlock(&ioctl_data->lock); 
+123 
+124    for (; i < count; i++) { 
+125        if (copy_to_user(&buf[i], &val, 1)) { 
+126            retval = -EFAULT; 
+127            goto out; 
+128        } 
+129    } 
+130 
+131    retval = count; 
+132out: 
+133    return retval; 
+134} 
+135 
+136static int test_ioctl_close(struct inode *inode, struct file *filp) 
+137{ 
+138    pr_alert("%s call.\n", __func__); 
+139 
+140    if (filp->private_data) { 
+141        kfree(filp->private_data); 
+142        filp->private_data = NULL; 
+143    } 
+144 
+145    return 0; 
+146} 
+147 
+148static int test_ioctl_open(struct inode *inode, struct file *filp) 
+149{ 
+150    struct test_ioctl_data *ioctl_data; 
+151    pr_alert("%s call.\n", __func__); 
+152    ioctl_data = kmalloc(sizeof(struct test_ioctl_data), GFP_KERNEL); 
+153 
+154    if (ioctl_data == NULL) { 
+155        return -ENOMEM; 
+156    } 
+157 
+158    rwlock_init(&ioctl_data->lock); 
+159    ioctl_data->val = 0xFF; 
+160    filp->private_data = ioctl_data; 
+161    return 0; 
+162} 
+163 
+164struct file_operations fops = { 
+165    .owner = THIS_MODULE, 
+166    .open = test_ioctl_open, 
+167    .release = test_ioctl_close, 
+168    .read = test_ioctl_read, 
+169    .unlocked_ioctl = test_ioctl_ioctl, 
+170}; 
+171 
+172static int ioctl_init(void) 
+173{ 
+174    dev_t dev = MKDEV(test_ioctl_major, 0); 
+175    int alloc_ret = 0; 
+176    int cdev_ret = 0; 
+177    alloc_ret = alloc_chrdev_region(&dev, 0, num_of_dev, DRIVER_NAME); 
+178 
+179    if (alloc_ret) { 
+180        goto error; 
+181    } 
+182 
+183    test_ioctl_major = MAJOR(dev); 
+184    cdev_init(&test_ioctl_cdev, &fops); 
+185    cdev_ret = cdev_add(&test_ioctl_cdev, dev, num_of_dev); 
+186 
+187    if (cdev_ret) { 
+188        goto error; 
+189    } 
+190 
+191    pr_alert("%s driver(major: %d) installed.\n", DRIVER_NAME, 
+192             test_ioctl_major); 
+193    return 0; 
+194error: 
+195 
+196    if (cdev_ret == 0) { 
+197        cdev_del(&test_ioctl_cdev); 
+198    } 
+199 
+200    if (alloc_ret == 0) { 
+201        unregister_chrdev_region(dev, num_of_dev); 
+202    } 
+203 
+204    return -1; 
+205} 
+206 
+207static void ioctl_exit(void) 
+208{ 
+209    dev_t dev = MKDEV(test_ioctl_major, 0); 
+210    cdev_del(&test_ioctl_cdev); 
+211    unregister_chrdev_region(dev, num_of_dev); 
+212    pr_alert("%s driver removed.\n", DRIVER_NAME); 
+213} 
+214 
+215module_init(ioctl_init); 
+216module_exit(ioctl_exit); 
+217 
+218MODULE_LICENSE("GPL"); 
+219MODULE_DESCRIPTION("This is test_ioctl module");
+

+

+

0.10 System Calls

+

So far, the only thing we’ve done was to use well defined kernel mechanisms to +register /proc files and device handlers. This is fine if you want to do something the +kernel programmers thought you’d want, such as write a device driver. But what if +you want to do something unusual, to change the behavior of the system in some +way? Then, you are mostly on your own. +

If you are not being sensible and using a virtual machine then this is where kernel +programming can become hazardous. While writing the example below, +I killed the open() system call. This meant I could not open any files, I +could not run any programs, and I could not shutdown the system. I had +to restart the virtual machine. No important files got anihilated, but if I + + + +was doing this on some live mission critical system then that could have +been a possible outcome. To ensure you do not lose any files, even within a +test environment, please run sync right before you do the insmod and the +rmmod. +

Forget about /proc files, forget about device files. They are just minor details. +Minutiae in the vast expanse of the universe. The real process to kernel +communication mechanism, the one used by all processes, is system calls. When a +process requests a service from the kernel (such as opening a file, forking to a new +process, or requesting more memory), this is the mechanism used. If you want to +change the behaviour of the kernel in interesting ways, this is the place to do +it. By the way, if you want to see which system calls a program uses, run +strace <arguments>. +

In general, a process is not supposed to be able to access the kernel. It can not +access kernel memory and it can’t call kernel functions. The hardware of the CPU +enforces this (that is the reason why it is called “protected mode” or “page +protection”). +

System calls are an exception to this general rule. What happens is that the +process fills the registers with the appropriate values and then calls a special +instruction which jumps to a previously defined location in the kernel (of course, that +location is readable by user processes, it is not writable by them). Under Intel CPUs, +this is done by means of interrupt 0x80. The hardware knows that once you jump to +this location, you are no longer running in restricted user mode, but as the +operating system kernel — and therefore you’re allowed to do whatever you +want. +

The location in the kernel a process can jump to is called system_call. The +procedure at that location checks the system call number, which tells the kernel what +service the process requested. Then, it looks at the table of system calls +(sys_call_table) to see the address of the kernel function to call. Then it calls the +function, and after it returns, does a few system checks and then return back to the +process (or to a different process, if the process time ran out). If you want to read +this code, it is at the source file arch/$(architecture)/kernel/entry.S, after the +line ENTRY(system_call). +

So, if we want to change the way a certain system call works, what we need to do +is to write our own function to implement it (usually by adding a bit of our own +code, and then calling the original function) and then change the pointer at +sys_call_table to point to our function. Because we might be removed later and +we don’t want to leave the system in an unstable state, it’s important for +cleanup_module to restore the table to its original state. +

The source code here is an example of such a kernel module. We want to “spy” on +a certain user, and to pr_info() a message whenever that user opens a file. +Towards this end, we replace the system call to open a file with our own +function, called our_sys_open. This function checks the uid (user’s id) of the +current process, and if it is equal to the uid we spy on, it calls pr_info() +to display the name of the file to be opened. Then, either way, it calls the +original open() function with the same parameters, to actually open the +file. + + + +

The init_module function replaces the appropriate location in sys_call_table +and keeps the original pointer in a variable. The cleanup_module function uses that +variable to restore everything back to normal. This approach is dangerous, because of +the possibility of two kernel modules changing the same system call. Imagine we have +two kernel modules, A and B. A’s open system call will be A_open and B’s will be +B_open. Now, when A is inserted into the kernel, the system call is replaced with +A_open, which will call the original sys_open when it is done. Next, B +is inserted into the kernel, which replaces the system call with B_open, +which will call what it thinks is the original system call, A_open, when it’s +done. +

Now, if B is removed first, everything will be well — it will simply restore the +system call to A_open, which calls the original. However, if A is removed and then B +is removed, the system will crash. A’s removal will restore the system call to the +original, sys_open, cutting B out of the loop. Then, when B is removed, it will +restore the system call to what it thinks is the original, A_open, which is no +longer in memory. At first glance, it appears we could solve this particular +problem by checking if the system call is equal to our open function and if so +not changing it at all (so that B won’t change the system call when it is +removed), but that will cause an even worse problem. When A is removed, it +sees that the system call was changed to B_open so that it is no longer +pointing to A_open, so it will not restore it to sys_open before it is +removed from memory. Unfortunately, B_open will still try to call A_open +which is no longer there, so that even without removing B the system would +crash. +

Note that all the related problems make syscall stealing unfeasiable for production +use. In order to keep people from doing potential harmful things sys_call_table is +no longer exported. This means, if you want to do something more than a mere dry +run of this example, you will have to patch your current kernel in order to +have sys_call_table exported. In the example directory you will find a +README and the patch. As you can imagine, such modifications are not to be +taken lightly. Do not try this on valueable systems (ie systems that you +do not own - or cannot restore easily). You will need to get the complete +sourcecode of this guide as a tarball in order to get the patch and the README. +Depending on your kernel version, you might even need to hand apply the +patch. +

+

+
1/* 
+2 *  syscall.c 
+3 * 
+4 *  System call "stealing" sample. 
+5 * 
+6 *  Disables page protection at a processor level by 
+7 *  changing the 16th bit in the cr0 register (could be Intel specific) 
+8 * 
+9 *  Based on example by Peter Jay Salzman and 
+10 *  https://bbs.archlinux.org/viewtopic.php?id=139406 
+11 */ 
+12 
+13#include <linux/delay.h> 
+14#include <linux/kernel.h> 
+15#include <linux/module.h> 
+16#include <linux/moduleparam.h> /* which will have params */ 
+17#include <linux/syscalls.h> 
+18#include <linux/unistd.h> /* The list of system calls */ 
+19 
+20/* 
+21 * For the current (process) structure, we need 
+22 * this to know who the current user is. 
+23 */ 
+24#include <linux/sched.h> 
+25#include <linux/uaccess.h> 
+26 
+27unsigned long **sys_call_table; 
+28unsigned long original_cr0; 
+29 
+30/* 
+31 * UID we want to spy on - will be filled from the 
+32 * command line 
+33 */ 
+34static int uid; 
+35module_param(uid, int, 0644); 
+36 
+37/* 
+38 * A pointer to the original system call. The reason 
+39 * we keep this, rather than call the original function 
+40 * (sys_open), is because somebody else might have 
+41 * replaced the system call before us. Note that this 
+42 * is not 100% safe, because if another module 
+43 * replaced sys_open before us, then when we're inserted 
+44 * we'll call the function in that module - and it 
+45 * might be removed before we are. 
+46 * 
+47 * Another reason for this is that we can't get sys_open. 
+48 * It's a static variable, so it is not exported. 
+49 */ 
+50asmlinkage int (*original_call)(const char *, intint); 
+51 
+52/* 
+53 * The function we'll replace sys_open (the function 
+54 * called when you call the open system call) with. To 
+55 * find the exact prototype, with the number and type 
+56 * of arguments, we find the original function first 
+57 * (it's at fs/open.c). 
+58 * 
+59 * In theory, this means that we're tied to the 
+60 * current version of the kernel. In practice, the 
+61 * system calls almost never change (it would wreck havoc 
+62 * and require programs to be recompiled, since the system 
+63 * calls are the interface between the kernel and the 
+64 * processes). 
+65 */ 
+66asmlinkage int our_sys_open(const char *filename, int flags, int mode) 
+67{ 
+68    int i = 0; 
+69    char ch; 
+70 
+71    /* 
+72     * Report the file, if relevant 
+73     */ 
+74    pr_info("Opened file by %d: ", uid); 
+75    do { 
+76        get_user(ch, filename + i); 
+77        i++; 
+78        pr_info("%c", ch); 
+79    } while (ch != 0); 
+80    pr_info("\n"); 
+81 
+82    /* 
+83     * Call the original sys_open - otherwise, we lose 
+84     * the ability to open files 
+85     */ 
+86    return original_call(filename, flags, mode); 
+87} 
+88 
+89static unsigned long **aquire_sys_call_table(void) 
+90{ 
+91    unsigned long int offset = PAGE_OFFSET; 
+92    unsigned long **sct; 
+93 
+94    while (offset < ULLONG_MAX) { 
+95        sct = (unsigned long **) offset; 
+96 
+97        if (sct[__NR_close] == (unsigned long *) ksys_close) 
+98            return sct; 
+99 
+100        offset += sizeof(void *); 
+101    } 
+102 
+103    return NULL; 
+104} 
+105 
+106static int __init syscall_start(void) 
+107{ 
+108    if (!(sys_call_table = aquire_sys_call_table())) 
+109        return -1; 
+110 
+111    original_cr0 = read_cr0(); 
+112 
+113    write_cr0(original_cr0 & ~0x00010000); 
+114 
+115    /* keep track of the original open function */ 
+116    original_call = (void *) sys_call_table[__NR_open]; 
+117 
+118    /* use our open function instead */ 
+119    sys_call_table[__NR_open] = (unsigned long *) our_sys_open; 
+120 
+121    write_cr0(original_cr0); 
+122 
+123    pr_info("Spying on UID:%d\n", uid); 
+124 
+125    return 0; 
+126} 
+127 
+128static void __exit syscall_end(void) 
+129{ 
+130    if (!sys_call_table) { 
+131        return; 
+132    } 
+133 
+134    /* 
+135     * Return the system call back to normal 
+136     */ 
+137    if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) { 
+138        pr_alert("Somebody else also played with the "); 
+139        pr_alert("open system call\n"); 
+140        pr_alert("The system may be left in "); 
+141        pr_alert("an unstable state.\n"); 
+142    } 
+143 
+144    write_cr0(original_cr0 & ~0x00010000); 
+145    sys_call_table[__NR_open] = (unsigned long *) original_call; 
+146    write_cr0(original_cr0); 
+147 
+148    msleep(2000); 
+149} 
+150 
+151module_init(syscall_start); 
+152module_exit(syscall_end); 
+153 
+154MODULE_LICENSE("GPL");
+

+

+

0.11 Blocking Processes and threads

+ + + +

+

+

0.11.1 Sleep

+

What do you do when somebody asks you for something you can’t do right away? If +you’re a human being and you’re bothered by a human being, the only thing you can +say is: "Not right now, I’m busy. Go away!". But if you’re a kernel module and +you’re bothered by a process, you have another possibility. You can put the process +to sleep until you can service it. After all, processes are being put to sleep by the +kernel and woken up all the time (that’s the way multiple processes appear to run on +the same time on a single CPU). +

This kernel module is an example of this. The file (called /proc/sleep) can only +be opened by a single process at a time. If the file is already open, the kernel module +calls wait_event_interruptible. The easiest way to keep a file open is to open it +with: +

+

+
1tail -f
+

This function changes the status of the task (a task is the kernel data +structure which holds information about a process and the system call it’s in, if +any) to TASK_INTERRUPTIBLE, which means that the task will +not run until it is woken up somehow, and adds it to WaitQ, the queue +of tasks waiting to access the file. Then, the function calls the scheduler +to context switch to a different process, one which has some use for the +CPU. +

When a process is done with the file, it closes it, and module_close is called. That +function wakes up all the processes in the queue (there’s no mechanism +to only wake up one of them). It then returns and the process which just +closed the file can continue to run. In time, the scheduler decides that that +process has had enough and gives control of the CPU to another process. +Eventually, one of the processes which was in the queue will be given control +of the CPU by the scheduler. It starts at the point right after the call to +module_interruptible_sleep_on. +

This means that the process is still in kernel mode - as far as the process is +concerned, it issued the open system call and the system call hasn’t returned yet. +The process doesn’t know somebody else used the CPU for most of the time between +the moment it issued the call and the moment it returned. +

It can then proceed to set a global variable to tell all the other processes that the +file is still open and go on with its life. When the other processes get a piece of the +CPU, they’ll see that global variable and go back to sleep. +

So we’ll use tail -f to keep the file open in the background, while trying to +access it with another process (again in the background, so that we need not +switch to a different vt). As soon as the first background process is killed +with kill %1 , the second is woken up, is able to access the file and finally +terminates. + + + +

To make our life more interesting, module_close doesn’t have a monopoly +on waking up the processes which wait to access the file. A signal, such as +Ctrl +c (SIGINT) can also wake up a process. This is because we used +module_interruptible_sleep_on. We could have used module_sleep_on +instead, but that would have resulted in extremely angry users whose Ctrl+c’s are +ignored. +

In that case, we want to return with -EINTR immediately. This is important so +users can, for example, kill the process before it receives the file. +

There is one more point to remember. Some times processes don’t want to sleep, +they want either to get what they want immediately, or to be told it cannot be done. +Such processes use the O_NONBLOCK flag when opening the file. The kernel is +supposed to respond by returning with the error code -EAGAIN from operations +which would otherwise block, such as opening the file in this example. The program +cat_noblock, available in the source directory for this chapter, can be used to open a +file with O_NONBLOCK. + + + +

+
+$ sudo insmod sleep.ko
+$ cat_noblock /proc/sleep
+Last input:
+$ tail -f /proc/sleep &
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+tail: /proc/sleep: file truncated
+[1] 6540
+$ cat_noblock /proc/sleep
+Open would block
+$ kill %1
+[1]+  Terminated              tail -f /proc/sleep
+$ cat_noblock /proc/sleep
+Last input:
+$
+
+

+

+

+
1/* 
+2 *  sleep.c - create a /proc file, and if several processes try to open it at 
+3 *  the same time, put all but one to sleep 
+4 */ 
+5 
+6#include <linux/kernel.h>  /* We're doing kernel work */ 
+7#include <linux/module.h>  /* Specifically, a module */ 
+8#include <linux/proc_fs.h> /* Necessary because we use proc fs */ 
+9#include <linux/sched.h>   /* For putting processes to sleep and 
+10                                   waking them up */  
+11#include <linux/uaccess.h> /* for get_user and put_user */ 
+12#include <linux/version.h> 
+13 
+14#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+15#define HAVE_PROC_OPS 
+16#endif 
+17 
+18/* 
+19 * The module's file functions 
+20 */ 
+21 
+22/* 
+23 * Here we keep the last message received, to prove that we can process our 
+24 * input 
+25 */ 
+26#define MESSAGE_LENGTH 80 
+27static char Message[MESSAGE_LENGTH]; 
+28 
+29static struct proc_dir_entry *Our_Proc_File; 
+30#define PROC_ENTRY_FILENAME "sleep" 
+31 
+32/* 
+33 * Since we use the file operations struct, we can't use the special proc 
+34 * output provisions - we have to use a standard read function, which is this 
+35 * function 
+36 */ 
+37static ssize_t module_output(struct file *file, /* see include/linux/fs.h   */ 
+38                             char *buf,         /* The buffer to put data to 
+39                                                   (in the user segment)    */  
+40                             size_t len,        /* The length of the buffer */ 
+41                             loff_t *offset) 
+42{ 
+43    static int finished = 0; 
+44    int i; 
+45    char message[MESSAGE_LENGTH + 30]; 
+46 
+47    /* 
+48     * Return 0 to signify end of file - that we have nothing 
+49     * more to say at this point. 
+50     */ 
+51    if (finished) { 
+52        finished = 0; 
+53        return 0; 
+54    } 
+55 
+56    /* 
+57     * If you don't understand this by now, you're hopeless as a kernel 
+58     * programmer. 
+59     */ 
+60    sprintf(message, "Last input:%s\n", Message); 
+61    for (i = 0; i < len && message[i]; i++) 
+62        put_user(message[i], buf + i); 
+63 
+64    finished = 1; 
+65    return i; /* Return the number of bytes "read" */ 
+66} 
+67 
+68/* 
+69 * This function receives input from the user when the user writes to the /proc 
+70 * file. 
+71 */ 
+72static ssize_t module_input(struct file *file, /* The file itself */ 
+73                            const char *buf,   /* The buffer with input */ 
+74                            size_t length,     /* The buffer's length */ 
+75                            loff_t *offset)    /* offset to file - ignore */ 
+76{ 
+77    int i; 
+78 
+79    /* 
+80     * Put the input into Message, where module_output will later be 
+81     * able to use it 
+82     */ 
+83    for (i = 0; i < MESSAGE_LENGTH - 1 && i < length; i++) 
+84        get_user(Message[i], buf + i); 
+85    /* 
+86     * we want a standard, zero terminated string 
+87     */ 
+88    Message[i] = '\0'; 
+89 
+90    /* 
+91     * We need to return the number of input characters used 
+92     */ 
+93    return i; 
+94} 
+95 
+96/* 
+97 * 1 if the file is currently open by somebody 
+98 */ 
+99int Already_Open = 0; 
+100 
+101/* 
+102 * Queue of processes who want our file 
+103 */ 
+104DECLARE_WAIT_QUEUE_HEAD(WaitQ); 
+105/* 
+106 * Called when the /proc file is opened 
+107 */ 
+108static int module_open(struct inode *inode, struct file *file) 
+109{ 
+110    /* 
+111     * If the file's flags include O_NONBLOCK, it means the process doesn't 
+112     * want to wait for the file.  In this case, if the file is already 
+113     * open, we should fail with -EAGAIN, meaning "you'll have to try 
+114     * again", instead of blocking a process which would rather stay awake. 
+115     */ 
+116    if ((file->f_flags & O_NONBLOCK) && Already_Open) 
+117        return -EAGAIN; 
+118 
+119    /* 
+120     * This is the correct place for try_module_get(THIS_MODULE) because 
+121     * if a process is in the loop, which is within the kernel module, 
+122     * the kernel module must not be removed. 
+123     */ 
+124    try_module_get(THIS_MODULE); 
+125 
+126    /* 
+127     * If the file is already open, wait until it isn't 
+128     */ 
+129 
+130    while (Already_Open) { 
+131        int i, is_sig = 0; 
+132 
+133        /* 
+134         * This function puts the current process, including any system 
+135         * calls, such as us, to sleep.  Execution will be resumed right 
+136         * after the function call, either because somebody called 
+137         * wake_up(&WaitQ) (only module_close does that, when the file 
+138         * is closed) or when a signal, such as Ctrl-C, is sent 
+139         * to the process 
+140         */ 
+141        wait_event_interruptible(WaitQ, !Already_Open); 
+142 
+143        /* 
+144         * If we woke up because we got a signal we're not blocking, 
+145         * return -EINTR (fail the system call).  This allows processes 
+146         * to be killed or stopped. 
+147         */ 
+148 
+149        /* 
+150         * Emmanuel Papirakis: 
+151         * 
+152         * This is a little update to work with 2.2.*.  Signals now are 
+153         * contained in two words (64 bits) and are stored in a structure that 
+154         * contains an array of two unsigned longs.  We now have to make 2 
+155         * checks in our if. 
+156         * 
+157         * Ori Pomerantz: 
+158         * 
+159         * Nobody promised me they'll never use more than 64 bits, or that this 
+160         * book won't be used for a version of Linux with a word size of 16 
+161         * bits.  This code would work in any case. 
+162         */ 
+163        for (i = 0; i < _NSIG_WORDS && !is_sig; i++) 
+164            is_sig = current->pending.signal.sig[i] & ~current->blocked.sig[i]; 
+165 
+166        if (is_sig) { 
+167            /* 
+168             * It's important to put module_put(THIS_MODULE) here, 
+169             * because for processes where the open is interrupted 
+170             * there will never be a corresponding close. If we 
+171             * don't decrement the usage count here, we will be 
+172             * left with a positive usage count which we'll have no 
+173             * way to bring down to zero, giving us an immortal 
+174             * module, which can only be killed by rebooting 
+175             * the machine. 
+176             */ 
+177            module_put(THIS_MODULE); 
+178            return -EINTR; 
+179        } 
+180    } 
+181 
+182    /* 
+183     * If we got here, Already_Open must be zero 
+184     */ 
+185 
+186    /* 
+187     * Open the file 
+188     */ 
+189    Already_Open = 1; 
+190    return 0; /* Allow the access */ 
+191} 
+192 
+193/* 
+194 * Called when the /proc file is closed 
+195 */ 
+196int module_close(struct inode *inode, struct file *file) 
+197{ 
+198    /* 
+199     * Set Already_Open to zero, so one of the processes in the WaitQ will 
+200     * be able to set Already_Open back to one and to open the file. All 
+201     * the other processes will be called when Already_Open is back to one, 
+202     * so they'll go back to sleep. 
+203     */ 
+204    Already_Open = 0; 
+205 
+206    /* 
+207     * Wake up all the processes in WaitQ, so if anybody is waiting for the 
+208     * file, they can have it. 
+209     */ 
+210    wake_up(&WaitQ); 
+211 
+212    module_put(THIS_MODULE); 
+213 
+214    return 0; /* success */ 
+215} 
+216 
+217/* 
+218 * Structures to register as the /proc file, with pointers to all the relevant 
+219 * functions. 
+220 */ 
+221 
+222/* 
+223 * File operations for our proc file. This is where we place pointers to all 
+224 * the functions called when somebody tries to do something to our file. NULL 
+225 * means we don't want to deal with something. 
+226 */ 
+227#ifdef HAVE_PROC_OPS 
+228static const struct proc_ops File_Ops_4_Our_Proc_File = { 
+229    .proc_read = module_output,   /* "read" from the file */ 
+230    .proc_write = module_input,   /* "write" to the file */ 
+231    .proc_open = module_open,     /* called when the /proc file is opened */ 
+232    .proc_release = module_close, /* called when it's closed */ 
+233}; 
+234#else 
+235static const struct file_operations File_Ops_4_Our_Proc_File = { 
+236    .read = module_output, 
+237    .write = module_input, 
+238    .open = module_open, 
+239    .release = module_close, 
+240}; 
+241#endif 
+242 
+243/* 
+244 * Module initialization and cleanup 
+245 */ 
+246 
+247/* 
+248 * Initialize the module - register the proc file 
+249 */ 
+250 
+251int init_module() 
+252{ 
+253    Our_Proc_File = 
+254        proc_create(PROC_ENTRY_FILENAME, 0644, NULL, &File_Ops_4_Our_Proc_File); 
+255    if (Our_Proc_File == NULL) { 
+256        remove_proc_entry(PROC_ENTRY_FILENAME, NULL); 
+257        pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME); 
+258        return -ENOMEM; 
+259    } 
+260    proc_set_size(Our_Proc_File, 80); 
+261    proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); 
+262 
+263    pr_info("/proc/test created\n"); 
+264 
+265    return 0; 
+266} 
+267 
+268/* 
+269 * Cleanup - unregister our file from /proc.  This could get dangerous if 
+270 * there are still processes waiting in WaitQ, because they are inside our 
+271 * open function, which will get unloaded. I'll explain how to avoid removal 
+272 * of a kernel module in such a case in chapter 10. 
+273 */ 
+274void cleanup_module() 
+275{ 
+276    remove_proc_entry(PROC_ENTRY_FILENAME, NULL); 
+277    pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME); 
+278} 
+279 
+280MODULE_LICENSE("GPL");
+ +

+

+
1/* 
+2 *  cat_noblock.c - open a file and display its contents, but exit rather than 
+3 *  wait for input. 
+4 */ 
+5#include <errno.h>  /* for errno */ 
+6#include <fcntl.h>  /* for open */ 
+7#include <stdio.h>  /* standard I/O */ 
+8#include <stdlib.h> /* for exit */ 
+9#include <unistd.h> /* for read */ 
+10 
+11#define MAX_BYTES 1024 * 4 
+12 
+13int main(int argc, char *argv[]) 
+14{ 
+15    int fd;                 /* The file descriptor for the file to read */ 
+16    size_t bytes;           /* The number of bytes read */ 
+17    char buffer[MAX_BYTES]; /* The buffer for the bytes */ 
+18 
+19 
+20    /* Usage */ 
+21    if (argc != 2) { 
+22        printf("Usage: %s <filename>\n", argv[0]); 
+23        puts("Reads the content of a file, but doesn't wait for input"); 
+24        exit(-1); 
+25    } 
+26 
+27    /* Open the file for reading in non blocking mode */ 
+28    fd = open(argv[1], O_RDONLY | O_NONBLOCK); 
+29 
+30    /* If open failed */ 
+31    if (fd == -1) { 
+32        if (errno = EAGAIN) 
+33            puts("Open would block"); 
+34        else 
+35            puts("Open failed"); 
+36        exit(-1); 
+37    } 
+38 
+39    /* Read the file and output its contents */ 
+40    do { 
+41        int i; 
+42 
+43        /* Read characters from the file */ 
+44        bytes = read(fd, buffer, MAX_BYTES); 
+45 
+46        /* If there's an error, report it and die */ 
+47        if (bytes == -1) { 
+48            if (errno = EAGAIN) 
+49                puts("Normally I'd block, but you told me not to"); 
+50            else 
+51                puts("Another read error"); 
+52            exit(-1); 
+53        } 
+54 
+55        /* Print the characters */ 
+56        if (bytes > 0) { 
+57            for (i = 0; i < bytes; i++) 
+58                putchar(buffer[i]); 
+59        } 
+60 
+61        /* While there are no errors and the file isn't over */ 
+62    } while (bytes > 0); 
+63    return 0; 
+64}
+

+

+

0.11.2 Completions

+

Sometimes one thing should happen before another within a module having multiple +threads. Rather than using /proc/sleep commands the kernel has another way to +do this which allows timeouts or interrupts to also happen. +

In the following example two threads are started, but one needs to start before +another. +

+ + + +

+
1/* 
+2 *  completions.c 
+3 */ 
+4#include <linux/completion.h> 
+5#include <linux/init.h> 
+6#include <linux/kernel.h> 
+7#include <linux/kthread.h> 
+8#include <linux/module.h> 
+9 
+10static struct { 
+11    struct completion crank_comp; 
+12    struct completion flywheel_comp; 
+13} machine; 
+14 
+15static int machine_crank_thread(void *arg) 
+16{ 
+17    pr_info("Turn the crank\n"); 
+18 
+19    complete_all(&machine.crank_comp); 
+20    complete_and_exit(&machine.crank_comp, 0); 
+21} 
+22 
+23static int machine_flywheel_spinup_thread(void *arg) 
+24{ 
+25    wait_for_completion(&machine.crank_comp); 
+26 
+27    pr_info("Flywheel spins up\n"); 
+28 
+29    complete_all(&machine.flywheel_comp); 
+30    complete_and_exit(&machine.flywheel_comp, 0); 
+31} 
+32 
+33static int completions_init(void) 
+34{ 
+35    struct task_struct *crank_thread; 
+36    struct task_struct *flywheel_thread; 
+37 
+38    pr_info("completions example\n"); 
+39 
+40    init_completion(&machine.crank_comp); 
+41    init_completion(&machine.flywheel_comp); 
+42 
+43    crank_thread = kthread_create(machine_crank_thread, NULL, "KThread Crank"); 
+44    if (IS_ERR(crank_thread)) 
+45        goto ERROR_THREAD_1; 
+46 
+47    flywheel_thread = kthread_create(machine_flywheel_spinup_thread, NULL, 
+48                                     "KThread Flywheel"); 
+49    if (IS_ERR(flywheel_thread)) 
+50        goto ERROR_THREAD_2; 
+51 
+52    wake_up_process(flywheel_thread); 
+53    wake_up_process(crank_thread); 
+54 
+55    return 0; 
+56 
+57ERROR_THREAD_2: 
+58    kthread_stop(crank_thread); 
+59ERROR_THREAD_1: 
+60 
+61    return -1; 
+62} 
+63 
+64void completions_exit(void) 
+65{ 
+66    wait_for_completion(&machine.crank_comp); 
+67    wait_for_completion(&machine.flywheel_comp); 
+68 
+69    pr_info("completions exit\n"); 
+70} 
+71 
+72module_init(completions_init); 
+73module_exit(completions_exit); 
+74 
+75MODULE_DESCRIPTION("Completions example"); 
+76MODULE_LICENSE("GPL");
+

The machine structure stores the completion states for the two threads. At the +exit point of each thread the respective completion state is updated, and +wait_for_completion is used by the flywheel thread to ensure that it doesn’t begin +prematurely. +

So even though flywheel_thread is started first you should notice if you load this +module and run dmesg that turning the crank always happens first because the +flywheel thread waits for it to complete. +

There are other variations upon the wait_for_completion function, which include +timeouts or being interrupted, but this basic mechanism is enough for many common +situations without adding a lot of complexity. +

+

+

0.12 Avoiding Collisions and Deadlocks

+

If processes running on different CPUs or in different threads try to access the same +memory then it’s possible that strange things can happen or your system can lock +up. To avoid this various types of mutual exclusion kernel functions are available. +These indicate if a section of code is "locked" or "unlocked" so that simultaneous +attempts to run it can’t happen. +

+

0.12.1 Mutex

+

You can use kernel mutexes (mutual exclusions) in much the same manner that you +might deploy them in userland. This may be all that’s needed to avoid collisions in +most cases. +

+

+
1/* 
+2 *  example_mutex.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/mutex.h> 
+8 
+9DEFINE_MUTEX(mymutex); 
+10 
+11static int example_mutex_init(void) 
+12{ 
+13    int ret; 
+14 
+15    pr_info("example_mutex init\n"); 
+16 
+17    ret = mutex_trylock(&mymutex); 
+18    if (ret != 0) { 
+19        pr_info("mutex is locked\n"); 
+20 
+21        if (mutex_is_locked(&mymutex) == 0) 
+22            pr_info("The mutex failed to lock!\n"); 
+23 
+24        mutex_unlock(&mymutex); 
+25        pr_info("mutex is unlocked\n"); 
+26    } else 
+27        pr_info("Failed to lock\n"); 
+28 
+29    return 0; 
+30} 
+31 
+32static void example_mutex_exit(void) 
+33{ 
+34    pr_info("example_mutex exit\n"); 
+35} 
+36 
+37module_init(example_mutex_init); 
+38module_exit(example_mutex_exit); 
+39 
+40MODULE_DESCRIPTION("Mutex example"); 
+41MODULE_LICENSE("GPL");
+

+

+

0.12.2 Spinlocks

+

As the name suggests, spinlocks lock up the CPU that the code is running on, +taking 100% of its resources. Because of this you should only use the spinlock +mechanism around code which is likely to take no more than a few milliseconds to +run and so won’t noticably slow anything down from the user’s point of +view. + + + +

The example here is "irq safe" in that if interrupts happen during the lock then +they won’t be forgotten and will activate when the unlock happens, using the flags +variable to retain their state. +

+

+
1/* 
+2 *  example_spinlock.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/interrupt.h> 
+6#include <linux/kernel.h> 
+7#include <linux/module.h> 
+8#include <linux/spinlock.h> 
+9 
+10DEFINE_SPINLOCK(sl_static); 
+11spinlock_t sl_dynamic; 
+12 
+13static void example_spinlock_static(void) 
+14{ 
+15    unsigned long flags; 
+16 
+17    spin_lock_irqsave(&sl_static, flags); 
+18    pr_info("Locked static spinlock\n"); 
+19 
+20    /* Do something or other safely. 
+21       Because this uses 100% CPU time this 
+22       code should take no more than a few 
+23       milliseconds to run */ 
+24 
+25    spin_unlock_irqrestore(&sl_static, flags); 
+26    pr_info("Unlocked static spinlock\n"); 
+27} 
+28 
+29static void example_spinlock_dynamic(void) 
+30{ 
+31    unsigned long flags; 
+32 
+33    spin_lock_init(&sl_dynamic); 
+34    spin_lock_irqsave(&sl_dynamic, flags); 
+35    pr_info("Locked dynamic spinlock\n"); 
+36 
+37    /* Do something or other safely. 
+38       Because this uses 100% CPU time this 
+39       code should take no more than a few 
+40       milliseconds to run */ 
+41 
+42    spin_unlock_irqrestore(&sl_dynamic, flags); 
+43    pr_info("Unlocked dynamic spinlock\n"); 
+44} 
+45 
+46static int example_spinlock_init(void) 
+47{ 
+48    pr_info("example spinlock started\n"); 
+49 
+50    example_spinlock_static(); 
+51    example_spinlock_dynamic(); 
+52 
+53    return 0; 
+54} 
+55 
+56static void example_spinlock_exit(void) 
+57{ 
+58    pr_info("example spinlock exit\n"); 
+59} 
+60 
+61module_init(example_spinlock_init); 
+62module_exit(example_spinlock_exit); 
+63 
+64MODULE_DESCRIPTION("Spinlock example"); 
+65MODULE_LICENSE("GPL");
+

+

+

0.12.3 Read and write locks

+

Read and write locks are specialised kinds of spinlocks so that you can exclusively +read from something or write to something. Like the earlier spinlocks example the +one below shows an "irq safe" situation in which if other functions were triggered +from irqs which might also read and write to whatever you are concerned +with then they wouldn’t disrupt the logic. As before it’s a good idea to keep +anything done within the lock as short as possible so that it doesn’t hang up +the system and cause users to start revolting against the tyranny of your +module. +

+

+
1/* 
+2 *  example_rwlock.c 
+3 */ 
+4#include <linux/interrupt.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7 
+8DEFINE_RWLOCK(myrwlock); 
+9 
+10static void example_read_lock(void) 
+11{ 
+12    unsigned long flags; 
+13 
+14    read_lock_irqsave(&myrwlock, flags); 
+15    pr_info("Read Locked\n"); 
+16 
+17    /* Read from something */ 
+18 
+19    read_unlock_irqrestore(&myrwlock, flags); 
+20    pr_info("Read Unlocked\n"); 
+21} 
+22 
+23static void example_write_lock(void) 
+24{ 
+25    unsigned long flags; 
+26 
+27    write_lock_irqsave(&myrwlock, flags); 
+28    pr_info("Write Locked\n"); 
+29 
+30    /* Write to something */ 
+31 
+32    write_unlock_irqrestore(&myrwlock, flags); 
+33    pr_info("Write Unlocked\n"); 
+34} 
+35 
+36static int example_rwlock_init(void) 
+37{ 
+38    pr_info("example_rwlock started\n"); 
+39 
+40    example_read_lock(); 
+41    example_write_lock(); 
+42 
+43    return 0; 
+44} 
+45 
+46static void example_rwlock_exit(void) 
+47{ 
+48    pr_info("example_rwlock exit\n"); 
+49} 
+50 
+51module_init(example_rwlock_init); 
+52module_exit(example_rwlock_exit); 
+53 
+54MODULE_DESCRIPTION("Read/Write locks example"); 
+55MODULE_LICENSE("GPL");
+

Of course if you know for sure that there are no functions triggered by irqs +which could possibly interfere with your logic then you can use the simpler +read_lock(&myrwlock) and read_unlock(&myrwlock) or the corresponding write +functions. +

+

0.12.4 Atomic operations

+

If you’re doing simple arithmetic: adding, subtracting or bitwise operations then +there’s another way in the multi-CPU and multi-hyperthreaded world to stop other +parts of the system from messing with your mojo. By using atomic operations you +can be confident that your addition, subtraction or bit flip did actually happen +and wasn’t overwritten by some other shenanigans. An example is shown +below. +

+

+
1/* 
+2 *  example_atomic.c 
+3 */ 
+4#include <linux/interrupt.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7 
+8#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" 
+9#define BYTE_TO_BINARY(byte)                                  \ 
+10    (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'),     \ 
+11        (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), \ 
+12        (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), \ 
+13        (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0') 
+14 
+15static void atomic_add_subtract(void) 
+16{ 
+17    atomic_t debbie; 
+18    atomic_t chris = ATOMIC_INIT(50); 
+19 
+20    atomic_set(&debbie, 45); 
+21 
+22    /* subtract one */ 
+23    atomic_dec(&debbie); 
+24 
+25    atomic_add(7, &debbie); 
+26 
+27    /* add one */ 
+28    atomic_inc(&debbie); 
+29 
+30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
+31            atomic_read(&debbie)); 
+32} 
+33 
+34static void atomic_bitwise(void) 
+35{ 
+36    unsigned long word = 0; 
+37 
+38    pr_info("Bits 0: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+39    set_bit(3, &word); 
+40    set_bit(5, &word); 
+41    pr_info("Bits 1: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+42    clear_bit(5, &word); 
+43    pr_info("Bits 2: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+44    change_bit(3, &word); 
+45 
+46    pr_info("Bits 3: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+47    if (test_and_set_bit(3, &word)) 
+48        pr_info("wrong\n"); 
+49    pr_info("Bits 4: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+50 
+51    word = 255; 
+52    pr_info("Bits 5: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+53} 
+54 
+55static int example_atomic_init(void) 
+56{ 
+57    pr_info("example_atomic started\n"); 
+58 
+59    atomic_add_subtract(); 
+60    atomic_bitwise(); 
+61 
+62    return 0; 
+63} 
+64 
+65static void example_atomic_exit(void) 
+66{ 
+67    pr_info("example_atomic exit\n"); 
+68} 
+69 
+70module_init(example_atomic_init); 
+71module_exit(example_atomic_exit); 
+72 
+73MODULE_DESCRIPTION("Atomic operations example"); 
+74MODULE_LICENSE("GPL");
+ + + +

+

+

0.13 Replacing Print Macros

+

+

+

0.13.1 Replacement

+

In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s +true for developing kernel modules, but in actual use, you want to be able +to send messages to whichever tty the command to load the module came +from. +

"tty" is an abbreviation of teletype: originally a combination keyboard-printer +used to communicate with a Unix system, and today an abstraction for the text +stream used for a Unix program, whether it’s a physical terminal, an xterm on an X +display, a network connection used with ssh, etc. +

The way this is done is by using current, a pointer to the currently running task, +to get the current task’s tty structure. Then, we look inside that tty structure to find +a pointer to a string write function, which we use to write a string to the +tty. +

+

+
1/* 
+2 *  print_string.c - Send output to the tty we're running on, regardless if it's 
+3 *  through X11, telnet, etc.  We do this by printing the string to the tty 
+4 *  associated with the current task. 
+5 */ 
+6#include <linux/init.h> 
+7#include <linux/kernel.h> 
+8#include <linux/module.h> 
+9#include <linux/sched.h> /* For current */ 
+10#include <linux/tty.h>   /* For the tty declarations */ 
+11 
+12MODULE_LICENSE("GPL"); 
+13 
+14static void print_string(char *str) 
+15{ 
+16    struct tty_struct *my_tty; 
+17    const struct tty_operations *ttyops; 
+18 
+19    /* 
+20     * The tty for the current task, for 2.6.6+ kernels 
+21     */ 
+22    my_tty = get_current_tty(); 
+23    ttyops = my_tty->driver->ops; 
+24 
+25    /* 
+26     * If my_tty is NULL, the current task has no tty you can print to 
+27     * (ie, if it's a daemon).  If so, there's nothing we can do. 
+28     */ 
+29    if (my_tty != NULL) { 
+30        /* 
+31         * my_tty->driver is a struct which holds the tty's functions, 
+32         * one of which (write) is used to write strings to the tty. 
+33         * It can be used to take a string either from the user's or 
+34         * kernel's memory segment. 
+35         * 
+36         * The function's 1st parameter is the tty to write to, 
+37         * because the same function would normally be used for all 
+38         * tty's of a certain type. 
+39         * The 2nd parameter is a pointer to a string. 
+40         * The 3rd parameter is the length of the string. 
+41         * 
+42         * As you will see below, sometimes it's necessary to use 
+43         * preprocessor stuff to create code that works for different 
+44         * kernel versions. The (naive) approach we've taken here 
+45         * does not scale well. The right way to deal with this 
+46         * is described in section 2 of 
+47         * linux/Documentation/SubmittingPatches 
+48         */ 
+49        (ttyops->write)(my_tty,       /* The tty itself */ 
+50                        str,          /* String                 */ 
+51                        strlen(str)); /* Length */ 
+52 
+53        /* 
+54         * ttys were originally hardware devices, which (usually) 
+55         * strictly followed the ASCII standard.  In ASCII, to move to 
+56         * a new line you need two characters, a carriage return and a 
+57         * line feed.  On Unix, the ASCII line feed is used for both 
+58         * purposes - so we can't just use \n, because it wouldn't have 
+59         * a carriage return and the next line will start at the 
+60         * column right after the line feed. 
+61         * 
+62         * This is why text files are different between Unix and 
+63         * MS Windows.  In CP/M and derivatives, like MS-DOS and 
+64         * MS Windows, the ASCII standard was strictly adhered to, 
+65         * and therefore a newline requirs both a LF and a CR. 
+66         */ 
+67        (ttyops->write)(my_tty, "\015\012", 2); 
+68    } 
+69} 
+70 
+71static int __init print_string_init(void) 
+72{ 
+73    print_string("The module has been inserted.  Hello world!"); 
+74    return 0; 
+75} 
+76 
+77static void __exit print_string_exit(void) 
+78{ 
+79    print_string("The module has been removed.  Farewell world!"); 
+80} 
+81 
+82module_init(print_string_init); 
+83module_exit(print_string_exit);
+

+

+

0.13.2 Flashing keyboard LEDs

+

In certain conditions, you may desire a simpler and more direct way to communicate +to the external world. Flashing keyboard LEDs can be such a solution: It is an +immediate way to attract attention or to display a status condition. Keyboard LEDs +are present on every hardware, they are always visible, they do not need any setup, +and their use is rather simple and non-intrusive, compared to writing to a tty or a +file. +

The following source code illustrates a minimal kernel module which, when +loaded, starts blinking the keyboard LEDs until it is unloaded. +

+

+
1/* 
+2 *  kbleds.c - Blink keyboard leds until the module is unloaded. 
+3 */ 
+4 
+5#include <linux/init.h> 
+6#include <linux/kd.h> /* For KDSETLED */ 
+7#include <linux/module.h> 
+8#include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */ 
+9#include <linux/vt.h> 
+10#include <linux/vt_kern.h> /* for fg_console */ 
+11 
+12#include <linux/console_struct.h> /* For vc_cons */ 
+13 
+14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
+15MODULE_LICENSE("GPL"); 
+16 
+17struct timer_list my_timer; 
+18struct tty_driver *my_driver; 
+19char kbledstatus = 0; 
+20 
+21#define BLINK_DELAY HZ / 5 
+22#define ALL_LEDS_ON 0x07 
+23#define RESTORE_LEDS 0xFF 
+24 
+25/* 
+26 * Function my_timer_func blinks the keyboard LEDs periodically by invoking 
+27 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
+28 * terminal ioctl operations, please see file: 
+29 *     /usr/src/linux/drivers/char/vt_ioctl.c, function vt_ioctl(). 
+30 * 
+31 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
+32 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
+33 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
+34 * the LEDs reflect the actual keyboard status).  To learn more on this, 
+35 * please see file: 
+36 *     /usr/src/linux/drivers/char/keyboard.c, function setledstate(). 
+37 * 
+38 */ 
+39 
+40static void my_timer_func(unsigned long ptr) 
+41{ 
+42    unsigned long *pstatus = (unsigned long *) ptr; 
+43    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
+44 
+45    if (*pstatus == ALL_LEDS_ON) 
+46        *pstatus = RESTORE_LEDS; 
+47    else 
+48        *pstatus = ALL_LEDS_ON; 
+49 
+50    (my_driver->ops->ioctl)(t, KDSETLED, *pstatus); 
+51 
+52    my_timer.expires = jiffies + BLINK_DELAY; 
+53    add_timer(&my_timer); 
+54} 
+55 
+56static int __init kbleds_init(void) 
+57{ 
+58    int i; 
+59 
+60    pr_info("kbleds: loading\n"); 
+61    pr_info("kbleds: fgconsole is %x\n", fg_console); 
+62    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
+63        if (!vc_cons[i].d) 
+64            break; 
+65        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
+66                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
+67    } 
+68    pr_info("kbleds: finished scanning consoles\n"); 
+69 
+70    my_driver = vc_cons[fg_console].d->port.tty->driver; 
+71    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
+72 
+73    /* 
+74     * Set up the LED blink timer the first time 
+75     */ 
+76    timer_setup(&my_timer, (void *) &my_timer_func, 
+77                (unsigned long) &kbledstatus); 
+78    my_timer.expires = jiffies + BLINK_DELAY; 
+79    add_timer(&my_timer); 
+80 
+81    return 0; 
+82} 
+83 
+84static void __exit kbleds_cleanup(void) 
+85{ 
+86    pr_info("kbleds: unloading...\n"); 
+87    del_timer(&my_timer); 
+88    (my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, 
+89                            RESTORE_LEDS); 
+90} 
+91 
+92module_init(kbleds_init); 
+93module_exit(kbleds_cleanup);
+

If none of the examples in this chapter fit your debugging needs there might yet +be some other tricks to try. Ever wondered what CONFIG_LL_DEBUG in +make menuconfig is good for? If you activate that you get low level access +to the serial port. While this might not sound very powerful by itself, you + + + +can patch kernel/printk.c or any other essential syscall to use printascii, +thus makeing it possible to trace virtually everything what your code does +over a serial line. If you find yourself porting the kernel to some new and +former unsupported architecture this is usually amongst the first things that +should be implemented. Logging over a netconsole might also be worth a +try. +

While you have seen lots of stuff that can be used to aid debugging here, there are +some things to be aware of. Debugging is almost always intrusive. Adding debug code +can change the situation enough to make the bug seem to dissappear. Thus you +should try to keep debug code to a minimum and make sure it does not show up in +production code. +

+

+

0.14 Scheduling Tasks

+

There are two main ways of running tasks: tasklets and work queues. Tasklets are a +quick and easy way of scheduling a single function to be run, for example when +triggered from an interrupt, whereas work queues are more complicated but also +better suited to running multiple things in a sequence. +

+

+

0.14.1 Tasklets

+

Here’s an example tasklet module. The tasklet_fn function runs for a few seconds +and in the mean time execution of the example_tasklet_init function continues to +the exit point. +

+

+
1/* 
+2 *  example_tasklet.c 
+3 */ 
+4#include <linux/delay.h> 
+5#include <linux/interrupt.h> 
+6#include <linux/kernel.h> 
+7#include <linux/module.h> 
+8 
+9static void tasklet_fn(unsigned long data) 
+10{ 
+11    pr_info("Example tasklet starts\n"); 
+12    mdelay(5000); 
+13    pr_info("Example tasklet ends\n"); 
+14} 
+15 
+16DECLARE_TASKLET(mytask, tasklet_fn, 0L); 
+17 
+18static int example_tasklet_init(void) 
+19{ 
+20    pr_info("tasklet example init\n"); 
+21    tasklet_schedule(&mytask); 
+22    mdelay(200); 
+23    pr_info("Example tasklet init continues...\n"); 
+24    return 0; 
+25} 
+26 
+27static void example_tasklet_exit(void) 
+28{ 
+29    pr_info("tasklet example exit\n"); 
+30    tasklet_kill(&mytask); 
+31} 
+32 
+33module_init(example_tasklet_init); 
+34module_exit(example_tasklet_exit); 
+35 
+36MODULE_DESCRIPTION("Tasklet example"); 
+37MODULE_LICENSE("GPL");
+

So with this example loaded dmesg should show: + + + +

+
+tasklet example init
+Example tasklet starts
+Example tasklet init continues...
+Example tasklet ends
+
+

+

+

+

0.14.2 Work queues

+

To add a task to the scheduler we can use a workqueue. The kernel then uses the +Completely Fair Scheduler (CFS) to execute work within the queue. +

+

+
1/* 
+2 *  sched.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/module.h> 
+6#include <linux/workqueue.h> 
+7 
+8static struct workqueue_struct *queue = NULL; 
+9static struct work_struct work; 
+10 
+11static void work_handler(struct work_struct *data) 
+12{ 
+13    pr_info("work handler function.\n"); 
+14} 
+15 
+16int init_module() 
+17{ 
+18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
+19    INIT_WORK(&work, work_handler); 
+20    schedule_work(&work); 
+21 
+22    return 0; 
+23} 
+24 
+25void cleanup_module() 
+26{ 
+27    destroy_workqueue(queue); 
+28} 
+29 
+30MODULE_LICENSE("GPL"); 
+31MODULE_DESCRIPTION("Workqueue example");
+

+

+

0.15 Interrupt Handlers

+

+

+

0.15.1 Interrupt Handlers

+

Except for the last chapter, everything we did in the kernel so far we’ve done as a +response to a process asking for it, either by dealing with a special file, sending an +ioctl(), or issuing a system call. But the job of the kernel isn’t just to respond to +process requests. Another job, which is every bit as important, is to speak to the +hardware connected to the machine. +

There are two types of interaction between the CPU and the rest of the +computer’s hardware. The first type is when the CPU gives orders to the hardware, +the other is when the hardware needs to tell the CPU something. The second, called +interrupts, is much harder to implement because it has to be dealt with when +convenient for the hardware, not the CPU. Hardware devices typically have a very +small amount of RAM, and if you don’t read their information when available, it is +lost. + + + +

Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There +are two types of IRQ’s, short and long. A short IRQ is one which is expected to take +a very short period of time, during which the rest of the machine will be blocked and +no other interrupts will be handled. A long IRQ is one which can take longer, and +during which other interrupts may occur (but not interrupts from the same +device). If at all possible, it’s better to declare an interrupt handler to be +long. +

When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s +processing a more important interrupt, in which case it will deal with this one +only when the more important one is done), saves certain parameters on +the stack and calls the interrupt handler. This means that certain things +are not allowed in the interrupt handler itself, because the system is in an +unknown state. The solution to this problem is for the interrupt handler to +do what needs to be done immediately, usually read something from the +hardware or send something to the hardware, and then schedule the handling of +the new information at a later time (this is called the "bottom half") and +return. The kernel is then guaranteed to call the bottom half as soon as +possible – and when it does, everything allowed in kernel modules will be +allowed. +

The way to implement this is to call request_irq() to get your interrupt handler +called when the relevant IRQ is received. +

In practice IRQ handling can be a bit more complex. Hardware is often +designed in a way that chains two interrupt controllers, so that all the IRQs +from interrupt controller B are cascaded to a certain IRQ from interrupt +controller A. Of course that requires that the kernel finds out which IRQ it +really was afterwards and that adds overhead. Other architectures offer some +special, very low overhead, so called "fast IRQ" or FIQs. To take advantage of +them requires handlers to be written in assembler, so they do not really fit +into the kernel. They can be made to work similar to the others, but after +that procedure, they’re no longer any faster than "common" IRQs. SMP +enabled kernels running on systems with more than one processor need to solve +another truckload of problems. It’s not enough to know if a certain IRQs +has happend, it’s also important for what CPU(s) it was for. People still +interested in more details, might want to do a web search for "APIC" now +;) +

This function receives the IRQ number, the name of the function, flags, a name +for /proc/interrupts and a parameter to pass to the interrupt handler. Usually +there is a certain number of IRQs available. How many IRQs there are is +hardware-dependent. The flags can include SA_SHIRQ to indicate you’re willing to +share the IRQ with other interrupt handlers (usually because a number of hardware +devices sit on the same IRQ) and SA_INTERRUPT to indicate this is a fast +interrupt. This function will only succeed if there isn’t already a handler on this IRQ, +or if you’re both willing to share. + + + +

+

+

0.15.2 Detecting button presses

+

Many popular single board computers, such as Raspberry Pis or Beagleboards, have +a bunch of GPIO pins. Attaching buttons to those and then having a button press do +something is a classic case in which you might need to use interrupts so that instead +of having the CPU waste time and battery power polling for a change in input state +it’s better for the input to trigger the CPU to then run a particular handling +function. +

Here’s an example where buttons are connected to GPIO numbers 17 and 18 and +an LED is connected to GPIO 4. You can change those numbers to whatever is +appropriate for your board. +

+

+
1/* 
+2 *  intrpt.c - Handling GPIO with interrupts 
+3 * 
+4 *  Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de) 
+5 *  from: 
+6 *    https://github.com/wendlers/rpi-kmod-samples 
+7 * 
+8 *  Press one button to turn on a LED and another to turn it off 
+9 */ 
+10 
+11#include <linux/gpio.h> 
+12#include <linux/interrupt.h> 
+13#include <linux/kernel.h> 
+14#include <linux/module.h> 
+15 
+16static int button_irqs[] = {-1, -1}; 
+17 
+18/* Define GPIOs for LEDs. 
+19   Change the numbers for the GPIO on your board. */ 
+20static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+21 
+22/* Define GPIOs for BUTTONS 
+23   Change the numbers for the GPIO on your board. */ 
+24static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+25                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+26 
+27/* 
+28 * interrupt function triggered when a button is pressed 
+29 */ 
+30static irqreturn_t button_isr(int irq, void *data) 
+31{ 
+32    /* first button */ 
+33    if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio)) 
+34        gpio_set_value(leds[0].gpio, 1); 
+35    /* second button */ 
+36    else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio)) 
+37        gpio_set_value(leds[0].gpio, 0); 
+38 
+39    return IRQ_HANDLED; 
+40} 
+41 
+42int init_module() 
+43{ 
+44    int ret = 0; 
+45 
+46    pr_info("%s\n", __func__); 
+47 
+48    /* register LED gpios */ 
+49    ret = gpio_request_array(leds, ARRAY_SIZE(leds)); 
+50 
+51    if (ret) { 
+52        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+53        return ret; 
+54    } 
+55 
+56    /* register BUTTON gpios */ 
+57    ret = gpio_request_array(buttons, ARRAY_SIZE(buttons)); 
+58 
+59    if (ret) { 
+60        pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret); 
+61        goto fail1; 
+62    } 
+63 
+64    pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio)); 
+65 
+66    ret = gpio_to_irq(buttons[0].gpio); 
+67 
+68    if (ret < 0) { 
+69        pr_err("Unable to request IRQ: %d\n", ret); 
+70        goto fail2; 
+71    } 
+72 
+73    button_irqs[0] = ret; 
+74 
+75    pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]); 
+76 
+77    ret = request_irq(button_irqs[0], button_isr, 
+78                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+79                      "gpiomod#button1", NULL); 
+80 
+81    if (ret) { 
+82        pr_err("Unable to request IRQ: %d\n", ret); 
+83        goto fail2; 
+84    } 
+85 
+86 
+87    ret = gpio_to_irq(buttons[1].gpio); 
+88 
+89    if (ret < 0) { 
+90        pr_err("Unable to request IRQ: %d\n", ret); 
+91        goto fail2; 
+92    } 
+93 
+94    button_irqs[1] = ret; 
+95 
+96    pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]); 
+97 
+98    ret = request_irq(button_irqs[1], button_isr, 
+99                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+100                      "gpiomod#button2", NULL); 
+101 
+102    if (ret) { 
+103        pr_err("Unable to request IRQ: %d\n", ret); 
+104        goto fail3; 
+105    } 
+106 
+107    return 0; 
+108 
+109/* cleanup what has been setup so far */ 
+110fail3: 
+111    free_irq(button_irqs[0], NULL); 
+112 
+113fail2: 
+114    gpio_free_array(buttons, ARRAY_SIZE(leds)); 
+115 
+116fail1: 
+117    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+118 
+119    return ret; 
+120} 
+121 
+122void cleanup_module() 
+123{ 
+124    int i; 
+125 
+126    pr_info("%s\n", __func__); 
+127 
+128    /* free irqs */ 
+129    free_irq(button_irqs[0], NULL); 
+130    free_irq(button_irqs[1], NULL); 
+131 
+132    /* turn all LEDs off */ 
+133    for (i = 0; i < ARRAY_SIZE(leds); i++) 
+134        gpio_set_value(leds[i].gpio, 0); 
+135 
+136    /* unregister */ 
+137    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+138    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
+139} 
+140 
+141MODULE_LICENSE("GPL"); 
+142MODULE_DESCRIPTION("Handle some GPIO interrupts");
+

+

+

0.15.3 Bottom Half

+

Suppose you want to do a bunch of stuff inside of an interrupt routine. A common +way to do that without rendering the interrupt unavailable for a significant duration +is to combine it with a tasklet. This pushes the bulk of the work off into the +scheduler. +

The example below modifies the previous example to also run an additional task +when an interrupt is triggered. +

+

+
1/* 
+2 * bottomhalf.c - Top and bottom half interrupt handling 
+3 * 
+4 * Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de) 
+5 * from: 
+6 *    https://github.com/wendlers/rpi-kmod-samples 
+7 * 
+8 *  Press one button to turn on a LED and another to turn it off 
+9 */ 
+10 
+11#include <linux/delay.h> 
+12#include <linux/gpio.h> 
+13#include <linux/interrupt.h> 
+14#include <linux/kernel.h> 
+15#include <linux/module.h> 
+16 
+17static int button_irqs[] = {-1, -1}; 
+18 
+19/* Define GPIOs for LEDs. 
+20   Change the numbers for the GPIO on your board. */ 
+21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+22 
+23/* Define GPIOs for BUTTONS 
+24   Change the numbers for the GPIO on your board. */ 
+25static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+26                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+27 
+28/* Tasklet containing some non-trivial amount of processing */ 
+29static void bottomhalf_tasklet_fn(unsigned long data) 
+30{ 
+31    pr_info("Bottom half tasklet starts\n"); 
+32    /* do something which takes a while */ 
+33    mdelay(500); 
+34    pr_info("Bottom half tasklet ends\n"); 
+35} 
+36 
+37DECLARE_TASKLET(buttontask, bottomhalf_tasklet_fn, 0L); 
+38 
+39/* 
+40 * interrupt function triggered when a button is pressed 
+41 */ 
+42static irqreturn_t button_isr(int irq, void *data) 
+43{ 
+44    /* Do something quickly right now */ 
+45    if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio)) 
+46        gpio_set_value(leds[0].gpio, 1); 
+47    else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio)) 
+48        gpio_set_value(leds[0].gpio, 0); 
+49 
+50    /* Do the rest at leisure via the scheduler */ 
+51    tasklet_schedule(&buttontask); 
+52 
+53    return IRQ_HANDLED; 
+54} 
+55 
+56int init_module() 
+57{ 
+58    int ret = 0; 
+59 
+60    pr_info("%s\n", __func__); 
+61 
+62    /* register LED gpios */ 
+63    ret = gpio_request_array(leds, ARRAY_SIZE(leds)); 
+64 
+65    if (ret) { 
+66        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+67        return ret; 
+68    } 
+69 
+70    /* register BUTTON gpios */ 
+71    ret = gpio_request_array(buttons, ARRAY_SIZE(buttons)); 
+72 
+73    if (ret) { 
+74        pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret); 
+75        goto fail1; 
+76    } 
+77 
+78    pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio)); 
+79 
+80    ret = gpio_to_irq(buttons[0].gpio); 
+81 
+82    if (ret < 0) { 
+83        pr_err("Unable to request IRQ: %d\n", ret); 
+84        goto fail2; 
+85    } 
+86 
+87    button_irqs[0] = ret; 
+88 
+89    pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]); 
+90 
+91    ret = request_irq(button_irqs[0], button_isr, 
+92                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+93                      "gpiomod#button1", NULL); 
+94 
+95    if (ret) { 
+96        pr_err("Unable to request IRQ: %d\n", ret); 
+97        goto fail2; 
+98    } 
+99 
+100 
+101    ret = gpio_to_irq(buttons[1].gpio); 
+102 
+103    if (ret < 0) { 
+104        pr_err("Unable to request IRQ: %d\n", ret); 
+105        goto fail2; 
+106    } 
+107 
+108    button_irqs[1] = ret; 
+109 
+110    pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]); 
+111 
+112    ret = request_irq(button_irqs[1], button_isr, 
+113                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+114                      "gpiomod#button2", NULL); 
+115 
+116    if (ret) { 
+117        pr_err("Unable to request IRQ: %d\n", ret); 
+118        goto fail3; 
+119    } 
+120 
+121    return 0; 
+122 
+123/* cleanup what has been setup so far */ 
+124fail3: 
+125    free_irq(button_irqs[0], NULL); 
+126 
+127fail2: 
+128    gpio_free_array(buttons, ARRAY_SIZE(leds)); 
+129 
+130fail1: 
+131    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+132 
+133    return ret; 
+134} 
+135 
+136void cleanup_module() 
+137{ 
+138    int i; 
+139 
+140    pr_info("%s\n", __func__); 
+141 
+142    /* free irqs */ 
+143    free_irq(button_irqs[0], NULL); 
+144    free_irq(button_irqs[1], NULL); 
+145 
+146    /* turn all LEDs off */ 
+147    for (i = 0; i < ARRAY_SIZE(leds); i++) 
+148        gpio_set_value(leds[i].gpio, 0); 
+149 
+150    /* unregister */ 
+151    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+152    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
+153} 
+154 
+155MODULE_LICENSE("GPL"); 
+156MODULE_DESCRIPTION("Interrupt with top and bottom half");
+

+

+

0.16 Crypto

+

At the dawn of the internet everybody trusted everybody completely…but that didn’t +work out so well. When this guide was originally written it was a more innocent era +in which almost nobody actually gave a damn about crypto - least of all kernel +developers. That’s certainly no longer the case now. To handle crypto stuff the kernel +has its own API enabling common methods of encryption, decryption and your +favourite hash functions. + + + +

+

+

0.16.1 Hash functions

+

Calculating and checking the hashes of things is a common operation. Here is a +demonstration of how to calculate a sha256 hash within a kernel module. +

+

+
1/* 
+2 *  cryptosha256.c 
+3 */ 
+4#include <crypto/internal/hash.h> 
+5#include <linux/module.h> 
+6 
+7#define SHA256_LENGTH 32 
+8 
+9static void show_hash_result(char *plaintext, char *hash_sha256) 
+10{ 
+11    int i; 
+12    char str[SHA256_LENGTH * 2 + 1]; 
+13 
+14    pr_info("sha256 test for string: \"%s\"\n", plaintext); 
+15    for (i = 0; i < SHA256_LENGTH; i++) 
+16        sprintf(&str[i * 2], "%02x", (unsigned char) hash_sha256[i]); 
+17    str[i * 2] = 0; 
+18    pr_info("%s\n", str); 
+19} 
+20 
+21int cryptosha256_init(void) 
+22{ 
+23    char *plaintext = "This is a test"; 
+24    char hash_sha256[SHA256_LENGTH]; 
+25    struct crypto_shash *sha256; 
+26    struct shash_desc *shash; 
+27 
+28    sha256 = crypto_alloc_shash("sha256", 0, 0); 
+29    if (IS_ERR(sha256)) 
+30        return -1; 
+31 
+32    shash = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(sha256), 
+33                    GFP_KERNEL); 
+34    if (!shash) 
+35        return -ENOMEM; 
+36 
+37    shash->tfm = sha256; 
+38 
+39    if (crypto_shash_init(shash)) 
+40        return -1; 
+41 
+42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
+43        return -1; 
+44 
+45    if (crypto_shash_final(shash, hash_sha256)) 
+46        return -1; 
+47 
+48    kfree(shash); 
+49    crypto_free_shash(sha256); 
+50 
+51    show_hash_result(plaintext, hash_sha256); 
+52 
+53    return 0; 
+54} 
+55 
+56void cryptosha256_exit(void) {} 
+57 
+58module_init(cryptosha256_init); 
+59module_exit(cryptosha256_exit); 
+60 
+61MODULE_DESCRIPTION("sha256 hash test"); 
+62MODULE_LICENSE("GPL");
+

Make and install the module: +

+

+
1make 
+2sudo insmod cryptosha256.ko 
+3dmesg
+

And you should see that the hash was calculated for the test string. +

Finally, remove the test module: +

+

+
1sudo rmmod cryptosha256
+

+

+

0.16.2 Symmetric key encryption

+

Here is an example of symmetrically encrypting a string using the AES algorithm +and a password. +

+

+
1/* 
+2 *  cryptosk.c 
+3 */ 
+4#include <crypto/internal/skcipher.h> 
+5#include <linux/crypto.h> 
+6#include <linux/module.h> 
+7 
+8#define SYMMETRIC_KEY_LENGTH 32 
+9#define CIPHER_BLOCK_SIZE 16 
+10 
+11struct tcrypt_result { 
+12    struct completion completion; 
+13    int err; 
+14}; 
+15 
+16struct skcipher_def { 
+17    struct scatterlist sg; 
+18    struct crypto_skcipher *tfm; 
+19    struct skcipher_request *req; 
+20    struct tcrypt_result result; 
+21    char *scratchpad; 
+22    char *ciphertext; 
+23    char *ivdata; 
+24}; 
+25 
+26static struct skcipher_def sk; 
+27 
+28static void test_skcipher_finish(struct skcipher_def *sk) 
+29{ 
+30    if (sk->tfm) 
+31        crypto_free_skcipher(sk->tfm); 
+32    if (sk->req) 
+33        skcipher_request_free(sk->req); 
+34    if (sk->ivdata) 
+35        kfree(sk->ivdata); 
+36    if (sk->scratchpad) 
+37        kfree(sk->scratchpad); 
+38    if (sk->ciphertext) 
+39        kfree(sk->ciphertext); 
+40} 
+41 
+42static int test_skcipher_result(struct skcipher_def *sk, int rc) 
+43{ 
+44    switch (rc) { 
+45    case 0: 
+46        break; 
+47    case -EINPROGRESS || -EBUSY: 
+48        rc = wait_for_completion_interruptible(&sk->result.completion); 
+49        if (!rc && !sk->result.err) { 
+50            reinit_completion(&sk->result.completion); 
+51            break; 
+52        } 
+53        pr_info("skcipher encrypt returned with %d result %d\n", rc, 
+54                sk->result.err); 
+55        break; 
+56    default: 
+57        pr_info("skcipher encrypt returned with %d result %d\n", rc, 
+58                sk->result.err); 
+59        break; 
+60    } 
+61 
+62    init_completion(&sk->result.completion); 
+63 
+64    return rc; 
+65} 
+66 
+67static void test_skcipher_callback(struct crypto_async_request *req, int error) 
+68{ 
+69    struct tcrypt_result *result = req->data; 
+70    /* int ret; */ 
+71 
+72    if (error == -EINPROGRESS) 
+73        return; 
+74 
+75    result->err = error; 
+76    complete(&result->completion); 
+77    pr_info("Encryption finished successfully\n"); 
+78 
+79    /* decrypt data */ 
+80    /* 
+81    memset((void*)sk.scratchpad, '-', CIPHER_BLOCK_SIZE); 
+82    ret = crypto_skcipher_decrypt(sk.req); 
+83    ret = test_skcipher_result(&sk, ret); 
+84    if (ret) 
+85        return; 
+86 
+87    sg_copy_from_buffer(&sk.sg, 1, sk.scratchpad, CIPHER_BLOCK_SIZE); 
+88    sk.scratchpad[CIPHER_BLOCK_SIZE-1] = 0; 
+89 
+90    pr_info("Decryption request successful\n"); 
+91    pr_info("Decrypted: %s\n", sk.scratchpad); 
+92    */ 
+93} 
+94 
+95static int test_skcipher_encrypt(char *plaintext, 
+96                                 char *password, 
+97                                 struct skcipher_def *sk) 
+98{ 
+99    int ret = -EFAULT; 
+100    unsigned char key[SYMMETRIC_KEY_LENGTH]; 
+101 
+102    if (!sk->tfm) { 
+103        sk->tfm = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0); 
+104        if (IS_ERR(sk->tfm)) { 
+105            pr_info("could not allocate skcipher handle\n"); 
+106            return PTR_ERR(sk->tfm); 
+107        } 
+108    } 
+109 
+110    if (!sk->req) { 
+111        sk->req = skcipher_request_alloc(sk->tfm, GFP_KERNEL); 
+112        if (!sk->req) { 
+113            pr_info("could not allocate skcipher request\n"); 
+114            ret = -ENOMEM; 
+115            goto out; 
+116        } 
+117    } 
+118 
+119    skcipher_request_set_callback(sk->req, CRYPTO_TFM_REQ_MAY_BACKLOG, 
+120                                  test_skcipher_callback, &sk->result); 
+121 
+122    /* clear the key */ 
+123    memset((void *) key, '\0', SYMMETRIC_KEY_LENGTH); 
+124 
+125    /* Use the world's favourite password */ 
+126    sprintf((char *) key, "%s", password); 
+127 
+128    /* AES 256 with given symmetric key */ 
+129    if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) { 
+130        pr_info("key could not be set\n"); 
+131        ret = -EAGAIN; 
+132        goto out; 
+133    } 
+134    pr_info("Symmetric key: %s\n", key); 
+135    pr_info("Plaintext: %s\n", plaintext); 
+136 
+137    if (!sk->ivdata) { 
+138        /* see https://en.wikipedia.org/wiki/Initialization_vector */ 
+139        sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL); 
+140        if (!sk->ivdata) { 
+141            pr_info("could not allocate ivdata\n"); 
+142            goto out; 
+143        } 
+144        get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE); 
+145    } 
+146 
+147    if (!sk->scratchpad) { 
+148        /* The text to be encrypted */ 
+149        sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL); 
+150        if (!sk->scratchpad) { 
+151            pr_info("could not allocate scratchpad\n"); 
+152            goto out; 
+153        } 
+154    } 
+155    sprintf((char *) sk->scratchpad, "%s", plaintext); 
+156 
+157    sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE); 
+158    skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg, CIPHER_BLOCK_SIZE, 
+159                               sk->ivdata); 
+160    init_completion(&sk->result.completion); 
+161 
+162    /* encrypt data */ 
+163    ret = crypto_skcipher_encrypt(sk->req); 
+164    ret = test_skcipher_result(sk, ret); 
+165    if (ret) 
+166        goto out; 
+167 
+168    pr_info("Encryption request successful\n"); 
+169 
+170out: 
+171    return ret; 
+172} 
+173 
+174int cryptoapi_init(void) 
+175{ 
+176    /* The world's favorite password */ 
+177    char *password = "password123"; 
+178 
+179    sk.tfm = NULL; 
+180    sk.req = NULL; 
+181    sk.scratchpad = NULL; 
+182    sk.ciphertext = NULL; 
+183    sk.ivdata = NULL; 
+184 
+185    test_skcipher_encrypt("Testing", password, &sk); 
+186    return 0; 
+187} 
+188 
+189void cryptoapi_exit(void) 
+190{ 
+191    test_skcipher_finish(&sk); 
+192} 
+193 
+194module_init(cryptoapi_init); 
+195module_exit(cryptoapi_exit); 
+196 
+197MODULE_DESCRIPTION("Symmetric key encryption example"); 
+198MODULE_LICENSE("GPL");
+

+

+

0.17 Standardising the interfaces: The Device Model

+

Up to this point we’ve seen all kinds of modules doing all kinds of things, but there +was no consistency in their interfaces with the rest of the kernel. To impose some +consistency such that there is at minimum a standardised way to start, suspend and +resume a device a device model was added. An example is show below, and you can +use this as a template to add your own suspend, resume or other interface +functions. +

+

+
1/* 
+2 *  devicemodel.c 
+3 */ 
+4#include <linux/kernel.h> 
+5#include <linux/module.h> 
+6#include <linux/platform_device.h> 
+7 
+8struct devicemodel_data { 
+9    char *greeting; 
+10    int number; 
+11}; 
+12 
+13static int devicemodel_probe(struct platform_device *dev) 
+14{ 
+15    struct devicemodel_data *pd = 
+16        (struct devicemodel_data *) (dev->dev.platform_data); 
+17 
+18    pr_info("devicemodel probe\n"); 
+19    pr_info("devicemodel greeting: %s; %d\n", pd->greeting, pd->number); 
+20 
+21    /* Your device initialisation code */ 
+22 
+23    return 0; 
+24} 
+25 
+26static int devicemodel_remove(struct platform_device *dev) 
+27{ 
+28    pr_info("devicemodel example removed\n"); 
+29 
+30    /* Your device removal code */ 
+31 
+32    return 0; 
+33} 
+34 
+35static int devicemodel_suspend(struct device *dev) 
+36{ 
+37    pr_info("devicemodel example suspend\n"); 
+38 
+39    /* Your device suspend code */ 
+40 
+41    return 0; 
+42} 
+43 
+44static int devicemodel_resume(struct device *dev) 
+45{ 
+46    pr_info("devicemodel example resume\n"); 
+47 
+48    /* Your device resume code */ 
+49 
+50    return 0; 
+51} 
+52 
+53static const struct dev_pm_ops devicemodel_pm_ops = { 
+54    .suspend = devicemodel_suspend, 
+55    .resume = devicemodel_resume, 
+56    .poweroff = devicemodel_suspend, 
+57    .freeze = devicemodel_suspend, 
+58    .thaw = devicemodel_resume, 
+59    .restore = devicemodel_resume, 
+60}; 
+61 
+62static struct platform_driver devicemodel_driver = { 
+63    .driver = 
+64        { 
+65            .name = "devicemodel_example", 
+66            .owner = THIS_MODULE, 
+67            .pm = &devicemodel_pm_ops, 
+68        }, 
+69    .probe = devicemodel_probe, 
+70    .remove = devicemodel_remove, 
+71}; 
+72 
+73static int devicemodel_init(void) 
+74{ 
+75    int ret; 
+76 
+77    pr_info("devicemodel init\n"); 
+78 
+79    ret = platform_driver_register(&devicemodel_driver); 
+80 
+81    if (ret) { 
+82        pr_err("Unable to register driver\n"); 
+83        return ret; 
+84    } 
+85 
+86    return 0; 
+87} 
+88 
+89static void devicemodel_exit(void) 
+90{ 
+91    pr_info("devicemodel exit\n"); 
+92    platform_driver_unregister(&devicemodel_driver); 
+93} 
+94 
+95MODULE_LICENSE("GPL"); 
+96MODULE_DESCRIPTION("Linux Device Model example"); 
+97 
+98module_init(devicemodel_init); 
+99module_exit(devicemodel_exit);
+ + + +

+

+

0.18 Optimizations

+

+

+

0.18.1 Likely and Unlikely conditions

+

Sometimes you might want your code to run as quickly as possible, especially if +it’s handling an interrupt or doing something which might cause noticible +latency. If your code contains boolean conditions and if you know that the +conditions are almost always likely to evaluate as either true or false, then +you can allow the compiler to optimise for this using the likely and unlikely +macros. +

For example, when allocating memory you’re almost always expecting this to +succeed. +

+

+
1bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx); 
+2if (unlikely(!bvl)) { 
+3  mempool_free(bio, bio_pool); 
+4  bio = NULL; 
+5  goto out; 
+6}
+

When the unlikely macro is used the compiler alters its machine instruction +output so that it continues along the false branch and only jumps if the condition is +true. That avoids flushing the processor pipeline. The opposite happens if you use the +likely macro. +

+

0.19 Common Pitfalls

+

Before I send you on your way to go out into the world and write kernel modules, +there are a few things I need to warn you about. If I fail to warn you and something +bad happens, please report the problem to me for a full refund of the amount I was +paid for your copy of the book. +

+

+

0.19.1 Using standard libraries

+

You can’t do that. In a kernel module you can only use kernel functions, which are +the functions you can see in /proc/kallsyms. +

+

+ + + +

0.19.2 Disabling interrupts

+

You might need to do this for a short time and that is OK, but if you don’t +enable them afterwards, your system will be stuck and you’ll have to power it +off. +

+

+

0.19.3 Sticking your head inside a large carnivore

+

I probably don’t have to warn you about this, but I figured I will anyway, just in +case. +

+

+

0.20 Where To Go From Here?

+

I could easily have squeezed a few more chapters into this book. I could have added a +chapter about creating new file systems, or about adding new protocol stacks (as if +there’s a need for that – you’d have to dig underground to find a protocol stack +not supported by Linux). I could have added explanations of the kernel +mechanisms we haven’t touched upon, such as bootstrapping or the disk +interface. +

However, I chose not to. My purpose in writing this book was to provide initiation +into the mysteries of kernel module programming and to teach the common +techniques for that purpose. For people seriously interested in kernel programming, I +recommend kernelnewbies.org and the Documentation subdirectory within the kernel +source code which isn’t always easy to understand but can be a starting point for +further investigation. Also, as Linus said, the best way to learn the kernel is to read +the source code yourself. +

If you’re interested in more examples of short kernel modules then searching on +sites such as Github and Gitlab is a good way to start, although there is a lot of +duplication of older LKMPG examples which may not compile with newer kernel +versions. You will also be able to find examples of the use of kernel modules to attack +or compromise systems or exfiltrate data and those can be useful for thinking about +how to defend systems and learning about existing security mechanisms within the +kernel. +

I hope I have helped you in your quest to become a better programmer, or at +least to have fun through technology. And, if you do write useful kernel modules, I +hope you publish them under the GPL, so I can use them too. +

If you’d like to contribute to this guide or notice anything glaringly wrong, please +create an issue at https://github.com/sysprog21/lkmpg. +

Happy hacking. +

+ + + \ No newline at end of file diff --git a/lkmpg.css b/lkmpg.css new file mode 100644 index 0000000..ecebe56 --- /dev/null +++ b/lkmpg.css @@ -0,0 +1,3454 @@ + +/* start css.sty */ +.cmr-7{font-size:70%;} +.cmmi-10{font-style: italic;} +.ecrm-1728{font-size:170%;} +.ecrm-1200{font-size:120%;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ectt-1000{ font-family: monospace,monospace;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecrm-0500{font-size:50%;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.ecbx-1000{ font-weight: bold;} +.tctt-1000{font-family: monospace,monospace;} +.tctt-1000{font-family: monospace,monospace;} +.ectt-0800{font-size:80%; font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.ectt-0800{ font-family: monospace,monospace;} +.tctt-0800{font-size:80%;font-family: monospace,monospace;} +.tctt-0800{font-family: monospace,monospace;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +.ecbi-1000{ font-weight: bold; font-style: italic;} +p{margin-top:0;margin-bottom:0} +p.indent{text-indent:0;} +p + p{margin-top:1em;} +p + div, p + pre {margin-top:1em;} +div + p, pre + p {margin-top:1em;} +a { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; hyphens: auto; } +@media print {div.crosslinks {visibility:hidden;}} +a img { border-top: 0; border-left: 0; border-right: 0; } +center { margin-top:1em; margin-bottom:1em; } +td center { margin-top:0em; margin-bottom:0em; } +.Canvas { position:relative; } +img.math{vertical-align:middle;} +div.par-math-display, div.math-display{text-align:center;} +li p.indent { text-indent: 0em } +li p:first-child{ margin-top:0em; } +li p:first-child{ margin-bottom; } +li p:last-child, li div:last-child { margin-bottom:0.5em; } +li p:first-child{ margin-bottom:0; } +li p~ul:last-child, li p~ol:last-child{ margin-bottom:0.5em; } +.enumerate1 {list-style-type:decimal;} +.enumerate2 {list-style-type:lower-alpha;} +.enumerate3 {list-style-type:lower-roman;} +.enumerate4 {list-style-type:upper-alpha;} +div.newtheorem { margin-bottom: 2em; margin-top: 2em;} +.obeylines-h,.obeylines-v {white-space: nowrap; } +div.obeylines-v p { margin-top:0; margin-bottom:0; } +.overline{ text-decoration:overline; } +.overline img{ border-top: 1px solid black; } +td.displaylines {text-align:center; white-space:nowrap;} +.centerline {text-align:center;} +.rightline {text-align:right;} +pre.verbatim {font-family: monospace,monospace; text-align:left; clear:both; } +.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +div.fbox {display:table} +div.center div.fbox {text-align:center; clear:both; padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +div.minipage{width:100%;} +div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;} +div.center div {text-align: left;} +div.flushright, div.flushright div.flushright {text-align: right;} +div.flushright div {text-align: left;} +div.flushleft {text-align: left;} +.underline{ text-decoration:underline; } +.underline img{ border-bottom: 1px solid black; margin-bottom:1pt; } +.framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +.framebox-c {text-align:center;} +.framebox-l {text-align:left;} +.framebox-r {text-align:right;} +span.thank-mark{ vertical-align: super } +span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript{ font-size:80%; } +div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; } +table.tabular td p{margin-top:0em;} +table.tabular {margin-left: auto; margin-right: auto;} +td p:first-child{ margin-top:0em; } +td p:last-child{ margin-bottom:0em; } +div.td00{ margin-left:0pt; margin-right:0pt; } +div.td01{ margin-left:0pt; margin-right:5pt; } +div.td10{ margin-left:5pt; margin-right:0pt; } +div.td11{ margin-left:5pt; margin-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +td.td00{ padding-left:0pt; padding-right:0pt; } +td.td01{ padding-left:0pt; padding-right:5pt; } +td.td10{ padding-left:5pt; padding-right:0pt; } +td.td11{ padding-left:5pt; padding-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +.hline hr, .cline hr{ height : 0px; margin:0px; } +.hline td, .cline td{ padding: 0; } +.hline hr, .cline hr{border:none;border-top:1px solid black;} +.tabbing-right {text-align:right;} +div.float, div.figure {margin-left: auto; margin-right: auto;} +div.float img {text-align:center;} +div.figure img {text-align:center;} +.marginpar,.reversemarginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;} +.marginpar p,.reversemarginpar p{margin-top:0.4em; margin-bottom:0.4em;} +.reversemarginpar{float:left;} +table.equation {width:100%;} +.equation td{text-align:center; } +td.equation { margin-top:1em; margin-bottom:1em; } +td.equation-label { width:5%; text-align:center; } +td.eqnarray4 { width:5%; white-space: normal; } +td.eqnarray2 { width:5%; } +table.eqnarray-star, table.eqnarray {width:100%;} +div.eqnarray{text-align:center;} +div.array {text-align:center;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +span.pmatrix img{vertical-align:middle;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +span.bar-css {text-decoration:overline;} +table.tabular{border-collapse: collapse; border-spacing: 0;} +img.cdots{vertical-align:middle;} +.partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;} +.chapterToc a, .chapterToc, .likechapterToc a, .likechapterToc, .appendixToc a, .appendixToc {line-height: 200%; font-weight:bold;} +.index-item, .index-subitem, .index-subsubitem {display:block} +div.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:left;} +div.caption span.id{font-weight: bold; white-space: nowrap; } +h1.partHead{text-align: center} +p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +.paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;} +.subparagraphHead, .likesubparagraphHead { font-weight: bold;} +.verse{white-space:nowrap; margin-left:2em} +div.maketitle {text-align:center;} +h2.titleHead{text-align:center;} +div.maketitle{ margin-bottom: 2em; } +div.author, div.date {text-align:center;} +div.thanks{text-align:left; margin-left:10%; font-size:85%; font-style:italic; } +div.author{white-space: nowrap;} +h1.partHead{text-align: center} + .chapterToc, .likechapterToc {margin-left:0em;} + .chapterToc ~ .likesectionToc, .chapterToc ~ .sectionToc, .likechapterToc ~ .likesectionToc, .likechapterToc ~ .sectionToc {margin-left:2em;} + .chapterToc ~ .likesectionToc ~ .likesubsectionToc, .chapterToc ~ .likesectionToc ~ .subsectionToc, .chapterToc ~ .sectionToc ~ .likesubsectionToc, .chapterToc ~ .sectionToc ~ .subsectionToc, .likechapterToc ~ .likesectionToc ~ .likesubsectionToc, .likechapterToc ~ .likesectionToc ~ .subsectionToc, .likechapterToc ~ .sectionToc ~ .likesubsectionToc, .likechapterToc ~ .sectionToc ~ .subsectionToc {margin-left:4em;} +.chapterToc ~ .likesectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .chapterToc ~ .likesectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .chapterToc ~ .likesectionToc ~ .subsectionToc ~ .likesubsubsectionToc, .chapterToc ~ .likesectionToc ~ .subsectionToc ~ .subsubsectionToc, .chapterToc ~ .sectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .chapterToc ~ .sectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .chapterToc ~ .sectionToc ~ .subsectionToc ~ .likesubsubsectionToc, .chapterToc ~ .sectionToc ~ .subsectionToc ~ .subsubsectionToc, .likechapterToc ~ .likesectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .likechapterToc ~ .likesectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .likechapterToc ~ .likesectionToc ~ .subsectionToc ~ .likesubsubsectionToc, .likechapterToc ~ .likesectionToc ~ .subsectionToc ~ .subsubsectionToc, .likechapterToc ~ .sectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .likechapterToc ~ .sectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .likechapterToc ~ .sectionToc ~ .subsectionToc ~ .likesubsubsectionToc .likechapterToc ~ .sectionToc ~ .subsectionToc ~ .subsubsectionToc {margin-left:6em;} + .likesectionToc , .sectionToc {margin-left:0em;} + .likesectionToc ~ .likesubsectionToc, .likesectionToc ~ .subsectionToc, .sectionToc ~ .likesubsectionToc, .sectionToc ~ .subsectionToc {margin-left:2em;} +.likesectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .likesectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .likesectionToc ~ .subsectionToc ~ .likesubsubsectionToc, .likesectionToc ~ .subsectionToc ~ .subsubsectionToc, .sectionToc ~ .likesubsectionToc ~ .likesubsubsectionToc, .sectionToc ~ .likesubsectionToc ~ .subsubsectionToc, .sectionToc ~ .subsectionToc ~ .likesubsubsectionToc, .sectionToc ~ .subsectionToc ~ .subsubsectionToc {margin-left:4em;} + .likesubsectionToc, .subsectionToc {margin-left:0em;} + .likesubsectionToc ~ .subsubsectionToc, .subsectionToc ~ .subsubsectionToc {margin-left:2em;} +figure.float, div.figure {margin-left: auto; margin-right: auto;} +figure.float img, figure.figure img {display: block; margin-left: auto; margin-right: auto;} +figure.figure {text-align:center;} +figcaption.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:center;} +figcaption.caption span.id{font-weight: bold; white-space: nowrap; } +p + figcaption, img + figcaption{margin-top: 1em;} +.rotatebox{display: inline-block;} +div.verbatiminput {font-family: monospace,monospace; white-space: nowrap; } +pre.fancyvrb {white-space: pre-wrap; margin:0em;font-family:monospace,monospace;} +.framedenv{border: 1px solid black;} +* :not(img) { max-width: 100%; width: 50vw; height: auto; margin: 0 auto; } +* { font-size: 1vw; } +.ecrm-0500 { font-size: 70%; font-style: italic; color: gray; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none; } +.ecrm-0500:after { content:" "; white-space: pre; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; user-select: none; } +pre#fancyvrb1{padding:5.69054pt;} +pre#fancyvrb1{ border-top: solid 0.4pt; } +pre#fancyvrb1{ border-left: solid 0.4pt; } +pre#fancyvrb1{ border-bottom: solid 0.4pt; } +pre#fancyvrb1{ border-right: solid 0.4pt; } +pre#fancyvrb2{padding:5.69054pt;} +pre#fancyvrb2{ border-top: solid 0.4pt; } +pre#fancyvrb2{ border-left: solid 0.4pt; } +pre#fancyvrb2{ border-bottom: solid 0.4pt; } +pre#fancyvrb2{ border-right: solid 0.4pt; } +pre#fancyvrb3{padding:5.69054pt;} +pre#fancyvrb3{ border-top: solid 0.4pt; } +pre#fancyvrb3{ border-left: solid 0.4pt; } +pre#fancyvrb3{ border-bottom: solid 0.4pt; } +pre#fancyvrb3{ border-right: solid 0.4pt; } +pre#fancyvrb4{padding:5.69054pt;} +pre#fancyvrb4{ border-top: solid 0.4pt; } +pre#fancyvrb4{ border-left: solid 0.4pt; } +pre#fancyvrb4{ border-bottom: solid 0.4pt; } +pre#fancyvrb4{ border-right: solid 0.4pt; } +pre#fancyvrb5{padding:5.69054pt;} +pre#fancyvrb5{ border-top: solid 0.4pt; } +pre#fancyvrb5{ border-left: solid 0.4pt; } +pre#fancyvrb5{ border-bottom: solid 0.4pt; } +pre#fancyvrb5{ border-right: solid 0.4pt; } +pre#fancyvrb6{padding:5.69054pt;} +pre#fancyvrb6{ border-top: solid 0.4pt; } +pre#fancyvrb6{ border-left: solid 0.4pt; } +pre#fancyvrb6{ border-bottom: solid 0.4pt; } +pre#fancyvrb6{ border-right: solid 0.4pt; } +span#textcolor1{color:rgb(163,20,20)} +span#textcolor2{color:rgb(163,20,20)} +pre#fancyvrb7{padding:5.69054pt;} +pre#fancyvrb7{ border-top: solid 0.4pt; } +pre#fancyvrb7{ border-left: solid 0.4pt; } +pre#fancyvrb7{ border-bottom: solid 0.4pt; } +pre#fancyvrb7{ border-right: solid 0.4pt; } +pre#fancyvrb8{padding:5.69054pt;} +pre#fancyvrb8{ border-top: solid 0.4pt; } +pre#fancyvrb8{ border-left: solid 0.4pt; } +pre#fancyvrb8{ border-bottom: solid 0.4pt; } +pre#fancyvrb8{ border-right: solid 0.4pt; } +pre#fancyvrb9{padding:5.69054pt;} +pre#fancyvrb9{ border-top: solid 0.4pt; } +pre#fancyvrb9{ border-left: solid 0.4pt; } +pre#fancyvrb9{ border-bottom: solid 0.4pt; } +pre#fancyvrb9{ border-right: solid 0.4pt; } +pre#fancyvrb10{padding:5.69054pt;} +pre#fancyvrb10{ border-top: solid 0.4pt; } +pre#fancyvrb10{ border-left: solid 0.4pt; } +pre#fancyvrb10{ border-bottom: solid 0.4pt; } +pre#fancyvrb10{ border-right: solid 0.4pt; } +span#textcolor3{color:rgb(0,127,0)} +span#textcolor4{color:rgb(0,127,0)} +span#textcolor5{color:rgb(0,127,0)} +span#textcolor6{color:rgb(0,0,255)} +span#textcolor7{color:rgb(0,127,0)} +span#textcolor8{color:rgb(0,0,255)} +span#textcolor9{color:rgb(0,127,0)} +span#textcolor10{color:rgb(43,145,175)} +span#textcolor11{color:rgb(43,145,175)} +span#textcolor12{color:rgb(163,20,20)} +span#textcolor13{color:rgb(163,20,20)} +span#textcolor14{color:rgb(163,20,20)} +span#textcolor15{color:rgb(0,127,0)} +span#textcolor16{color:rgb(0,127,0)} +span#textcolor17{color:rgb(0,127,0)} +span#textcolor18{color:rgb(0,0,255)} +span#textcolor19{color:rgb(43,145,175)} +span#textcolor20{color:rgb(43,145,175)} +span#textcolor21{color:rgb(163,20,20)} +span#textcolor22{color:rgb(163,20,20)} +span#textcolor23{color:rgb(163,20,20)} +span#textcolor24{color:rgb(163,20,20)} +pre#fancyvrb11{padding:5.69054pt;} +pre#fancyvrb11{ border-top: solid 0.4pt; } +pre#fancyvrb11{ border-left: solid 0.4pt; } +pre#fancyvrb11{ border-bottom: solid 0.4pt; } +pre#fancyvrb11{ border-right: solid 0.4pt; } +#colorbox25{border: solid 1px rgb(255,0,0);} +#colorbox25{background-color: rgb(255,255,255);} +#colorbox26{border: solid 1px rgb(255,0,0);} +#colorbox26{background-color: rgb(255,255,255);} +#colorbox27{border: solid 1px rgb(255,0,0);} +#colorbox27{background-color: rgb(255,255,255);} +#colorbox28{border: solid 1px rgb(255,0,0);} +#colorbox28{background-color: rgb(255,255,255);} +pre#fancyvrb12{padding:5.69054pt;} +pre#fancyvrb12{ border-top: solid 0.4pt; } +pre#fancyvrb12{ border-left: solid 0.4pt; } +pre#fancyvrb12{ border-bottom: solid 0.4pt; } +pre#fancyvrb12{ border-right: solid 0.4pt; } +pre#fancyvrb13{padding:5.69054pt;} +pre#fancyvrb13{ border-top: solid 0.4pt; } +pre#fancyvrb13{ border-left: solid 0.4pt; } +pre#fancyvrb13{ border-bottom: solid 0.4pt; } +pre#fancyvrb13{ border-right: solid 0.4pt; } +pre#fancyvrb14{padding:5.69054pt;} +pre#fancyvrb14{ border-top: solid 0.4pt; } +pre#fancyvrb14{ border-left: solid 0.4pt; } +pre#fancyvrb14{ border-bottom: solid 0.4pt; } +pre#fancyvrb14{ border-right: solid 0.4pt; } +pre#fancyvrb15{padding:5.69054pt;} +pre#fancyvrb15{ border-top: solid 0.4pt; } +pre#fancyvrb15{ border-left: solid 0.4pt; } +pre#fancyvrb15{ border-bottom: solid 0.4pt; } +pre#fancyvrb15{ border-right: solid 0.4pt; } +pre#fancyvrb16{padding:5.69054pt;} +pre#fancyvrb16{ border-top: solid 0.4pt; } +pre#fancyvrb16{ border-left: solid 0.4pt; } +pre#fancyvrb16{ border-bottom: solid 0.4pt; } +pre#fancyvrb16{ border-right: solid 0.4pt; } +pre#fancyvrb17{padding:5.69054pt;} +pre#fancyvrb17{ border-top: solid 0.4pt; } +pre#fancyvrb17{ border-left: solid 0.4pt; } +pre#fancyvrb17{ border-bottom: solid 0.4pt; } +pre#fancyvrb17{ border-right: solid 0.4pt; } +pre#fancyvrb18{padding:5.69054pt;} +pre#fancyvrb18{ border-top: solid 0.4pt; } +pre#fancyvrb18{ border-left: solid 0.4pt; } +pre#fancyvrb18{ border-bottom: solid 0.4pt; } +pre#fancyvrb18{ border-right: solid 0.4pt; } +span#textcolor29{color:rgb(163,20,20)} +pre#fancyvrb19{padding:5.69054pt;} +pre#fancyvrb19{ border-top: solid 0.4pt; } +pre#fancyvrb19{ border-left: solid 0.4pt; } +pre#fancyvrb19{ border-bottom: solid 0.4pt; } +pre#fancyvrb19{ border-right: solid 0.4pt; } +span#textcolor30{color:rgb(0,127,0)} +span#textcolor31{color:rgb(0,127,0)} +span#textcolor32{color:rgb(0,127,0)} +span#textcolor33{color:rgb(0,127,0)} +span#textcolor34{color:rgb(0,0,255)} +span#textcolor35{color:rgb(0,127,0)} +span#textcolor36{color:rgb(0,0,255)} +span#textcolor37{color:rgb(0,127,0)} +span#textcolor38{color:rgb(0,0,255)} +span#textcolor39{color:rgb(0,127,0)} +span#textcolor40{color:rgb(0,0,255)} +span#textcolor41{color:rgb(43,145,175)} +span#textcolor42{color:rgb(43,145,175)} +span#textcolor43{color:rgb(163,20,20)} +span#textcolor44{color:rgb(163,20,20)} +span#textcolor45{color:rgb(163,20,20)} +span#textcolor46{color:rgb(0,0,255)} +span#textcolor47{color:rgb(0,0,255)} +span#textcolor48{color:rgb(43,145,175)} +span#textcolor49{color:rgb(43,145,175)} +span#textcolor50{color:rgb(163,20,20)} +span#textcolor51{color:rgb(163,20,20)} +span#textcolor52{color:rgb(163,20,20)} +span#textcolor53{color:rgb(163,20,20)} +pre#fancyvrb20{padding:5.69054pt;} +pre#fancyvrb20{ border-top: solid 0.4pt; } +pre#fancyvrb20{ border-left: solid 0.4pt; } +pre#fancyvrb20{ border-bottom: solid 0.4pt; } +pre#fancyvrb20{ border-right: solid 0.4pt; } +#colorbox54{border: solid 1px rgb(255,0,0);} +#colorbox54{background-color: rgb(255,255,255);} +#colorbox55{border: solid 1px rgb(255,0,0);} +#colorbox55{background-color: rgb(255,255,255);} +#colorbox56{border: solid 1px rgb(255,0,0);} +#colorbox56{background-color: rgb(255,255,255);} +#colorbox57{border: solid 1px rgb(255,0,0);} +#colorbox57{background-color: rgb(255,255,255);} +pre#fancyvrb21{padding:5.69054pt;} +pre#fancyvrb21{ border-top: solid 0.4pt; } +pre#fancyvrb21{ border-left: solid 0.4pt; } +pre#fancyvrb21{ border-bottom: solid 0.4pt; } +pre#fancyvrb21{ border-right: solid 0.4pt; } +span#textcolor58{color:rgb(0,127,0)} +span#textcolor59{color:rgb(0,127,0)} +span#textcolor60{color:rgb(0,127,0)} +span#textcolor61{color:rgb(0,0,255)} +span#textcolor62{color:rgb(0,127,0)} +span#textcolor63{color:rgb(0,0,255)} +span#textcolor64{color:rgb(0,127,0)} +span#textcolor65{color:rgb(0,0,255)} +span#textcolor66{color:rgb(0,127,0)} +span#textcolor67{color:rgb(0,0,255)} +span#textcolor68{color:rgb(43,145,175)} +span#textcolor69{color:rgb(0,0,255)} +span#textcolor70{color:rgb(43,145,175)} +span#textcolor71{color:rgb(43,145,175)} +span#textcolor72{color:rgb(163,20,20)} +span#textcolor73{color:rgb(163,20,20)} +span#textcolor74{color:rgb(163,20,20)} +span#textcolor75{color:rgb(0,0,255)} +span#textcolor76{color:rgb(0,0,255)} +span#textcolor77{color:rgb(43,145,175)} +span#textcolor78{color:rgb(43,145,175)} +span#textcolor79{color:rgb(163,20,20)} +span#textcolor80{color:rgb(163,20,20)} +span#textcolor81{color:rgb(163,20,20)} +span#textcolor82{color:rgb(163,20,20)} +pre#fancyvrb22{padding:5.69054pt;} +pre#fancyvrb22{ border-top: solid 0.4pt; } +pre#fancyvrb22{ border-left: solid 0.4pt; } +pre#fancyvrb22{ border-bottom: solid 0.4pt; } +pre#fancyvrb22{ border-right: solid 0.4pt; } +span#textcolor83{color:rgb(0,127,0)} +span#textcolor84{color:rgb(0,127,0)} +span#textcolor85{color:rgb(0,127,0)} +span#textcolor86{color:rgb(0,0,255)} +span#textcolor87{color:rgb(0,127,0)} +span#textcolor88{color:rgb(0,0,255)} +span#textcolor89{color:rgb(0,127,0)} +span#textcolor90{color:rgb(0,0,255)} +span#textcolor91{color:rgb(0,127,0)} +span#textcolor92{color:rgb(163,20,20)} +span#textcolor93{color:rgb(163,20,20)} +span#textcolor94{color:rgb(163,20,20)} +span#textcolor95{color:rgb(163,20,20)} +span#textcolor96{color:rgb(0,0,255)} +span#textcolor97{color:rgb(43,145,175)} +span#textcolor98{color:rgb(43,145,175)} +span#textcolor99{color:rgb(163,20,20)} +span#textcolor100{color:rgb(163,20,20)} +span#textcolor101{color:rgb(163,20,20)} +span#textcolor102{color:rgb(0,0,255)} +span#textcolor103{color:rgb(0,0,255)} +span#textcolor104{color:rgb(43,145,175)} +span#textcolor105{color:rgb(43,145,175)} +span#textcolor106{color:rgb(163,20,20)} +span#textcolor107{color:rgb(163,20,20)} +span#textcolor108{color:rgb(163,20,20)} +pre#fancyvrb23{padding:5.69054pt;} +pre#fancyvrb23{ border-top: solid 0.4pt; } +pre#fancyvrb23{ border-left: solid 0.4pt; } +pre#fancyvrb23{ border-bottom: solid 0.4pt; } +pre#fancyvrb23{ border-right: solid 0.4pt; } +span#textcolor109{color:rgb(43,145,175)} +span#textcolor110{color:rgb(43,145,175)} +pre#fancyvrb24{padding:5.69054pt;} +pre#fancyvrb24{ border-top: solid 0.4pt; } +pre#fancyvrb24{ border-left: solid 0.4pt; } +pre#fancyvrb24{ border-bottom: solid 0.4pt; } +pre#fancyvrb24{ border-right: solid 0.4pt; } +span#textcolor111{color:rgb(43,145,175)} +span#textcolor112{color:rgb(43,145,175)} +span#textcolor113{color:rgb(0,127,0)} +span#textcolor114{color:rgb(43,145,175)} +span#textcolor115{color:rgb(43,145,175)} +span#textcolor116{color:rgb(43,145,175)} +span#textcolor117{color:rgb(0,127,0)} +pre#fancyvrb25{padding:5.69054pt;} +pre#fancyvrb25{ border-top: solid 0.4pt; } +pre#fancyvrb25{ border-left: solid 0.4pt; } +pre#fancyvrb25{ border-bottom: solid 0.4pt; } +pre#fancyvrb25{ border-right: solid 0.4pt; } +span#textcolor118{color:rgb(0,127,0)} +span#textcolor119{color:rgb(0,127,0)} +span#textcolor120{color:rgb(0,127,0)} +span#textcolor121{color:rgb(0,0,255)} +span#textcolor122{color:rgb(0,127,0)} +span#textcolor123{color:rgb(0,0,255)} +span#textcolor124{color:rgb(0,127,0)} +span#textcolor125{color:rgb(0,0,255)} +span#textcolor126{color:rgb(0,127,0)} +span#textcolor127{color:rgb(0,0,255)} +span#textcolor128{color:rgb(0,127,0)} +span#textcolor129{color:rgb(0,0,255)} +span#textcolor130{color:rgb(0,127,0)} +span#textcolor131{color:rgb(163,20,20)} +span#textcolor132{color:rgb(0,0,255)} +span#textcolor133{color:rgb(43,145,175)} +span#textcolor134{color:rgb(43,145,175)} +span#textcolor135{color:rgb(0,0,255)} +span#textcolor136{color:rgb(43,145,175)} +span#textcolor137{color:rgb(0,0,255)} +span#textcolor138{color:rgb(43,145,175)} +span#textcolor139{color:rgb(43,145,175)} +span#textcolor140{color:rgb(0,0,255)} +span#textcolor141{color:rgb(43,145,175)} +span#textcolor142{color:rgb(163,20,20)} +span#textcolor143{color:rgb(0,0,255)} +span#textcolor144{color:rgb(43,145,175)} +span#textcolor145{color:rgb(0,0,255)} +span#textcolor146{color:rgb(43,145,175)} +span#textcolor147{color:rgb(0,127,0)} +span#textcolor148{color:rgb(0,127,0)} +span#textcolor149{color:rgb(0,127,0)} +span#textcolor150{color:rgb(0,127,0)} +span#textcolor151{color:rgb(0,127,0)} +span#textcolor152{color:rgb(0,127,0)} +span#textcolor153{color:rgb(0,127,0)} +span#textcolor154{color:rgb(43,145,175)} +span#textcolor155{color:rgb(163,20,20)} +span#textcolor156{color:rgb(43,145,175)} +span#textcolor157{color:rgb(163,20,20)} +span#textcolor158{color:rgb(43,145,175)} +span#textcolor159{color:rgb(163,20,20)} +span#textcolor160{color:rgb(163,20,20)} +span#textcolor161{color:rgb(0,127,0)} +span#textcolor162{color:rgb(0,127,0)} +span#textcolor163{color:rgb(0,127,0)} +span#textcolor164{color:rgb(0,127,0)} +span#textcolor165{color:rgb(0,127,0)} +span#textcolor166{color:rgb(0,127,0)} +span#textcolor167{color:rgb(0,127,0)} +span#textcolor168{color:rgb(0,127,0)} +span#textcolor169{color:rgb(43,145,175)} +span#textcolor170{color:rgb(163,20,20)} +span#textcolor171{color:rgb(0,0,255)} +span#textcolor172{color:rgb(43,145,175)} +span#textcolor173{color:rgb(43,145,175)} +span#textcolor174{color:rgb(43,145,175)} +span#textcolor175{color:rgb(163,20,20)} +span#textcolor176{color:rgb(163,20,20)} +span#textcolor177{color:rgb(163,20,20)} +span#textcolor178{color:rgb(163,20,20)} +span#textcolor179{color:rgb(163,20,20)} +span#textcolor180{color:rgb(163,20,20)} +span#textcolor181{color:rgb(163,20,20)} +span#textcolor182{color:rgb(163,20,20)} +span#textcolor183{color:rgb(163,20,20)} +span#textcolor184{color:rgb(163,20,20)} +span#textcolor185{color:rgb(163,20,20)} +span#textcolor186{color:rgb(163,20,20)} +span#textcolor187{color:rgb(163,20,20)} +span#textcolor188{color:rgb(163,20,20)} +span#textcolor189{color:rgb(163,20,20)} +span#textcolor190{color:rgb(163,20,20)} +span#textcolor191{color:rgb(163,20,20)} +span#textcolor192{color:rgb(0,0,255)} +span#textcolor193{color:rgb(0,0,255)} +span#textcolor194{color:rgb(0,0,255)} +span#textcolor195{color:rgb(43,145,175)} +span#textcolor196{color:rgb(163,20,20)} +span#textcolor197{color:rgb(163,20,20)} +span#textcolor198{color:rgb(163,20,20)} +span#textcolor199{color:rgb(163,20,20)} +span#textcolor200{color:rgb(163,20,20)} +span#textcolor201{color:rgb(163,20,20)} +span#textcolor202{color:rgb(0,0,255)} +span#textcolor203{color:rgb(0,0,255)} +span#textcolor204{color:rgb(43,145,175)} +span#textcolor205{color:rgb(43,145,175)} +span#textcolor206{color:rgb(163,20,20)} +span#textcolor207{color:rgb(163,20,20)} +span#textcolor208{color:rgb(163,20,20)} +pre#fancyvrb26{padding:5.69054pt;} +pre#fancyvrb26{ border-top: solid 0.4pt; } +pre#fancyvrb26{ border-left: solid 0.4pt; } +pre#fancyvrb26{ border-bottom: solid 0.4pt; } +pre#fancyvrb26{ border-right: solid 0.4pt; } +#colorbox209{border: solid 1px rgb(255,0,0);} +#colorbox209{background-color: rgb(255,255,255);} +span#textcolor210{color:rgb(163,20,20)} +span#textcolor211{color:rgb(43,145,175)} +span#textcolor212{color:rgb(43,145,175)} +#colorbox213{border: solid 1px rgb(255,0,0);} +#colorbox213{background-color: rgb(255,255,255);} +#colorbox214{border: solid 1px rgb(255,0,0);} +#colorbox214{background-color: rgb(255,255,255);} +span#textcolor215{color:rgb(163,20,20)} +span#textcolor216{color:rgb(43,145,175)} +span#textcolor217{color:rgb(43,145,175)} +#colorbox218{border: solid 1px rgb(255,0,0);} +#colorbox218{background-color: rgb(255,255,255);} +#colorbox219{border: solid 1px rgb(255,0,0);} +#colorbox219{background-color: rgb(255,255,255);} +span#textcolor220{color:rgb(0,0,255)} +span#textcolor221{color:rgb(163,20,20)} +pre#fancyvrb27{padding:5.69054pt;} +pre#fancyvrb27{ border-top: solid 0.4pt; } +pre#fancyvrb27{ border-left: solid 0.4pt; } +pre#fancyvrb27{ border-bottom: solid 0.4pt; } +pre#fancyvrb27{ border-right: solid 0.4pt; } +span#textcolor222{color:rgb(0,127,0)} +span#textcolor223{color:rgb(0,127,0)} +span#textcolor224{color:rgb(0,127,0)} +span#textcolor225{color:rgb(0,0,255)} +span#textcolor226{color:rgb(0,127,0)} +span#textcolor227{color:rgb(0,0,255)} +span#textcolor228{color:rgb(0,127,0)} +span#textcolor229{color:rgb(43,145,175)} +span#textcolor230{color:rgb(43,145,175)} +span#textcolor231{color:rgb(163,20,20)} +span#textcolor232{color:rgb(163,20,20)} +span#textcolor233{color:rgb(163,20,20)} +span#textcolor234{color:rgb(0,0,255)} +span#textcolor235{color:rgb(163,20,20)} +pre#fancyvrb28{padding:5.69054pt;} +pre#fancyvrb28{ border-top: solid 0.4pt; } +pre#fancyvrb28{ border-left: solid 0.4pt; } +pre#fancyvrb28{ border-bottom: solid 0.4pt; } +pre#fancyvrb28{ border-right: solid 0.4pt; } +span#textcolor236{color:rgb(0,127,0)} +span#textcolor237{color:rgb(0,127,0)} +span#textcolor238{color:rgb(0,127,0)} +span#textcolor239{color:rgb(0,0,255)} +span#textcolor240{color:rgb(0,127,0)} +span#textcolor241{color:rgb(0,0,255)} +span#textcolor242{color:rgb(0,127,0)} +span#textcolor243{color:rgb(43,145,175)} +span#textcolor244{color:rgb(163,20,20)} +span#textcolor245{color:rgb(163,20,20)} +span#textcolor246{color:rgb(163,20,20)} +span#textcolor247{color:rgb(163,20,20)} +pre#fancyvrb29{padding:5.69054pt;} +pre#fancyvrb29{ border-top: solid 0.4pt; } +pre#fancyvrb29{ border-left: solid 0.4pt; } +pre#fancyvrb29{ border-bottom: solid 0.4pt; } +pre#fancyvrb29{ border-right: solid 0.4pt; } +#colorbox248{border: solid 1px rgb(255,0,0);} +#colorbox248{background-color: rgb(255,255,255);} +#colorbox249{border: solid 1px rgb(255,0,0);} +#colorbox249{background-color: rgb(255,255,255);} +#colorbox250{border: solid 1px rgb(255,0,0);} +#colorbox250{background-color: rgb(255,255,255);} +#colorbox251{border: solid 1px rgb(255,0,0);} +#colorbox251{background-color: rgb(255,255,255);} +pre#fancyvrb30{padding:5.69054pt;} +pre#fancyvrb30{ border-top: solid 0.4pt; } +pre#fancyvrb30{ border-left: solid 0.4pt; } +pre#fancyvrb30{ border-bottom: solid 0.4pt; } +pre#fancyvrb30{ border-right: solid 0.4pt; } +span#textcolor252{color:rgb(0,0,255)} +span#textcolor253{color:rgb(0,127,0)} +span#textcolor254{color:rgb(43,145,175)} +span#textcolor255{color:rgb(43,145,175)} +span#textcolor256{color:rgb(163,20,20)} +span#textcolor257{color:rgb(0,0,255)} +pre#fancyvrb31{padding:5.69054pt;} +pre#fancyvrb31{ border-top: solid 0.4pt; } +pre#fancyvrb31{ border-left: solid 0.4pt; } +pre#fancyvrb31{ border-bottom: solid 0.4pt; } +pre#fancyvrb31{ border-right: solid 0.4pt; } +span#textcolor258{color:rgb(0,0,255)} +span#textcolor259{color:rgb(0,0,255)} +span#textcolor260{color:rgb(0,0,255)} +span#textcolor261{color:rgb(43,145,175)} +span#textcolor262{color:rgb(43,145,175)} +span#textcolor263{color:rgb(0,0,255)} +span#textcolor264{color:rgb(43,145,175)} +span#textcolor265{color:rgb(43,145,175)} +span#textcolor266{color:rgb(43,145,175)} +span#textcolor267{color:rgb(0,0,255)} +span#textcolor268{color:rgb(0,0,255)} +span#textcolor269{color:rgb(43,145,175)} +span#textcolor270{color:rgb(43,145,175)} +span#textcolor271{color:rgb(43,145,175)} +span#textcolor272{color:rgb(0,0,255)} +span#textcolor273{color:rgb(0,0,255)} +span#textcolor274{color:rgb(0,0,255)} +span#textcolor275{color:rgb(43,145,175)} +span#textcolor276{color:rgb(43,145,175)} +span#textcolor277{color:rgb(43,145,175)} +span#textcolor278{color:rgb(0,0,255)} +span#textcolor279{color:rgb(0,0,255)} +span#textcolor280{color:rgb(0,0,255)} +span#textcolor281{color:rgb(43,145,175)} +span#textcolor282{color:rgb(43,145,175)} +span#textcolor283{color:rgb(43,145,175)} +span#textcolor284{color:rgb(0,0,255)} +span#textcolor285{color:rgb(0,0,255)} +span#textcolor286{color:rgb(43,145,175)} +span#textcolor287{color:rgb(0,0,255)} +span#textcolor288{color:rgb(0,0,255)} +span#textcolor289{color:rgb(43,145,175)} +span#textcolor290{color:rgb(0,0,255)} +span#textcolor291{color:rgb(43,145,175)} +span#textcolor292{color:rgb(43,145,175)} +span#textcolor293{color:rgb(43,145,175)} +span#textcolor294{color:rgb(43,145,175)} +span#textcolor295{color:rgb(43,145,175)} +span#textcolor296{color:rgb(0,0,255)} +span#textcolor297{color:rgb(43,145,175)} +span#textcolor298{color:rgb(43,145,175)} +span#textcolor299{color:rgb(43,145,175)} +span#textcolor300{color:rgb(43,145,175)} +span#textcolor301{color:rgb(43,145,175)} +span#textcolor302{color:rgb(0,0,255)} +span#textcolor303{color:rgb(0,0,255)} +span#textcolor304{color:rgb(43,145,175)} +span#textcolor305{color:rgb(0,0,255)} +span#textcolor306{color:rgb(0,0,255)} +span#textcolor307{color:rgb(43,145,175)} +span#textcolor308{color:rgb(0,0,255)} +span#textcolor309{color:rgb(43,145,175)} +span#textcolor310{color:rgb(0,0,255)} +span#textcolor311{color:rgb(0,0,255)} +span#textcolor312{color:rgb(43,145,175)} +span#textcolor313{color:rgb(0,0,255)} +span#textcolor314{color:rgb(43,145,175)} +span#textcolor315{color:rgb(43,145,175)} +span#textcolor316{color:rgb(0,0,255)} +span#textcolor317{color:rgb(43,145,175)} +span#textcolor318{color:rgb(43,145,175)} +span#textcolor319{color:rgb(43,145,175)} +span#textcolor320{color:rgb(0,0,255)} +span#textcolor321{color:rgb(43,145,175)} +span#textcolor322{color:rgb(43,145,175)} +span#textcolor323{color:rgb(0,0,255)} +span#textcolor324{color:rgb(43,145,175)} +span#textcolor325{color:rgb(0,0,255)} +span#textcolor326{color:rgb(43,145,175)} +span#textcolor327{color:rgb(0,0,255)} +span#textcolor328{color:rgb(0,0,255)} +span#textcolor329{color:rgb(43,145,175)} +span#textcolor330{color:rgb(43,145,175)} +span#textcolor331{color:rgb(43,145,175)} +span#textcolor332{color:rgb(43,145,175)} +span#textcolor333{color:rgb(0,0,255)} +span#textcolor334{color:rgb(43,145,175)} +span#textcolor335{color:rgb(43,145,175)} +span#textcolor336{color:rgb(43,145,175)} +span#textcolor337{color:rgb(43,145,175)} +span#textcolor338{color:rgb(43,145,175)} +span#textcolor339{color:rgb(43,145,175)} +span#textcolor340{color:rgb(43,145,175)} +span#textcolor341{color:rgb(43,145,175)} +span#textcolor342{color:rgb(43,145,175)} +span#textcolor343{color:rgb(43,145,175)} +span#textcolor344{color:rgb(43,145,175)} +span#textcolor345{color:rgb(0,0,255)} +span#textcolor346{color:rgb(43,145,175)} +span#textcolor347{color:rgb(0,0,255)} +span#textcolor348{color:rgb(43,145,175)} +span#textcolor349{color:rgb(0,0,255)} +span#textcolor350{color:rgb(0,0,255)} +span#textcolor351{color:rgb(43,145,175)} +span#textcolor352{color:rgb(43,145,175)} +span#textcolor353{color:rgb(43,145,175)} +span#textcolor354{color:rgb(43,145,175)} +span#textcolor355{color:rgb(0,0,255)} +span#textcolor356{color:rgb(0,0,255)} +span#textcolor357{color:rgb(43,145,175)} +span#textcolor358{color:rgb(43,145,175)} +span#textcolor359{color:rgb(43,145,175)} +span#textcolor360{color:rgb(43,145,175)} +span#textcolor361{color:rgb(0,0,255)} +span#textcolor362{color:rgb(43,145,175)} +span#textcolor363{color:rgb(0,0,255)} +span#textcolor364{color:rgb(43,145,175)} +span#textcolor365{color:rgb(0,0,255)} +span#textcolor366{color:rgb(43,145,175)} +span#textcolor367{color:rgb(43,145,175)} +span#textcolor368{color:rgb(0,0,255)} +span#textcolor369{color:rgb(0,0,255)} +pre#fancyvrb32{padding:5.69054pt;} +pre#fancyvrb32{ border-top: solid 0.4pt; } +pre#fancyvrb32{ border-left: solid 0.4pt; } +pre#fancyvrb32{ border-bottom: solid 0.4pt; } +pre#fancyvrb32{ border-right: solid 0.4pt; } +span#textcolor370{color:rgb(0,0,255)} +pre#fancyvrb33{padding:5.69054pt;} +pre#fancyvrb33{ border-top: solid 0.4pt; } +pre#fancyvrb33{ border-left: solid 0.4pt; } +pre#fancyvrb33{ border-bottom: solid 0.4pt; } +pre#fancyvrb33{ border-right: solid 0.4pt; } +span#textcolor371{color:rgb(0,0,255)} +pre#fancyvrb34{padding:5.69054pt;} +pre#fancyvrb34{ border-top: solid 0.4pt; } +pre#fancyvrb34{ border-left: solid 0.4pt; } +pre#fancyvrb34{ border-bottom: solid 0.4pt; } +pre#fancyvrb34{ border-right: solid 0.4pt; } +span#textcolor372{color:rgb(43,145,175)} +span#textcolor373{color:rgb(43,145,175)} +span#textcolor374{color:rgb(43,145,175)} +span#textcolor375{color:rgb(0,0,255)} +span#textcolor376{color:rgb(43,145,175)} +span#textcolor377{color:rgb(0,0,255)} +pre#fancyvrb35{padding:5.69054pt;} +pre#fancyvrb35{ border-top: solid 0.4pt; } +pre#fancyvrb35{ border-left: solid 0.4pt; } +pre#fancyvrb35{ border-bottom: solid 0.4pt; } +pre#fancyvrb35{ border-right: solid 0.4pt; } +pre#fancyvrb36{padding:5.69054pt;} +pre#fancyvrb36{ border-top: solid 0.4pt; } +pre#fancyvrb36{ border-left: solid 0.4pt; } +pre#fancyvrb36{ border-bottom: solid 0.4pt; } +pre#fancyvrb36{ border-right: solid 0.4pt; } +span#textcolor378{color:rgb(0,127,0)} +span#textcolor379{color:rgb(0,127,0)} +span#textcolor380{color:rgb(0,127,0)} +span#textcolor381{color:rgb(0,127,0)} +span#textcolor382{color:rgb(0,0,255)} +span#textcolor383{color:rgb(0,127,0)} +span#textcolor384{color:rgb(0,0,255)} +span#textcolor385{color:rgb(0,127,0)} +span#textcolor386{color:rgb(0,0,255)} +span#textcolor387{color:rgb(0,127,0)} +span#textcolor388{color:rgb(0,0,255)} +span#textcolor389{color:rgb(0,127,0)} +span#textcolor390{color:rgb(0,0,255)} +span#textcolor391{color:rgb(0,127,0)} +span#textcolor392{color:rgb(0,0,255)} +span#textcolor393{color:rgb(0,127,0)} +span#textcolor394{color:rgb(0,0,255)} +span#textcolor395{color:rgb(0,127,0)} +span#textcolor396{color:rgb(0,0,255)} +span#textcolor397{color:rgb(0,127,0)} +span#textcolor398{color:rgb(0,0,255)} +span#textcolor399{color:rgb(0,127,0)} +span#textcolor400{color:rgb(0,127,0)} +span#textcolor401{color:rgb(0,127,0)} +span#textcolor402{color:rgb(0,127,0)} +span#textcolor403{color:rgb(43,145,175)} +span#textcolor404{color:rgb(43,145,175)} +span#textcolor405{color:rgb(43,145,175)} +span#textcolor406{color:rgb(43,145,175)} +span#textcolor407{color:rgb(0,0,255)} +span#textcolor408{color:rgb(43,145,175)} +span#textcolor409{color:rgb(0,0,255)} +span#textcolor410{color:rgb(0,0,255)} +span#textcolor411{color:rgb(0,0,255)} +span#textcolor412{color:rgb(43,145,175)} +span#textcolor413{color:rgb(0,0,255)} +span#textcolor414{color:rgb(0,0,255)} +span#textcolor415{color:rgb(0,0,255)} +span#textcolor416{color:rgb(43,145,175)} +span#textcolor417{color:rgb(0,0,255)} +span#textcolor418{color:rgb(43,145,175)} +span#textcolor419{color:rgb(43,145,175)} +span#textcolor420{color:rgb(0,0,255)} +span#textcolor421{color:rgb(43,145,175)} +span#textcolor422{color:rgb(0,0,255)} +span#textcolor423{color:rgb(0,0,255)} +span#textcolor424{color:rgb(43,145,175)} +span#textcolor425{color:rgb(43,145,175)} +span#textcolor426{color:rgb(0,0,255)} +span#textcolor427{color:rgb(0,0,255)} +span#textcolor428{color:rgb(0,127,0)} +span#textcolor429{color:rgb(0,0,255)} +span#textcolor430{color:rgb(0,127,0)} +span#textcolor431{color:rgb(0,127,0)} +span#textcolor432{color:rgb(0,127,0)} +span#textcolor433{color:rgb(0,127,0)} +span#textcolor434{color:rgb(0,0,255)} +span#textcolor435{color:rgb(43,145,175)} +span#textcolor436{color:rgb(0,127,0)} +span#textcolor437{color:rgb(0,0,255)} +span#textcolor438{color:rgb(43,145,175)} +span#textcolor439{color:rgb(0,127,0)} +span#textcolor440{color:rgb(0,127,0)} +span#textcolor441{color:rgb(0,0,255)} +span#textcolor442{color:rgb(43,145,175)} +span#textcolor443{color:rgb(0,127,0)} +span#textcolor444{color:rgb(0,0,255)} +span#textcolor445{color:rgb(43,145,175)} +span#textcolor446{color:rgb(0,0,255)} +span#textcolor447{color:rgb(0,0,255)} +span#textcolor448{color:rgb(0,0,255)} +span#textcolor449{color:rgb(0,0,255)} +span#textcolor450{color:rgb(0,127,0)} +span#textcolor451{color:rgb(0,127,0)} +span#textcolor452{color:rgb(0,127,0)} +span#textcolor453{color:rgb(43,145,175)} +span#textcolor454{color:rgb(43,145,175)} +span#textcolor455{color:rgb(0,0,255)} +span#textcolor456{color:rgb(163,20,20)} +span#textcolor457{color:rgb(163,20,20)} +span#textcolor458{color:rgb(163,20,20)} +span#textcolor459{color:rgb(0,0,255)} +span#textcolor460{color:rgb(163,20,20)} +span#textcolor461{color:rgb(163,20,20)} +span#textcolor462{color:rgb(163,20,20)} +span#textcolor463{color:rgb(163,20,20)} +span#textcolor464{color:rgb(163,20,20)} +span#textcolor465{color:rgb(163,20,20)} +span#textcolor466{color:rgb(0,0,255)} +span#textcolor467{color:rgb(0,127,0)} +span#textcolor468{color:rgb(0,127,0)} +span#textcolor469{color:rgb(0,127,0)} +span#textcolor470{color:rgb(43,145,175)} +span#textcolor471{color:rgb(43,145,175)} +span#textcolor472{color:rgb(0,127,0)} +span#textcolor473{color:rgb(0,127,0)} +span#textcolor474{color:rgb(0,127,0)} +span#textcolor475{color:rgb(0,127,0)} +span#textcolor476{color:rgb(0,127,0)} +span#textcolor477{color:rgb(0,127,0)} +span#textcolor478{color:rgb(0,127,0)} +span#textcolor479{color:rgb(0,127,0)} +span#textcolor480{color:rgb(0,127,0)} +span#textcolor481{color:rgb(0,127,0)} +span#textcolor482{color:rgb(0,0,255)} +span#textcolor483{color:rgb(43,145,175)} +span#textcolor484{color:rgb(0,0,255)} +span#textcolor485{color:rgb(0,0,255)} +span#textcolor486{color:rgb(0,0,255)} +span#textcolor487{color:rgb(43,145,175)} +span#textcolor488{color:rgb(0,0,255)} +span#textcolor489{color:rgb(0,0,255)} +span#textcolor490{color:rgb(163,20,20)} +span#textcolor491{color:rgb(163,20,20)} +span#textcolor492{color:rgb(163,20,20)} +span#textcolor493{color:rgb(0,0,255)} +span#textcolor494{color:rgb(0,127,0)} +span#textcolor495{color:rgb(0,127,0)} +span#textcolor496{color:rgb(0,127,0)} +span#textcolor497{color:rgb(0,0,255)} +span#textcolor498{color:rgb(43,145,175)} +span#textcolor499{color:rgb(0,0,255)} +span#textcolor500{color:rgb(0,0,255)} +span#textcolor501{color:rgb(0,127,0)} +span#textcolor502{color:rgb(0,127,0)} +span#textcolor503{color:rgb(0,127,0)} +span#textcolor504{color:rgb(0,127,0)} +span#textcolor505{color:rgb(0,127,0)} +span#textcolor506{color:rgb(0,0,255)} +span#textcolor507{color:rgb(0,127,0)} +span#textcolor508{color:rgb(0,127,0)} +span#textcolor509{color:rgb(0,127,0)} +span#textcolor510{color:rgb(0,127,0)} +span#textcolor511{color:rgb(0,0,255)} +span#textcolor512{color:rgb(43,145,175)} +span#textcolor513{color:rgb(0,0,255)} +span#textcolor514{color:rgb(0,127,0)} +span#textcolor515{color:rgb(43,145,175)} +span#textcolor516{color:rgb(0,127,0)} +span#textcolor517{color:rgb(43,145,175)} +span#textcolor518{color:rgb(0,127,0)} +span#textcolor519{color:rgb(0,127,0)} +span#textcolor520{color:rgb(0,127,0)} +span#textcolor521{color:rgb(0,127,0)} +span#textcolor522{color:rgb(43,145,175)} +span#textcolor523{color:rgb(0,127,0)} +span#textcolor524{color:rgb(0,127,0)} +span#textcolor525{color:rgb(0,127,0)} +span#textcolor526{color:rgb(0,127,0)} +span#textcolor527{color:rgb(0,0,255)} +span#textcolor528{color:rgb(0,0,255)} +span#textcolor529{color:rgb(0,127,0)} +span#textcolor530{color:rgb(0,127,0)} +span#textcolor531{color:rgb(0,127,0)} +span#textcolor532{color:rgb(0,0,255)} +span#textcolor533{color:rgb(0,127,0)} +span#textcolor534{color:rgb(0,127,0)} +span#textcolor535{color:rgb(0,127,0)} +span#textcolor536{color:rgb(0,127,0)} +span#textcolor537{color:rgb(0,127,0)} +span#textcolor538{color:rgb(0,127,0)} +span#textcolor539{color:rgb(0,127,0)} +span#textcolor540{color:rgb(0,127,0)} +span#textcolor541{color:rgb(0,127,0)} +span#textcolor542{color:rgb(0,0,255)} +span#textcolor543{color:rgb(0,127,0)} +span#textcolor544{color:rgb(0,127,0)} +span#textcolor545{color:rgb(0,127,0)} +span#textcolor546{color:rgb(0,0,255)} +span#textcolor547{color:rgb(43,145,175)} +span#textcolor548{color:rgb(0,0,255)} +span#textcolor549{color:rgb(0,0,255)} +span#textcolor550{color:rgb(43,145,175)} +span#textcolor551{color:rgb(43,145,175)} +span#textcolor552{color:rgb(163,20,20)} +span#textcolor553{color:rgb(163,20,20)} +span#textcolor554{color:rgb(163,20,20)} +span#textcolor555{color:rgb(0,0,255)} +span#textcolor556{color:rgb(163,20,20)} +pre#fancyvrb37{padding:5.69054pt;} +pre#fancyvrb37{ border-top: solid 0.4pt; } +pre#fancyvrb37{ border-left: solid 0.4pt; } +pre#fancyvrb37{ border-bottom: solid 0.4pt; } +pre#fancyvrb37{ border-right: solid 0.4pt; } +span#textcolor557{color:rgb(0,127,0)} +span#textcolor558{color:rgb(0,127,0)} +span#textcolor559{color:rgb(0,127,0)} +span#textcolor560{color:rgb(0,0,255)} +span#textcolor561{color:rgb(0,127,0)} +span#textcolor562{color:rgb(0,0,255)} +span#textcolor563{color:rgb(0,127,0)} +span#textcolor564{color:rgb(0,0,255)} +span#textcolor565{color:rgb(0,127,0)} +span#textcolor566{color:rgb(0,0,255)} +span#textcolor567{color:rgb(0,127,0)} +span#textcolor568{color:rgb(0,0,255)} +span#textcolor569{color:rgb(0,127,0)} +span#textcolor570{color:rgb(0,0,255)} +span#textcolor571{color:rgb(0,0,255)} +span#textcolor572{color:rgb(0,0,255)} +span#textcolor573{color:rgb(0,0,255)} +span#textcolor574{color:rgb(0,0,255)} +span#textcolor575{color:rgb(43,145,175)} +span#textcolor576{color:rgb(0,0,255)} +span#textcolor577{color:rgb(43,145,175)} +span#textcolor578{color:rgb(43,145,175)} +span#textcolor579{color:rgb(43,145,175)} +span#textcolor580{color:rgb(163,20,20)} +span#textcolor581{color:rgb(163,20,20)} +span#textcolor582{color:rgb(163,20,20)} +span#textcolor583{color:rgb(43,145,175)} +span#textcolor584{color:rgb(0,0,255)} +span#textcolor585{color:rgb(43,145,175)} +span#textcolor586{color:rgb(0,0,255)} +span#textcolor587{color:rgb(163,20,20)} +span#textcolor588{color:rgb(163,20,20)} +span#textcolor589{color:rgb(163,20,20)} +span#textcolor590{color:rgb(0,0,255)} +span#textcolor591{color:rgb(163,20,20)} +span#textcolor592{color:rgb(163,20,20)} +span#textcolor593{color:rgb(163,20,20)} +span#textcolor594{color:rgb(0,0,255)} +span#textcolor595{color:rgb(0,0,255)} +span#textcolor596{color:rgb(0,0,255)} +span#textcolor597{color:rgb(0,0,255)} +span#textcolor598{color:rgb(0,0,255)} +span#textcolor599{color:rgb(0,0,255)} +span#textcolor600{color:rgb(0,0,255)} +span#textcolor601{color:rgb(0,0,255)} +span#textcolor602{color:rgb(0,0,255)} +span#textcolor603{color:rgb(0,0,255)} +span#textcolor604{color:rgb(43,145,175)} +span#textcolor605{color:rgb(0,0,255)} +span#textcolor606{color:rgb(163,20,20)} +span#textcolor607{color:rgb(163,20,20)} +span#textcolor608{color:rgb(163,20,20)} +span#textcolor609{color:rgb(0,0,255)} +span#textcolor610{color:rgb(163,20,20)} +span#textcolor611{color:rgb(163,20,20)} +span#textcolor612{color:rgb(163,20,20)} +span#textcolor613{color:rgb(0,0,255)} +span#textcolor614{color:rgb(43,145,175)} +span#textcolor615{color:rgb(163,20,20)} +span#textcolor616{color:rgb(163,20,20)} +span#textcolor617{color:rgb(163,20,20)} +span#textcolor618{color:rgb(163,20,20)} +pre#fancyvrb38{padding:5.69054pt;} +pre#fancyvrb38{ border-top: solid 0.4pt; } +pre#fancyvrb38{ border-left: solid 0.4pt; } +pre#fancyvrb38{ border-bottom: solid 0.4pt; } +pre#fancyvrb38{ border-right: solid 0.4pt; } +span#textcolor619{color:rgb(0,127,0)} +span#textcolor620{color:rgb(0,127,0)} +span#textcolor621{color:rgb(0,127,0)} +span#textcolor622{color:rgb(0,0,255)} +span#textcolor623{color:rgb(0,127,0)} +span#textcolor624{color:rgb(0,0,255)} +span#textcolor625{color:rgb(0,127,0)} +span#textcolor626{color:rgb(0,0,255)} +span#textcolor627{color:rgb(0,127,0)} +span#textcolor628{color:rgb(0,0,255)} +span#textcolor629{color:rgb(0,127,0)} +span#textcolor630{color:rgb(0,0,255)} +span#textcolor631{color:rgb(0,127,0)} +span#textcolor632{color:rgb(0,0,255)} +span#textcolor633{color:rgb(0,0,255)} +span#textcolor634{color:rgb(0,0,255)} +span#textcolor635{color:rgb(0,0,255)} +span#textcolor636{color:rgb(0,0,255)} +span#textcolor637{color:rgb(0,127,0)} +span#textcolor638{color:rgb(0,127,0)} +span#textcolor639{color:rgb(0,127,0)} +span#textcolor640{color:rgb(0,127,0)} +span#textcolor641{color:rgb(0,0,255)} +span#textcolor642{color:rgb(0,0,255)} +span#textcolor643{color:rgb(0,127,0)} +span#textcolor644{color:rgb(0,127,0)} +span#textcolor645{color:rgb(0,127,0)} +span#textcolor646{color:rgb(0,127,0)} +span#textcolor647{color:rgb(0,0,255)} +span#textcolor648{color:rgb(43,145,175)} +span#textcolor649{color:rgb(0,127,0)} +span#textcolor650{color:rgb(0,127,0)} +span#textcolor651{color:rgb(0,127,0)} +span#textcolor652{color:rgb(0,127,0)} +span#textcolor653{color:rgb(0,0,255)} +span#textcolor654{color:rgb(43,145,175)} +span#textcolor655{color:rgb(43,145,175)} +span#textcolor656{color:rgb(0,127,0)} +span#textcolor657{color:rgb(0,127,0)} +span#textcolor658{color:rgb(0,127,0)} +span#textcolor659{color:rgb(0,127,0)} +span#textcolor660{color:rgb(43,145,175)} +span#textcolor661{color:rgb(0,0,255)} +span#textcolor662{color:rgb(43,145,175)} +span#textcolor663{color:rgb(43,145,175)} +span#textcolor664{color:rgb(43,145,175)} +span#textcolor665{color:rgb(163,20,20)} +span#textcolor666{color:rgb(163,20,20)} +span#textcolor667{color:rgb(163,20,20)} +span#textcolor668{color:rgb(43,145,175)} +span#textcolor669{color:rgb(0,0,255)} +span#textcolor670{color:rgb(43,145,175)} +span#textcolor671{color:rgb(0,0,255)} +span#textcolor672{color:rgb(163,20,20)} +span#textcolor673{color:rgb(163,20,20)} +span#textcolor674{color:rgb(163,20,20)} +span#textcolor675{color:rgb(0,0,255)} +span#textcolor676{color:rgb(163,20,20)} +span#textcolor677{color:rgb(163,20,20)} +span#textcolor678{color:rgb(163,20,20)} +span#textcolor679{color:rgb(0,0,255)} +span#textcolor680{color:rgb(0,127,0)} +span#textcolor681{color:rgb(0,127,0)} +span#textcolor682{color:rgb(0,127,0)} +span#textcolor683{color:rgb(0,127,0)} +span#textcolor684{color:rgb(0,0,255)} +span#textcolor685{color:rgb(43,145,175)} +span#textcolor686{color:rgb(0,0,255)} +span#textcolor687{color:rgb(0,0,255)} +span#textcolor688{color:rgb(43,145,175)} +span#textcolor689{color:rgb(43,145,175)} +span#textcolor690{color:rgb(0,0,255)} +span#textcolor691{color:rgb(0,0,255)} +span#textcolor692{color:rgb(0,0,255)} +span#textcolor693{color:rgb(163,20,20)} +span#textcolor694{color:rgb(0,0,255)} +span#textcolor695{color:rgb(0,0,255)} +span#textcolor696{color:rgb(0,0,255)} +span#textcolor697{color:rgb(0,0,255)} +span#textcolor698{color:rgb(0,0,255)} +span#textcolor699{color:rgb(0,0,255)} +span#textcolor700{color:rgb(0,0,255)} +span#textcolor701{color:rgb(0,0,255)} +span#textcolor702{color:rgb(0,0,255)} +span#textcolor703{color:rgb(0,0,255)} +span#textcolor704{color:rgb(0,127,0)} +span#textcolor705{color:rgb(0,127,0)} +span#textcolor706{color:rgb(0,127,0)} +span#textcolor707{color:rgb(0,127,0)} +span#textcolor708{color:rgb(43,145,175)} +span#textcolor709{color:rgb(0,0,255)} +span#textcolor710{color:rgb(163,20,20)} +span#textcolor711{color:rgb(163,20,20)} +span#textcolor712{color:rgb(163,20,20)} +span#textcolor713{color:rgb(0,0,255)} +span#textcolor714{color:rgb(163,20,20)} +span#textcolor715{color:rgb(163,20,20)} +span#textcolor716{color:rgb(163,20,20)} +span#textcolor717{color:rgb(0,0,255)} +span#textcolor718{color:rgb(0,127,0)} +span#textcolor719{color:rgb(0,127,0)} +span#textcolor720{color:rgb(0,127,0)} +span#textcolor721{color:rgb(0,127,0)} +span#textcolor722{color:rgb(43,145,175)} +span#textcolor723{color:rgb(163,20,20)} +span#textcolor724{color:rgb(163,20,20)} +span#textcolor725{color:rgb(163,20,20)} +span#textcolor726{color:rgb(163,20,20)} +pre#fancyvrb39{padding:5.69054pt;} +pre#fancyvrb39{ border-top: solid 0.4pt; } +pre#fancyvrb39{ border-left: solid 0.4pt; } +pre#fancyvrb39{ border-bottom: solid 0.4pt; } +pre#fancyvrb39{ border-right: solid 0.4pt; } +span#textcolor727{color:rgb(0,127,0)} +span#textcolor728{color:rgb(0,127,0)} +span#textcolor729{color:rgb(0,127,0)} +span#textcolor730{color:rgb(0,0,255)} +span#textcolor731{color:rgb(0,127,0)} +span#textcolor732{color:rgb(0,0,255)} +span#textcolor733{color:rgb(0,127,0)} +span#textcolor734{color:rgb(0,0,255)} +span#textcolor735{color:rgb(0,127,0)} +span#textcolor736{color:rgb(0,0,255)} +span#textcolor737{color:rgb(0,127,0)} +span#textcolor738{color:rgb(0,0,255)} +span#textcolor739{color:rgb(0,127,0)} +span#textcolor740{color:rgb(0,0,255)} +span#textcolor741{color:rgb(0,127,0)} +span#textcolor742{color:rgb(0,0,255)} +span#textcolor743{color:rgb(0,0,255)} +span#textcolor744{color:rgb(0,0,255)} +span#textcolor745{color:rgb(0,0,255)} +span#textcolor746{color:rgb(0,0,255)} +span#textcolor747{color:rgb(0,0,255)} +span#textcolor748{color:rgb(0,0,255)} +span#textcolor749{color:rgb(43,145,175)} +span#textcolor750{color:rgb(0,0,255)} +span#textcolor751{color:rgb(43,145,175)} +span#textcolor752{color:rgb(43,145,175)} +span#textcolor753{color:rgb(0,0,255)} +span#textcolor754{color:rgb(43,145,175)} +span#textcolor755{color:rgb(0,0,255)} +span#textcolor756{color:rgb(43,145,175)} +span#textcolor757{color:rgb(43,145,175)} +span#textcolor758{color:rgb(0,0,255)} +span#textcolor759{color:rgb(43,145,175)} +span#textcolor760{color:rgb(0,0,255)} +span#textcolor761{color:rgb(163,20,20)} +span#textcolor762{color:rgb(163,20,20)} +span#textcolor763{color:rgb(163,20,20)} +span#textcolor764{color:rgb(0,0,255)} +span#textcolor765{color:rgb(0,0,255)} +span#textcolor766{color:rgb(0,0,255)} +span#textcolor767{color:rgb(163,20,20)} +span#textcolor768{color:rgb(163,20,20)} +span#textcolor769{color:rgb(163,20,20)} +span#textcolor770{color:rgb(0,0,255)} +span#textcolor771{color:rgb(0,0,255)} +span#textcolor772{color:rgb(43,145,175)} +span#textcolor773{color:rgb(0,0,255)} +span#textcolor774{color:rgb(0,0,255)} +span#textcolor775{color:rgb(43,145,175)} +span#textcolor776{color:rgb(43,145,175)} +span#textcolor777{color:rgb(0,0,255)} +span#textcolor778{color:rgb(0,0,255)} +span#textcolor779{color:rgb(0,0,255)} +span#textcolor780{color:rgb(0,0,255)} +span#textcolor781{color:rgb(163,20,20)} +span#textcolor782{color:rgb(163,20,20)} +span#textcolor783{color:rgb(163,20,20)} +span#textcolor784{color:rgb(0,0,255)} +span#textcolor785{color:rgb(43,145,175)} +span#textcolor786{color:rgb(0,0,255)} +span#textcolor787{color:rgb(0,0,255)} +span#textcolor788{color:rgb(0,0,255)} +span#textcolor789{color:rgb(43,145,175)} +span#textcolor790{color:rgb(0,0,255)} +span#textcolor791{color:rgb(0,0,255)} +span#textcolor792{color:rgb(0,0,255)} +span#textcolor793{color:rgb(0,0,255)} +span#textcolor794{color:rgb(0,0,255)} +span#textcolor795{color:rgb(0,0,255)} +span#textcolor796{color:rgb(0,0,255)} +span#textcolor797{color:rgb(0,0,255)} +span#textcolor798{color:rgb(0,0,255)} +span#textcolor799{color:rgb(0,0,255)} +span#textcolor800{color:rgb(0,0,255)} +span#textcolor801{color:rgb(43,145,175)} +span#textcolor802{color:rgb(0,0,255)} +span#textcolor803{color:rgb(163,20,20)} +span#textcolor804{color:rgb(163,20,20)} +span#textcolor805{color:rgb(163,20,20)} +span#textcolor806{color:rgb(0,0,255)} +span#textcolor807{color:rgb(163,20,20)} +span#textcolor808{color:rgb(163,20,20)} +span#textcolor809{color:rgb(163,20,20)} +span#textcolor810{color:rgb(0,0,255)} +span#textcolor811{color:rgb(43,145,175)} +span#textcolor812{color:rgb(163,20,20)} +span#textcolor813{color:rgb(163,20,20)} +span#textcolor814{color:rgb(163,20,20)} +span#textcolor815{color:rgb(163,20,20)} +pre#fancyvrb40{padding:5.69054pt;} +pre#fancyvrb40{ border-top: solid 0.4pt; } +pre#fancyvrb40{ border-left: solid 0.4pt; } +pre#fancyvrb40{ border-bottom: solid 0.4pt; } +pre#fancyvrb40{ border-right: solid 0.4pt; } +span#textcolor816{color:rgb(0,127,0)} +span#textcolor817{color:rgb(0,127,0)} +span#textcolor818{color:rgb(0,127,0)} +span#textcolor819{color:rgb(0,127,0)} +span#textcolor820{color:rgb(0,127,0)} +span#textcolor821{color:rgb(0,0,255)} +span#textcolor822{color:rgb(0,127,0)} +span#textcolor823{color:rgb(0,0,255)} +span#textcolor824{color:rgb(0,127,0)} +span#textcolor825{color:rgb(0,0,255)} +span#textcolor826{color:rgb(0,127,0)} +span#textcolor827{color:rgb(0,0,255)} +span#textcolor828{color:rgb(0,127,0)} +span#textcolor829{color:rgb(0,0,255)} +span#textcolor830{color:rgb(0,127,0)} +span#textcolor831{color:rgb(0,0,255)} +span#textcolor832{color:rgb(0,0,255)} +span#textcolor833{color:rgb(0,0,255)} +span#textcolor834{color:rgb(0,0,255)} +span#textcolor835{color:rgb(163,20,20)} +span#textcolor836{color:rgb(0,127,0)} +span#textcolor837{color:rgb(0,127,0)} +span#textcolor838{color:rgb(0,127,0)} +span#textcolor839{color:rgb(0,127,0)} +span#textcolor840{color:rgb(0,127,0)} +span#textcolor841{color:rgb(0,127,0)} +span#textcolor842{color:rgb(0,127,0)} +span#textcolor843{color:rgb(0,0,255)} +span#textcolor844{color:rgb(43,145,175)} +span#textcolor845{color:rgb(0,0,255)} +span#textcolor846{color:rgb(0,0,255)} +span#textcolor847{color:rgb(43,145,175)} +span#textcolor848{color:rgb(43,145,175)} +span#textcolor849{color:rgb(0,127,0)} +span#textcolor850{color:rgb(0,0,255)} +span#textcolor851{color:rgb(0,127,0)} +span#textcolor852{color:rgb(0,0,255)} +span#textcolor853{color:rgb(0,0,255)} +span#textcolor854{color:rgb(0,127,0)} +span#textcolor855{color:rgb(0,0,255)} +span#textcolor856{color:rgb(0,127,0)} +span#textcolor857{color:rgb(0,127,0)} +span#textcolor858{color:rgb(0,127,0)} +span#textcolor859{color:rgb(0,127,0)} +span#textcolor860{color:rgb(0,127,0)} +span#textcolor861{color:rgb(0,0,255)} +span#textcolor862{color:rgb(43,145,175)} +span#textcolor863{color:rgb(0,0,255)} +span#textcolor864{color:rgb(43,145,175)} +span#textcolor865{color:rgb(43,145,175)} +span#textcolor866{color:rgb(43,145,175)} +span#textcolor867{color:rgb(43,145,175)} +span#textcolor868{color:rgb(43,145,175)} +span#textcolor869{color:rgb(0,0,255)} +span#textcolor870{color:rgb(0,127,0)} +span#textcolor871{color:rgb(0,127,0)} +span#textcolor872{color:rgb(0,127,0)} +span#textcolor873{color:rgb(0,127,0)} +span#textcolor874{color:rgb(0,0,255)} +span#textcolor875{color:rgb(43,145,175)} +span#textcolor876{color:rgb(0,0,255)} +span#textcolor877{color:rgb(43,145,175)} +span#textcolor878{color:rgb(0,127,0)} +span#textcolor879{color:rgb(0,127,0)} +span#textcolor880{color:rgb(0,127,0)} +span#textcolor881{color:rgb(0,127,0)} +span#textcolor882{color:rgb(0,127,0)} +span#textcolor883{color:rgb(0,0,255)} +span#textcolor884{color:rgb(43,145,175)} +span#textcolor885{color:rgb(0,0,255)} +span#textcolor886{color:rgb(43,145,175)} +span#textcolor887{color:rgb(163,20,20)} +span#textcolor888{color:rgb(163,20,20)} +span#textcolor889{color:rgb(163,20,20)} +span#textcolor890{color:rgb(0,0,255)} +span#textcolor891{color:rgb(0,127,0)} +span#textcolor892{color:rgb(0,127,0)} +span#textcolor893{color:rgb(0,127,0)} +span#textcolor894{color:rgb(0,127,0)} +span#textcolor895{color:rgb(0,0,255)} +span#textcolor896{color:rgb(0,0,255)} +span#textcolor897{color:rgb(0,127,0)} +span#textcolor898{color:rgb(0,127,0)} +span#textcolor899{color:rgb(0,127,0)} +span#textcolor900{color:rgb(0,127,0)} +span#textcolor901{color:rgb(0,0,255)} +span#textcolor902{color:rgb(43,145,175)} +span#textcolor903{color:rgb(0,0,255)} +span#textcolor904{color:rgb(0,0,255)} +span#textcolor905{color:rgb(0,0,255)} +span#textcolor906{color:rgb(0,127,0)} +span#textcolor907{color:rgb(0,127,0)} +span#textcolor908{color:rgb(0,127,0)} +span#textcolor909{color:rgb(0,127,0)} +span#textcolor910{color:rgb(0,0,255)} +span#textcolor911{color:rgb(0,0,255)} +span#textcolor912{color:rgb(0,0,255)} +span#textcolor913{color:rgb(0,0,255)} +span#textcolor914{color:rgb(0,0,255)} +span#textcolor915{color:rgb(0,0,255)} +span#textcolor916{color:rgb(0,0,255)} +span#textcolor917{color:rgb(0,0,255)} +span#textcolor918{color:rgb(0,0,255)} +span#textcolor919{color:rgb(0,127,0)} +span#textcolor920{color:rgb(0,127,0)} +span#textcolor921{color:rgb(0,127,0)} +span#textcolor922{color:rgb(0,127,0)} +span#textcolor923{color:rgb(43,145,175)} +span#textcolor924{color:rgb(43,145,175)} +span#textcolor925{color:rgb(0,0,255)} +span#textcolor926{color:rgb(0,0,255)} +span#textcolor927{color:rgb(163,20,20)} +span#textcolor928{color:rgb(163,20,20)} +span#textcolor929{color:rgb(163,20,20)} +span#textcolor930{color:rgb(0,0,255)} +span#textcolor931{color:rgb(0,0,255)} +span#textcolor932{color:rgb(0,127,0)} +span#textcolor933{color:rgb(0,127,0)} +span#textcolor934{color:rgb(0,127,0)} +span#textcolor935{color:rgb(0,127,0)} +span#textcolor936{color:rgb(43,145,175)} +span#textcolor937{color:rgb(43,145,175)} +span#textcolor938{color:rgb(163,20,20)} +span#textcolor939{color:rgb(163,20,20)} +span#textcolor940{color:rgb(163,20,20)} +pre#fancyvrb41{padding:5.69054pt;} +pre#fancyvrb41{ border-top: solid 0.4pt; } +pre#fancyvrb41{ border-left: solid 0.4pt; } +pre#fancyvrb41{ border-bottom: solid 0.4pt; } +pre#fancyvrb41{ border-right: solid 0.4pt; } +pre#fancyvrb42{padding:5.69054pt;} +pre#fancyvrb42{ border-top: solid 0.4pt; } +pre#fancyvrb42{ border-left: solid 0.4pt; } +pre#fancyvrb42{ border-bottom: solid 0.4pt; } +pre#fancyvrb42{ border-right: solid 0.4pt; } +span#textcolor941{color:rgb(0,127,0)} +span#textcolor942{color:rgb(0,127,0)} +span#textcolor943{color:rgb(0,127,0)} +span#textcolor944{color:rgb(0,0,255)} +span#textcolor945{color:rgb(0,127,0)} +span#textcolor946{color:rgb(0,0,255)} +span#textcolor947{color:rgb(0,127,0)} +span#textcolor948{color:rgb(0,0,255)} +span#textcolor949{color:rgb(0,127,0)} +span#textcolor950{color:rgb(0,0,255)} +span#textcolor951{color:rgb(0,127,0)} +span#textcolor952{color:rgb(0,0,255)} +span#textcolor953{color:rgb(0,127,0)} +span#textcolor954{color:rgb(0,0,255)} +span#textcolor955{color:rgb(0,127,0)} +span#textcolor956{color:rgb(163,20,20)} +span#textcolor957{color:rgb(0,0,255)} +span#textcolor958{color:rgb(0,0,255)} +span#textcolor959{color:rgb(0,127,0)} +span#textcolor960{color:rgb(0,0,255)} +span#textcolor961{color:rgb(43,145,175)} +span#textcolor962{color:rgb(0,0,255)} +span#textcolor963{color:rgb(43,145,175)} +span#textcolor964{color:rgb(0,0,255)} +span#textcolor965{color:rgb(0,0,255)} +span#textcolor966{color:rgb(43,145,175)} +span#textcolor967{color:rgb(0,0,255)} +span#textcolor968{color:rgb(163,20,20)} +span#textcolor969{color:rgb(163,20,20)} +span#textcolor970{color:rgb(163,20,20)} +span#textcolor971{color:rgb(0,0,255)} +span#textcolor972{color:rgb(43,145,175)} +span#textcolor973{color:rgb(0,0,255)} +span#textcolor974{color:rgb(0,0,255)} +span#textcolor975{color:rgb(43,145,175)} +span#textcolor976{color:rgb(43,145,175)} +span#textcolor977{color:rgb(163,20,20)} +span#textcolor978{color:rgb(0,0,255)} +span#textcolor979{color:rgb(0,0,255)} +span#textcolor980{color:rgb(0,0,255)} +span#textcolor981{color:rgb(43,145,175)} +span#textcolor982{color:rgb(0,0,255)} +span#textcolor983{color:rgb(43,145,175)} +span#textcolor984{color:rgb(43,145,175)} +span#textcolor985{color:rgb(43,145,175)} +span#textcolor986{color:rgb(163,20,20)} +span#textcolor987{color:rgb(163,20,20)} +span#textcolor988{color:rgb(163,20,20)} +span#textcolor989{color:rgb(163,20,20)} +span#textcolor990{color:rgb(0,0,255)} +span#textcolor991{color:rgb(0,0,255)} +span#textcolor992{color:rgb(0,0,255)} +span#textcolor993{color:rgb(163,20,20)} +span#textcolor994{color:rgb(163,20,20)} +span#textcolor995{color:rgb(163,20,20)} +span#textcolor996{color:rgb(163,20,20)} +span#textcolor997{color:rgb(0,0,255)} +span#textcolor998{color:rgb(0,0,255)} +span#textcolor999{color:rgb(43,145,175)} +span#textcolor1000{color:rgb(43,145,175)} +span#textcolor1001{color:rgb(163,20,20)} +span#textcolor1002{color:rgb(163,20,20)} +span#textcolor1003{color:rgb(163,20,20)} +pre#fancyvrb43{padding:5.69054pt;} +pre#fancyvrb43{ border-top: solid 0.4pt; } +pre#fancyvrb43{ border-left: solid 0.4pt; } +pre#fancyvrb43{ border-bottom: solid 0.4pt; } +pre#fancyvrb43{ border-right: solid 0.4pt; } +pre#fancyvrb44{padding:5.69054pt;} +pre#fancyvrb44{ border-top: solid 0.4pt; } +pre#fancyvrb44{ border-left: solid 0.4pt; } +pre#fancyvrb44{ border-bottom: solid 0.4pt; } +pre#fancyvrb44{ border-right: solid 0.4pt; } +pre#fancyvrb45{padding:5.69054pt;} +pre#fancyvrb45{ border-top: solid 0.4pt; } +pre#fancyvrb45{ border-left: solid 0.4pt; } +pre#fancyvrb45{ border-bottom: solid 0.4pt; } +pre#fancyvrb45{ border-right: solid 0.4pt; } +pre#fancyvrb46{padding:5.69054pt;} +pre#fancyvrb46{ border-top: solid 0.4pt; } +pre#fancyvrb46{ border-left: solid 0.4pt; } +pre#fancyvrb46{ border-bottom: solid 0.4pt; } +pre#fancyvrb46{ border-right: solid 0.4pt; } +span#textcolor1004{color:rgb(163,20,20)} +pre#fancyvrb47{padding:5.69054pt;} +pre#fancyvrb47{ border-top: solid 0.4pt; } +pre#fancyvrb47{ border-left: solid 0.4pt; } +pre#fancyvrb47{ border-bottom: solid 0.4pt; } +pre#fancyvrb47{ border-right: solid 0.4pt; } +pre#fancyvrb48{padding:5.69054pt;} +pre#fancyvrb48{ border-top: solid 0.4pt; } +pre#fancyvrb48{ border-left: solid 0.4pt; } +pre#fancyvrb48{ border-bottom: solid 0.4pt; } +pre#fancyvrb48{ border-right: solid 0.4pt; } +span#textcolor1005{color:rgb(0,127,0)} +span#textcolor1006{color:rgb(0,127,0)} +span#textcolor1007{color:rgb(0,127,0)} +span#textcolor1008{color:rgb(0,0,255)} +span#textcolor1009{color:rgb(0,127,0)} +span#textcolor1010{color:rgb(0,0,255)} +span#textcolor1011{color:rgb(0,127,0)} +span#textcolor1012{color:rgb(0,0,255)} +span#textcolor1013{color:rgb(0,127,0)} +span#textcolor1014{color:rgb(0,0,255)} +span#textcolor1015{color:rgb(0,127,0)} +span#textcolor1016{color:rgb(0,0,255)} +span#textcolor1017{color:rgb(0,127,0)} +span#textcolor1018{color:rgb(0,0,255)} +span#textcolor1019{color:rgb(0,127,0)} +span#textcolor1020{color:rgb(0,0,255)} +span#textcolor1021{color:rgb(0,127,0)} +span#textcolor1022{color:rgb(0,0,255)} +span#textcolor1023{color:rgb(0,127,0)} +span#textcolor1024{color:rgb(0,0,255)} +span#textcolor1025{color:rgb(0,127,0)} +span#textcolor1026{color:rgb(0,0,255)} +span#textcolor1027{color:rgb(0,127,0)} +span#textcolor1028{color:rgb(0,0,255)} +span#textcolor1029{color:rgb(0,0,255)} +span#textcolor1030{color:rgb(0,0,255)} +span#textcolor1031{color:rgb(0,127,0)} +span#textcolor1032{color:rgb(0,127,0)} +span#textcolor1033{color:rgb(0,127,0)} +span#textcolor1034{color:rgb(0,127,0)} +span#textcolor1035{color:rgb(0,0,255)} +span#textcolor1036{color:rgb(43,145,175)} +span#textcolor1037{color:rgb(0,127,0)} +span#textcolor1038{color:rgb(0,127,0)} +span#textcolor1039{color:rgb(0,127,0)} +span#textcolor1040{color:rgb(0,0,255)} +span#textcolor1041{color:rgb(43,145,175)} +span#textcolor1042{color:rgb(0,127,0)} +span#textcolor1043{color:rgb(0,127,0)} +span#textcolor1044{color:rgb(0,127,0)} +span#textcolor1045{color:rgb(0,127,0)} +span#textcolor1046{color:rgb(0,127,0)} +span#textcolor1047{color:rgb(0,0,255)} +span#textcolor1048{color:rgb(43,145,175)} +span#textcolor1049{color:rgb(0,0,255)} +span#textcolor1050{color:rgb(43,145,175)} +span#textcolor1051{color:rgb(0,127,0)} +span#textcolor1052{color:rgb(0,0,255)} +span#textcolor1053{color:rgb(0,0,255)} +span#textcolor1054{color:rgb(0,127,0)} +span#textcolor1055{color:rgb(0,127,0)} +span#textcolor1056{color:rgb(0,127,0)} +span#textcolor1057{color:rgb(0,0,255)} +span#textcolor1058{color:rgb(43,145,175)} +span#textcolor1059{color:rgb(0,0,255)} +span#textcolor1060{color:rgb(0,0,255)} +span#textcolor1061{color:rgb(163,20,20)} +span#textcolor1062{color:rgb(163,20,20)} +span#textcolor1063{color:rgb(163,20,20)} +span#textcolor1064{color:rgb(0,127,0)} +span#textcolor1065{color:rgb(0,127,0)} +span#textcolor1066{color:rgb(0,127,0)} +span#textcolor1067{color:rgb(0,0,255)} +span#textcolor1068{color:rgb(0,0,255)} +span#textcolor1069{color:rgb(0,127,0)} +span#textcolor1070{color:rgb(0,127,0)} +span#textcolor1071{color:rgb(0,127,0)} +span#textcolor1072{color:rgb(0,0,255)} +span#textcolor1073{color:rgb(0,0,255)} +span#textcolor1074{color:rgb(43,145,175)} +span#textcolor1075{color:rgb(0,0,255)} +span#textcolor1076{color:rgb(0,0,255)} +span#textcolor1077{color:rgb(163,20,20)} +span#textcolor1078{color:rgb(163,20,20)} +span#textcolor1079{color:rgb(163,20,20)} +span#textcolor1080{color:rgb(0,127,0)} +span#textcolor1081{color:rgb(0,127,0)} +span#textcolor1082{color:rgb(0,127,0)} +span#textcolor1083{color:rgb(0,0,255)} +span#textcolor1084{color:rgb(0,127,0)} +span#textcolor1085{color:rgb(0,127,0)} +span#textcolor1086{color:rgb(0,127,0)} +span#textcolor1087{color:rgb(0,127,0)} +span#textcolor1088{color:rgb(0,0,255)} +span#textcolor1089{color:rgb(43,145,175)} +span#textcolor1090{color:rgb(0,0,255)} +span#textcolor1091{color:rgb(0,127,0)} +span#textcolor1092{color:rgb(43,145,175)} +span#textcolor1093{color:rgb(0,127,0)} +span#textcolor1094{color:rgb(0,127,0)} +span#textcolor1095{color:rgb(43,145,175)} +span#textcolor1096{color:rgb(0,127,0)} +span#textcolor1097{color:rgb(0,127,0)} +span#textcolor1098{color:rgb(0,127,0)} +span#textcolor1099{color:rgb(0,127,0)} +span#textcolor1100{color:rgb(43,145,175)} +span#textcolor1101{color:rgb(163,20,20)} +span#textcolor1102{color:rgb(163,20,20)} +span#textcolor1103{color:rgb(163,20,20)} +span#textcolor1104{color:rgb(0,127,0)} +span#textcolor1105{color:rgb(0,127,0)} +span#textcolor1106{color:rgb(0,127,0)} +span#textcolor1107{color:rgb(0,127,0)} +span#textcolor1108{color:rgb(0,0,255)} +span#textcolor1109{color:rgb(0,0,255)} +span#textcolor1110{color:rgb(0,127,0)} +span#textcolor1111{color:rgb(0,127,0)} +span#textcolor1112{color:rgb(0,127,0)} +span#textcolor1113{color:rgb(0,0,255)} +span#textcolor1114{color:rgb(0,127,0)} +span#textcolor1115{color:rgb(0,127,0)} +span#textcolor1116{color:rgb(0,127,0)} +span#textcolor1117{color:rgb(0,127,0)} +span#textcolor1118{color:rgb(0,127,0)} +span#textcolor1119{color:rgb(0,127,0)} +span#textcolor1120{color:rgb(0,127,0)} +span#textcolor1121{color:rgb(163,20,20)} +span#textcolor1122{color:rgb(163,20,20)} +span#textcolor1123{color:rgb(163,20,20)} +span#textcolor1124{color:rgb(0,127,0)} +span#textcolor1125{color:rgb(0,127,0)} +span#textcolor1126{color:rgb(0,127,0)} +span#textcolor1127{color:rgb(0,127,0)} +span#textcolor1128{color:rgb(0,0,255)} +span#textcolor1129{color:rgb(0,127,0)} +span#textcolor1130{color:rgb(0,127,0)} +span#textcolor1131{color:rgb(0,127,0)} +span#textcolor1132{color:rgb(0,127,0)} +span#textcolor1133{color:rgb(0,0,255)} +span#textcolor1134{color:rgb(43,145,175)} +span#textcolor1135{color:rgb(0,0,255)} +span#textcolor1136{color:rgb(0,0,255)} +span#textcolor1137{color:rgb(43,145,175)} +span#textcolor1138{color:rgb(43,145,175)} +span#textcolor1139{color:rgb(43,145,175)} +span#textcolor1140{color:rgb(163,20,20)} +span#textcolor1141{color:rgb(0,0,255)} +span#textcolor1142{color:rgb(0,127,0)} +span#textcolor1143{color:rgb(0,127,0)} +span#textcolor1144{color:rgb(0,127,0)} +span#textcolor1145{color:rgb(0,0,255)} +span#textcolor1146{color:rgb(0,127,0)} +span#textcolor1147{color:rgb(0,127,0)} +span#textcolor1148{color:rgb(0,127,0)} +span#textcolor1149{color:rgb(0,127,0)} +span#textcolor1150{color:rgb(0,127,0)} +span#textcolor1151{color:rgb(0,127,0)} +span#textcolor1152{color:rgb(0,127,0)} +span#textcolor1153{color:rgb(0,127,0)} +span#textcolor1154{color:rgb(0,127,0)} +span#textcolor1155{color:rgb(0,127,0)} +span#textcolor1156{color:rgb(43,145,175)} +span#textcolor1157{color:rgb(0,0,255)} +span#textcolor1158{color:rgb(0,127,0)} +span#textcolor1159{color:rgb(43,145,175)} +span#textcolor1160{color:rgb(43,145,175)} +span#textcolor1161{color:rgb(0,127,0)} +span#textcolor1162{color:rgb(43,145,175)} +span#textcolor1163{color:rgb(43,145,175)} +span#textcolor1164{color:rgb(43,145,175)} +span#textcolor1165{color:rgb(43,145,175)} +span#textcolor1166{color:rgb(43,145,175)} +span#textcolor1167{color:rgb(0,127,0)} +span#textcolor1168{color:rgb(0,127,0)} +span#textcolor1169{color:rgb(0,127,0)} +span#textcolor1170{color:rgb(0,0,255)} +span#textcolor1171{color:rgb(0,0,255)} +span#textcolor1172{color:rgb(0,127,0)} +span#textcolor1173{color:rgb(0,127,0)} +span#textcolor1174{color:rgb(0,127,0)} +span#textcolor1175{color:rgb(0,127,0)} +span#textcolor1176{color:rgb(0,127,0)} +span#textcolor1177{color:rgb(43,145,175)} +span#textcolor1178{color:rgb(0,127,0)} +span#textcolor1179{color:rgb(0,127,0)} +span#textcolor1180{color:rgb(0,127,0)} +span#textcolor1181{color:rgb(0,0,255)} +span#textcolor1182{color:rgb(43,145,175)} +span#textcolor1183{color:rgb(0,0,255)} +span#textcolor1184{color:rgb(0,0,255)} +span#textcolor1185{color:rgb(0,127,0)} +span#textcolor1186{color:rgb(0,127,0)} +span#textcolor1187{color:rgb(0,127,0)} +span#textcolor1188{color:rgb(0,127,0)} +span#textcolor1189{color:rgb(43,145,175)} +span#textcolor1190{color:rgb(0,127,0)} +span#textcolor1191{color:rgb(0,127,0)} +span#textcolor1192{color:rgb(0,127,0)} +span#textcolor1193{color:rgb(0,127,0)} +span#textcolor1194{color:rgb(163,20,20)} +span#textcolor1195{color:rgb(43,145,175)} +span#textcolor1196{color:rgb(0,0,255)} +span#textcolor1197{color:rgb(0,0,255)} +span#textcolor1198{color:rgb(0,127,0)} +span#textcolor1199{color:rgb(0,127,0)} +span#textcolor1200{color:rgb(0,127,0)} +span#textcolor1201{color:rgb(0,127,0)} +span#textcolor1202{color:rgb(0,0,255)} +span#textcolor1203{color:rgb(0,0,255)} +span#textcolor1204{color:rgb(0,0,255)} +span#textcolor1205{color:rgb(0,127,0)} +span#textcolor1206{color:rgb(0,127,0)} +span#textcolor1207{color:rgb(0,127,0)} +span#textcolor1208{color:rgb(0,127,0)} +span#textcolor1209{color:rgb(0,127,0)} +span#textcolor1210{color:rgb(0,127,0)} +span#textcolor1211{color:rgb(0,127,0)} +span#textcolor1212{color:rgb(0,127,0)} +span#textcolor1213{color:rgb(0,0,255)} +span#textcolor1214{color:rgb(0,127,0)} +span#textcolor1215{color:rgb(0,127,0)} +span#textcolor1216{color:rgb(0,127,0)} +span#textcolor1217{color:rgb(0,127,0)} +span#textcolor1218{color:rgb(43,145,175)} +span#textcolor1219{color:rgb(43,145,175)} +span#textcolor1220{color:rgb(0,127,0)} +span#textcolor1221{color:rgb(0,127,0)} +span#textcolor1222{color:rgb(0,127,0)} +span#textcolor1223{color:rgb(0,127,0)} +span#textcolor1224{color:rgb(0,127,0)} +span#textcolor1225{color:rgb(0,127,0)} +span#textcolor1226{color:rgb(0,0,255)} +span#textcolor1227{color:rgb(163,20,20)} +span#textcolor1228{color:rgb(163,20,20)} +span#textcolor1229{color:rgb(163,20,20)} +span#textcolor1230{color:rgb(163,20,20)} +span#textcolor1231{color:rgb(0,0,255)} +span#textcolor1232{color:rgb(163,20,20)} +span#textcolor1233{color:rgb(163,20,20)} +span#textcolor1234{color:rgb(163,20,20)} +span#textcolor1235{color:rgb(0,0,255)} +span#textcolor1236{color:rgb(0,127,0)} +span#textcolor1237{color:rgb(0,127,0)} +span#textcolor1238{color:rgb(0,127,0)} +span#textcolor1239{color:rgb(43,145,175)} +span#textcolor1240{color:rgb(0,127,0)} +span#textcolor1241{color:rgb(0,127,0)} +span#textcolor1242{color:rgb(0,127,0)} +span#textcolor1243{color:rgb(163,20,20)} +pre#fancyvrb49{padding:5.69054pt;} +pre#fancyvrb49{ border-top: solid 0.4pt; } +pre#fancyvrb49{ border-left: solid 0.4pt; } +pre#fancyvrb49{ border-bottom: solid 0.4pt; } +pre#fancyvrb49{ border-right: solid 0.4pt; } +span#textcolor1244{color:rgb(0,127,0)} +span#textcolor1245{color:rgb(0,127,0)} +span#textcolor1246{color:rgb(0,127,0)} +span#textcolor1247{color:rgb(0,127,0)} +span#textcolor1248{color:rgb(0,127,0)} +span#textcolor1249{color:rgb(0,127,0)} +span#textcolor1250{color:rgb(0,127,0)} +span#textcolor1251{color:rgb(0,0,255)} +span#textcolor1252{color:rgb(0,0,255)} +span#textcolor1253{color:rgb(0,0,255)} +span#textcolor1254{color:rgb(0,127,0)} +span#textcolor1255{color:rgb(0,127,0)} +span#textcolor1256{color:rgb(0,127,0)} +span#textcolor1257{color:rgb(0,127,0)} +span#textcolor1258{color:rgb(0,127,0)} +span#textcolor1259{color:rgb(0,127,0)} +span#textcolor1260{color:rgb(0,0,255)} +span#textcolor1261{color:rgb(0,127,0)} +span#textcolor1262{color:rgb(0,127,0)} +span#textcolor1263{color:rgb(0,127,0)} +span#textcolor1264{color:rgb(0,0,255)} +span#textcolor1265{color:rgb(0,127,0)} +span#textcolor1266{color:rgb(0,127,0)} +span#textcolor1267{color:rgb(0,127,0)} +span#textcolor1268{color:rgb(0,127,0)} +span#textcolor1269{color:rgb(0,127,0)} +span#textcolor1270{color:rgb(0,127,0)} +span#textcolor1271{color:rgb(0,127,0)} +span#textcolor1272{color:rgb(0,127,0)} +span#textcolor1273{color:rgb(0,127,0)} +span#textcolor1274{color:rgb(0,127,0)} +span#textcolor1275{color:rgb(0,127,0)} +span#textcolor1276{color:rgb(0,127,0)} +span#textcolor1277{color:rgb(0,127,0)} +span#textcolor1278{color:rgb(0,127,0)} +span#textcolor1279{color:rgb(0,127,0)} +span#textcolor1280{color:rgb(0,127,0)} +span#textcolor1281{color:rgb(0,127,0)} +span#textcolor1282{color:rgb(0,0,255)} +span#textcolor1283{color:rgb(0,127,0)} +span#textcolor1284{color:rgb(0,127,0)} +span#textcolor1285{color:rgb(0,127,0)} +span#textcolor1286{color:rgb(0,127,0)} +span#textcolor1287{color:rgb(0,127,0)} +span#textcolor1288{color:rgb(0,127,0)} +span#textcolor1289{color:rgb(0,127,0)} +span#textcolor1290{color:rgb(0,127,0)} +span#textcolor1291{color:rgb(0,127,0)} +span#textcolor1292{color:rgb(0,0,255)} +span#textcolor1293{color:rgb(0,127,0)} +span#textcolor1294{color:rgb(0,127,0)} +span#textcolor1295{color:rgb(0,127,0)} +span#textcolor1296{color:rgb(0,127,0)} +span#textcolor1297{color:rgb(0,127,0)} +span#textcolor1298{color:rgb(0,127,0)} +span#textcolor1299{color:rgb(0,127,0)} +span#textcolor1300{color:rgb(0,127,0)} +span#textcolor1301{color:rgb(0,0,255)} +span#textcolor1302{color:rgb(0,0,255)} +pre#fancyvrb50{padding:5.69054pt;} +pre#fancyvrb50{ border-top: solid 0.4pt; } +pre#fancyvrb50{ border-left: solid 0.4pt; } +pre#fancyvrb50{ border-bottom: solid 0.4pt; } +pre#fancyvrb50{ border-right: solid 0.4pt; } +span#textcolor1303{color:rgb(0,127,0)} +span#textcolor1304{color:rgb(0,127,0)} +span#textcolor1305{color:rgb(0,127,0)} +span#textcolor1306{color:rgb(0,0,255)} +span#textcolor1307{color:rgb(0,127,0)} +span#textcolor1308{color:rgb(0,0,255)} +span#textcolor1309{color:rgb(0,127,0)} +span#textcolor1310{color:rgb(0,0,255)} +span#textcolor1311{color:rgb(0,127,0)} +span#textcolor1312{color:rgb(0,0,255)} +span#textcolor1313{color:rgb(0,127,0)} +span#textcolor1314{color:rgb(0,0,255)} +span#textcolor1315{color:rgb(0,127,0)} +span#textcolor1316{color:rgb(0,0,255)} +span#textcolor1317{color:rgb(0,127,0)} +span#textcolor1318{color:rgb(0,0,255)} +span#textcolor1319{color:rgb(0,127,0)} +span#textcolor1320{color:rgb(0,0,255)} +span#textcolor1321{color:rgb(43,145,175)} +span#textcolor1322{color:rgb(43,145,175)} +span#textcolor1323{color:rgb(43,145,175)} +span#textcolor1324{color:rgb(43,145,175)} +span#textcolor1325{color:rgb(0,127,0)} +span#textcolor1326{color:rgb(0,0,255)} +span#textcolor1327{color:rgb(0,0,255)} +span#textcolor1328{color:rgb(0,0,255)} +span#textcolor1329{color:rgb(0,0,255)} +span#textcolor1330{color:rgb(0,0,255)} +span#textcolor1331{color:rgb(0,0,255)} +span#textcolor1332{color:rgb(0,0,255)} +span#textcolor1333{color:rgb(0,0,255)} +span#textcolor1334{color:rgb(43,145,175)} +span#textcolor1335{color:rgb(43,145,175)} +span#textcolor1336{color:rgb(0,0,255)} +span#textcolor1337{color:rgb(43,145,175)} +span#textcolor1338{color:rgb(43,145,175)} +span#textcolor1339{color:rgb(0,0,255)} +span#textcolor1340{color:rgb(0,0,255)} +span#textcolor1341{color:rgb(0,0,255)} +span#textcolor1342{color:rgb(43,145,175)} +span#textcolor1343{color:rgb(0,0,255)} +span#textcolor1344{color:rgb(43,145,175)} +span#textcolor1345{color:rgb(43,145,175)} +span#textcolor1346{color:rgb(0,0,255)} +span#textcolor1347{color:rgb(43,145,175)} +span#textcolor1348{color:rgb(0,0,255)} +span#textcolor1349{color:rgb(43,145,175)} +span#textcolor1350{color:rgb(43,145,175)} +span#textcolor1351{color:rgb(43,145,175)} +span#textcolor1352{color:rgb(43,145,175)} +span#textcolor1353{color:rgb(0,0,255)} +span#textcolor1354{color:rgb(43,145,175)} +span#textcolor1355{color:rgb(43,145,175)} +span#textcolor1356{color:rgb(43,145,175)} +span#textcolor1357{color:rgb(0,0,255)} +span#textcolor1358{color:rgb(0,0,255)} +span#textcolor1359{color:rgb(0,0,255)} +span#textcolor1360{color:rgb(0,0,255)} +span#textcolor1361{color:rgb(0,127,0)} +span#textcolor1362{color:rgb(0,127,0)} +span#textcolor1363{color:rgb(0,127,0)} +span#textcolor1364{color:rgb(0,127,0)} +span#textcolor1365{color:rgb(0,127,0)} +span#textcolor1366{color:rgb(0,127,0)} +span#textcolor1367{color:rgb(0,127,0)} +span#textcolor1368{color:rgb(0,127,0)} +span#textcolor1369{color:rgb(0,127,0)} +span#textcolor1370{color:rgb(0,127,0)} +span#textcolor1371{color:rgb(0,0,255)} +span#textcolor1372{color:rgb(43,145,175)} +span#textcolor1373{color:rgb(0,0,255)} +span#textcolor1374{color:rgb(0,0,255)} +span#textcolor1375{color:rgb(163,20,20)} +span#textcolor1376{color:rgb(163,20,20)} +span#textcolor1377{color:rgb(163,20,20)} +span#textcolor1378{color:rgb(0,0,255)} +span#textcolor1379{color:rgb(0,0,255)} +span#textcolor1380{color:rgb(0,127,0)} +span#textcolor1381{color:rgb(0,127,0)} +span#textcolor1382{color:rgb(0,127,0)} +span#textcolor1383{color:rgb(0,127,0)} +span#textcolor1384{color:rgb(0,127,0)} +span#textcolor1385{color:rgb(0,127,0)} +span#textcolor1386{color:rgb(0,0,255)} +span#textcolor1387{color:rgb(43,145,175)} +span#textcolor1388{color:rgb(0,0,255)} +span#textcolor1389{color:rgb(0,0,255)} +span#textcolor1390{color:rgb(0,0,255)} +span#textcolor1391{color:rgb(0,0,255)} +span#textcolor1392{color:rgb(43,145,175)} +span#textcolor1393{color:rgb(0,0,255)} +span#textcolor1394{color:rgb(0,0,255)} +span#textcolor1395{color:rgb(0,127,0)} +span#textcolor1396{color:rgb(0,127,0)} +span#textcolor1397{color:rgb(0,127,0)} +span#textcolor1398{color:rgb(0,127,0)} +span#textcolor1399{color:rgb(0,0,255)} +span#textcolor1400{color:rgb(0,0,255)} +span#textcolor1401{color:rgb(0,0,255)} +span#textcolor1402{color:rgb(43,145,175)} +span#textcolor1403{color:rgb(0,0,255)} +span#textcolor1404{color:rgb(43,145,175)} +span#textcolor1405{color:rgb(43,145,175)} +span#textcolor1406{color:rgb(0,0,255)} +span#textcolor1407{color:rgb(43,145,175)} +span#textcolor1408{color:rgb(43,145,175)} +span#textcolor1409{color:rgb(43,145,175)} +span#textcolor1410{color:rgb(43,145,175)} +span#textcolor1411{color:rgb(0,0,255)} +span#textcolor1412{color:rgb(0,0,255)} +span#textcolor1413{color:rgb(0,0,255)} +span#textcolor1414{color:rgb(0,0,255)} +span#textcolor1415{color:rgb(0,0,255)} +span#textcolor1416{color:rgb(43,145,175)} +span#textcolor1417{color:rgb(0,0,255)} +span#textcolor1418{color:rgb(0,0,255)} +span#textcolor1419{color:rgb(163,20,20)} +span#textcolor1420{color:rgb(163,20,20)} +span#textcolor1421{color:rgb(163,20,20)} +span#textcolor1422{color:rgb(0,0,255)} +span#textcolor1423{color:rgb(0,0,255)} +span#textcolor1424{color:rgb(0,0,255)} +span#textcolor1425{color:rgb(43,145,175)} +span#textcolor1426{color:rgb(0,0,255)} +span#textcolor1427{color:rgb(0,0,255)} +span#textcolor1428{color:rgb(0,0,255)} +span#textcolor1429{color:rgb(163,20,20)} +span#textcolor1430{color:rgb(163,20,20)} +span#textcolor1431{color:rgb(163,20,20)} +span#textcolor1432{color:rgb(0,0,255)} +span#textcolor1433{color:rgb(0,0,255)} +span#textcolor1434{color:rgb(0,0,255)} +span#textcolor1435{color:rgb(0,0,255)} +span#textcolor1436{color:rgb(0,0,255)} +span#textcolor1437{color:rgb(0,0,255)} +span#textcolor1438{color:rgb(0,0,255)} +span#textcolor1439{color:rgb(43,145,175)} +span#textcolor1440{color:rgb(43,145,175)} +span#textcolor1441{color:rgb(43,145,175)} +span#textcolor1442{color:rgb(43,145,175)} +span#textcolor1443{color:rgb(43,145,175)} +span#textcolor1444{color:rgb(0,0,255)} +span#textcolor1445{color:rgb(0,0,255)} +span#textcolor1446{color:rgb(0,0,255)} +span#textcolor1447{color:rgb(0,0,255)} +span#textcolor1448{color:rgb(163,20,20)} +span#textcolor1449{color:rgb(163,20,20)} +span#textcolor1450{color:rgb(163,20,20)} +span#textcolor1451{color:rgb(0,0,255)} +span#textcolor1452{color:rgb(0,0,255)} +span#textcolor1453{color:rgb(0,0,255)} +span#textcolor1454{color:rgb(0,0,255)} +span#textcolor1455{color:rgb(0,0,255)} +span#textcolor1456{color:rgb(43,145,175)} +span#textcolor1457{color:rgb(43,145,175)} +span#textcolor1458{color:rgb(43,145,175)} +span#textcolor1459{color:rgb(163,20,20)} +span#textcolor1460{color:rgb(163,20,20)} +span#textcolor1461{color:rgb(163,20,20)} +span#textcolor1462{color:rgb(163,20,20)} +span#textcolor1463{color:rgb(163,20,20)} +pre#fancyvrb51{padding:5.69054pt;} +pre#fancyvrb51{ border-top: solid 0.4pt; } +pre#fancyvrb51{ border-left: solid 0.4pt; } +pre#fancyvrb51{ border-bottom: solid 0.4pt; } +pre#fancyvrb51{ border-right: solid 0.4pt; } +span#textcolor1464{color:rgb(0,127,0)} +span#textcolor1465{color:rgb(0,127,0)} +span#textcolor1466{color:rgb(0,127,0)} +span#textcolor1467{color:rgb(0,127,0)} +span#textcolor1468{color:rgb(0,127,0)} +span#textcolor1469{color:rgb(0,127,0)} +span#textcolor1470{color:rgb(0,127,0)} +span#textcolor1471{color:rgb(0,127,0)} +span#textcolor1472{color:rgb(0,127,0)} +span#textcolor1473{color:rgb(0,127,0)} +span#textcolor1474{color:rgb(0,127,0)} +span#textcolor1475{color:rgb(0,0,255)} +span#textcolor1476{color:rgb(0,127,0)} +span#textcolor1477{color:rgb(0,0,255)} +span#textcolor1478{color:rgb(0,127,0)} +span#textcolor1479{color:rgb(0,0,255)} +span#textcolor1480{color:rgb(0,127,0)} +span#textcolor1481{color:rgb(0,0,255)} +span#textcolor1482{color:rgb(0,127,0)} +span#textcolor1483{color:rgb(0,0,255)} +span#textcolor1484{color:rgb(0,127,0)} +span#textcolor1485{color:rgb(0,0,255)} +span#textcolor1486{color:rgb(0,127,0)} +span#textcolor1487{color:rgb(0,127,0)} +span#textcolor1488{color:rgb(0,127,0)} +span#textcolor1489{color:rgb(0,127,0)} +span#textcolor1490{color:rgb(0,127,0)} +span#textcolor1491{color:rgb(0,0,255)} +span#textcolor1492{color:rgb(0,127,0)} +span#textcolor1493{color:rgb(0,0,255)} +span#textcolor1494{color:rgb(0,127,0)} +span#textcolor1495{color:rgb(43,145,175)} +span#textcolor1496{color:rgb(43,145,175)} +span#textcolor1497{color:rgb(43,145,175)} +span#textcolor1498{color:rgb(43,145,175)} +span#textcolor1499{color:rgb(0,127,0)} +span#textcolor1500{color:rgb(0,127,0)} +span#textcolor1501{color:rgb(0,127,0)} +span#textcolor1502{color:rgb(0,127,0)} +span#textcolor1503{color:rgb(0,0,255)} +span#textcolor1504{color:rgb(43,145,175)} +span#textcolor1505{color:rgb(43,145,175)} +span#textcolor1506{color:rgb(0,127,0)} +span#textcolor1507{color:rgb(0,127,0)} +span#textcolor1508{color:rgb(0,127,0)} +span#textcolor1509{color:rgb(0,127,0)} +span#textcolor1510{color:rgb(0,127,0)} +span#textcolor1511{color:rgb(0,127,0)} +span#textcolor1512{color:rgb(0,127,0)} +span#textcolor1513{color:rgb(0,127,0)} +span#textcolor1514{color:rgb(0,127,0)} +span#textcolor1515{color:rgb(0,127,0)} +span#textcolor1516{color:rgb(0,127,0)} +span#textcolor1517{color:rgb(0,127,0)} +span#textcolor1518{color:rgb(0,127,0)} +span#textcolor1519{color:rgb(0,0,255)} +span#textcolor1520{color:rgb(43,145,175)} +span#textcolor1521{color:rgb(43,145,175)} +span#textcolor1522{color:rgb(43,145,175)} +span#textcolor1523{color:rgb(0,127,0)} +span#textcolor1524{color:rgb(0,127,0)} +span#textcolor1525{color:rgb(0,127,0)} +span#textcolor1526{color:rgb(0,127,0)} +span#textcolor1527{color:rgb(0,127,0)} +span#textcolor1528{color:rgb(0,127,0)} +span#textcolor1529{color:rgb(0,127,0)} +span#textcolor1530{color:rgb(0,127,0)} +span#textcolor1531{color:rgb(0,127,0)} +span#textcolor1532{color:rgb(0,127,0)} +span#textcolor1533{color:rgb(0,127,0)} +span#textcolor1534{color:rgb(0,127,0)} +span#textcolor1535{color:rgb(0,127,0)} +span#textcolor1536{color:rgb(0,127,0)} +span#textcolor1537{color:rgb(43,145,175)} +span#textcolor1538{color:rgb(0,0,255)} +span#textcolor1539{color:rgb(43,145,175)} +span#textcolor1540{color:rgb(43,145,175)} +span#textcolor1541{color:rgb(43,145,175)} +span#textcolor1542{color:rgb(43,145,175)} +span#textcolor1543{color:rgb(43,145,175)} +span#textcolor1544{color:rgb(0,127,0)} +span#textcolor1545{color:rgb(0,127,0)} +span#textcolor1546{color:rgb(0,127,0)} +span#textcolor1547{color:rgb(163,20,20)} +span#textcolor1548{color:rgb(0,0,255)} +span#textcolor1549{color:rgb(163,20,20)} +span#textcolor1550{color:rgb(0,0,255)} +span#textcolor1551{color:rgb(163,20,20)} +span#textcolor1552{color:rgb(163,20,20)} +span#textcolor1553{color:rgb(163,20,20)} +span#textcolor1554{color:rgb(0,127,0)} +span#textcolor1555{color:rgb(0,127,0)} +span#textcolor1556{color:rgb(0,127,0)} +span#textcolor1557{color:rgb(0,127,0)} +span#textcolor1558{color:rgb(0,0,255)} +span#textcolor1559{color:rgb(0,0,255)} +span#textcolor1560{color:rgb(43,145,175)} +span#textcolor1561{color:rgb(43,145,175)} +span#textcolor1562{color:rgb(43,145,175)} +span#textcolor1563{color:rgb(43,145,175)} +span#textcolor1564{color:rgb(43,145,175)} +span#textcolor1565{color:rgb(43,145,175)} +span#textcolor1566{color:rgb(43,145,175)} +span#textcolor1567{color:rgb(43,145,175)} +span#textcolor1568{color:rgb(0,0,255)} +span#textcolor1569{color:rgb(43,145,175)} +span#textcolor1570{color:rgb(43,145,175)} +span#textcolor1571{color:rgb(0,0,255)} +span#textcolor1572{color:rgb(43,145,175)} +span#textcolor1573{color:rgb(43,145,175)} +span#textcolor1574{color:rgb(0,0,255)} +span#textcolor1575{color:rgb(0,0,255)} +span#textcolor1576{color:rgb(43,145,175)} +span#textcolor1577{color:rgb(0,0,255)} +span#textcolor1578{color:rgb(0,0,255)} +span#textcolor1579{color:rgb(43,145,175)} +span#textcolor1580{color:rgb(43,145,175)} +span#textcolor1581{color:rgb(0,0,255)} +span#textcolor1582{color:rgb(0,0,255)} +span#textcolor1583{color:rgb(0,127,0)} +span#textcolor1584{color:rgb(43,145,175)} +span#textcolor1585{color:rgb(0,127,0)} +span#textcolor1586{color:rgb(43,145,175)} +span#textcolor1587{color:rgb(43,145,175)} +span#textcolor1588{color:rgb(163,20,20)} +span#textcolor1589{color:rgb(163,20,20)} +span#textcolor1590{color:rgb(163,20,20)} +span#textcolor1591{color:rgb(0,0,255)} +span#textcolor1592{color:rgb(0,0,255)} +span#textcolor1593{color:rgb(43,145,175)} +span#textcolor1594{color:rgb(43,145,175)} +span#textcolor1595{color:rgb(0,0,255)} +span#textcolor1596{color:rgb(0,0,255)} +span#textcolor1597{color:rgb(0,127,0)} +span#textcolor1598{color:rgb(0,127,0)} +span#textcolor1599{color:rgb(0,127,0)} +span#textcolor1600{color:rgb(0,0,255)} +span#textcolor1601{color:rgb(43,145,175)} +span#textcolor1602{color:rgb(43,145,175)} +span#textcolor1603{color:rgb(163,20,20)} +span#textcolor1604{color:rgb(163,20,20)} +span#textcolor1605{color:rgb(163,20,20)} +span#textcolor1606{color:rgb(163,20,20)} +span#textcolor1607{color:rgb(163,20,20)} +span#textcolor1608{color:rgb(163,20,20)} +span#textcolor1609{color:rgb(163,20,20)} +span#textcolor1610{color:rgb(163,20,20)} +span#textcolor1611{color:rgb(43,145,175)} +span#textcolor1612{color:rgb(43,145,175)} +span#textcolor1613{color:rgb(163,20,20)} +pre#fancyvrb52{padding:5.69054pt;} +pre#fancyvrb52{ border-top: solid 0.4pt; } +pre#fancyvrb52{ border-left: solid 0.4pt; } +pre#fancyvrb52{ border-bottom: solid 0.4pt; } +pre#fancyvrb52{ border-right: solid 0.4pt; } +pre#fancyvrb53{padding:5.69054pt;} +pre#fancyvrb53{ border-top: solid 0.4pt; } +pre#fancyvrb53{ border-left: solid 0.4pt; } +pre#fancyvrb53{ border-bottom: solid 0.4pt; } +pre#fancyvrb53{ border-right: solid 0.4pt; } +span#textcolor1614{color:rgb(0,127,0)} +span#textcolor1615{color:rgb(0,127,0)} +span#textcolor1616{color:rgb(0,127,0)} +span#textcolor1617{color:rgb(0,127,0)} +span#textcolor1618{color:rgb(0,0,255)} +span#textcolor1619{color:rgb(0,127,0)} +span#textcolor1620{color:rgb(0,0,255)} +span#textcolor1621{color:rgb(0,127,0)} +span#textcolor1622{color:rgb(0,0,255)} +span#textcolor1623{color:rgb(0,127,0)} +span#textcolor1624{color:rgb(0,0,255)} +span#textcolor1625{color:rgb(0,127,0)} +#colorbox1626{border: solid 1px rgb(255,0,0);} +#colorbox1626{background-color: rgb(255,255,255);} +span#textcolor1627{color:rgb(0,0,255)} +span#textcolor1628{color:rgb(0,127,0)} +span#textcolor1629{color:rgb(0,0,255)} +span#textcolor1630{color:rgb(0,127,0)} +span#textcolor1631{color:rgb(0,0,255)} +span#textcolor1632{color:rgb(0,0,255)} +span#textcolor1633{color:rgb(0,0,255)} +span#textcolor1634{color:rgb(0,127,0)} +span#textcolor1635{color:rgb(0,127,0)} +span#textcolor1636{color:rgb(0,127,0)} +span#textcolor1637{color:rgb(0,127,0)} +span#textcolor1638{color:rgb(0,127,0)} +span#textcolor1639{color:rgb(0,127,0)} +span#textcolor1640{color:rgb(0,127,0)} +span#textcolor1641{color:rgb(0,0,255)} +span#textcolor1642{color:rgb(0,0,255)} +span#textcolor1643{color:rgb(43,145,175)} +span#textcolor1644{color:rgb(0,0,255)} +span#textcolor1645{color:rgb(0,0,255)} +span#textcolor1646{color:rgb(0,0,255)} +span#textcolor1647{color:rgb(0,127,0)} +span#textcolor1648{color:rgb(0,127,0)} +span#textcolor1649{color:rgb(0,127,0)} +span#textcolor1650{color:rgb(0,127,0)} +span#textcolor1651{color:rgb(0,127,0)} +span#textcolor1652{color:rgb(0,0,255)} +span#textcolor1653{color:rgb(43,145,175)} +span#textcolor1654{color:rgb(0,0,255)} +span#textcolor1655{color:rgb(0,127,0)} +span#textcolor1656{color:rgb(43,145,175)} +span#textcolor1657{color:rgb(0,127,0)} +span#textcolor1658{color:rgb(0,127,0)} +#colorbox1659{border: solid 1px rgb(255,0,0);} +#colorbox1659{background-color: rgb(255,255,255);} +span#textcolor1660{color:rgb(43,145,175)} +span#textcolor1661{color:rgb(0,127,0)} +span#textcolor1662{color:rgb(0,0,255)} +span#textcolor1663{color:rgb(43,145,175)} +span#textcolor1664{color:rgb(43,145,175)} +span#textcolor1665{color:rgb(43,145,175)} +span#textcolor1666{color:rgb(0,127,0)} +span#textcolor1667{color:rgb(0,127,0)} +span#textcolor1668{color:rgb(0,127,0)} +span#textcolor1669{color:rgb(0,127,0)} +span#textcolor1670{color:rgb(0,0,255)} +span#textcolor1671{color:rgb(0,0,255)} +span#textcolor1672{color:rgb(0,127,0)} +span#textcolor1673{color:rgb(0,127,0)} +span#textcolor1674{color:rgb(0,127,0)} +span#textcolor1675{color:rgb(0,127,0)} +span#textcolor1676{color:rgb(163,20,20)} +span#textcolor1677{color:rgb(163,20,20)} +span#textcolor1678{color:rgb(163,20,20)} +span#textcolor1679{color:rgb(0,0,255)} +span#textcolor1680{color:rgb(0,0,255)} +span#textcolor1681{color:rgb(0,127,0)} +span#textcolor1682{color:rgb(0,127,0)} +span#textcolor1683{color:rgb(0,127,0)} +span#textcolor1684{color:rgb(0,127,0)} +span#textcolor1685{color:rgb(0,127,0)} +span#textcolor1686{color:rgb(0,0,255)} +span#textcolor1687{color:rgb(43,145,175)} +span#textcolor1688{color:rgb(0,0,255)} +span#textcolor1689{color:rgb(0,127,0)} +span#textcolor1690{color:rgb(0,0,255)} +span#textcolor1691{color:rgb(43,145,175)} +span#textcolor1692{color:rgb(0,127,0)} +span#textcolor1693{color:rgb(43,145,175)} +span#textcolor1694{color:rgb(0,127,0)} +span#textcolor1695{color:rgb(0,127,0)} +span#textcolor1696{color:rgb(43,145,175)} +span#textcolor1697{color:rgb(0,127,0)} +span#textcolor1698{color:rgb(0,127,0)} +span#textcolor1699{color:rgb(0,127,0)} +span#textcolor1700{color:rgb(0,127,0)} +span#textcolor1701{color:rgb(0,0,255)} +span#textcolor1702{color:rgb(0,127,0)} +span#textcolor1703{color:rgb(0,127,0)} +span#textcolor1704{color:rgb(0,127,0)} +span#textcolor1705{color:rgb(163,20,20)} +span#textcolor1706{color:rgb(0,127,0)} +span#textcolor1707{color:rgb(0,127,0)} +span#textcolor1708{color:rgb(0,127,0)} +span#textcolor1709{color:rgb(0,0,255)} +span#textcolor1710{color:rgb(0,127,0)} +span#textcolor1711{color:rgb(0,127,0)} +span#textcolor1712{color:rgb(0,127,0)} +span#textcolor1713{color:rgb(43,145,175)} +span#textcolor1714{color:rgb(0,127,0)} +span#textcolor1715{color:rgb(0,127,0)} +span#textcolor1716{color:rgb(0,127,0)} +span#textcolor1717{color:rgb(0,127,0)} +span#textcolor1718{color:rgb(0,127,0)} +span#textcolor1719{color:rgb(0,127,0)} +span#textcolor1720{color:rgb(0,0,255)} +span#textcolor1721{color:rgb(43,145,175)} +span#textcolor1722{color:rgb(0,0,255)} +span#textcolor1723{color:rgb(0,0,255)} +span#textcolor1724{color:rgb(0,127,0)} +span#textcolor1725{color:rgb(0,127,0)} +span#textcolor1726{color:rgb(0,127,0)} +span#textcolor1727{color:rgb(0,127,0)} +span#textcolor1728{color:rgb(0,127,0)} +span#textcolor1729{color:rgb(0,127,0)} +span#textcolor1730{color:rgb(0,0,255)} +span#textcolor1731{color:rgb(0,0,255)} +span#textcolor1732{color:rgb(0,127,0)} +span#textcolor1733{color:rgb(0,127,0)} +span#textcolor1734{color:rgb(0,127,0)} +span#textcolor1735{color:rgb(0,127,0)} +span#textcolor1736{color:rgb(0,127,0)} +span#textcolor1737{color:rgb(0,127,0)} +span#textcolor1738{color:rgb(0,127,0)} +span#textcolor1739{color:rgb(0,127,0)} +span#textcolor1740{color:rgb(0,0,255)} +span#textcolor1741{color:rgb(43,145,175)} +span#textcolor1742{color:rgb(0,127,0)} +span#textcolor1743{color:rgb(0,127,0)} +span#textcolor1744{color:rgb(0,127,0)} +span#textcolor1745{color:rgb(0,127,0)} +span#textcolor1746{color:rgb(0,127,0)} +span#textcolor1747{color:rgb(0,127,0)} +span#textcolor1748{color:rgb(0,127,0)} +span#textcolor1749{color:rgb(0,127,0)} +span#textcolor1750{color:rgb(0,127,0)} +span#textcolor1751{color:rgb(0,127,0)} +span#textcolor1752{color:rgb(0,127,0)} +span#textcolor1753{color:rgb(0,127,0)} +span#textcolor1754{color:rgb(0,127,0)} +span#textcolor1755{color:rgb(0,127,0)} +span#textcolor1756{color:rgb(0,127,0)} +span#textcolor1757{color:rgb(0,127,0)} +span#textcolor1758{color:rgb(0,127,0)} +span#textcolor1759{color:rgb(0,127,0)} +span#textcolor1760{color:rgb(0,127,0)} +span#textcolor1761{color:rgb(0,127,0)} +span#textcolor1762{color:rgb(0,127,0)} +span#textcolor1763{color:rgb(0,127,0)} +span#textcolor1764{color:rgb(0,127,0)} +span#textcolor1765{color:rgb(0,127,0)} +span#textcolor1766{color:rgb(0,127,0)} +span#textcolor1767{color:rgb(0,127,0)} +span#textcolor1768{color:rgb(0,127,0)} +span#textcolor1769{color:rgb(0,0,255)} +span#textcolor1770{color:rgb(0,0,255)} +span#textcolor1771{color:rgb(0,127,0)} +span#textcolor1772{color:rgb(0,127,0)} +span#textcolor1773{color:rgb(0,127,0)} +span#textcolor1774{color:rgb(0,127,0)} +span#textcolor1775{color:rgb(0,127,0)} +span#textcolor1776{color:rgb(0,127,0)} +span#textcolor1777{color:rgb(0,127,0)} +span#textcolor1778{color:rgb(0,127,0)} +span#textcolor1779{color:rgb(0,127,0)} +span#textcolor1780{color:rgb(0,127,0)} +span#textcolor1781{color:rgb(0,0,255)} +span#textcolor1782{color:rgb(0,127,0)} +span#textcolor1783{color:rgb(0,127,0)} +span#textcolor1784{color:rgb(0,127,0)} +span#textcolor1785{color:rgb(0,127,0)} +span#textcolor1786{color:rgb(0,127,0)} +span#textcolor1787{color:rgb(0,127,0)} +span#textcolor1788{color:rgb(0,0,255)} +span#textcolor1789{color:rgb(0,127,0)} +span#textcolor1790{color:rgb(0,127,0)} +span#textcolor1791{color:rgb(0,127,0)} +span#textcolor1792{color:rgb(0,127,0)} +span#textcolor1793{color:rgb(43,145,175)} +span#textcolor1794{color:rgb(0,0,255)} +span#textcolor1795{color:rgb(0,0,255)} +span#textcolor1796{color:rgb(0,127,0)} +span#textcolor1797{color:rgb(0,127,0)} +span#textcolor1798{color:rgb(0,127,0)} +span#textcolor1799{color:rgb(0,127,0)} +span#textcolor1800{color:rgb(0,127,0)} +span#textcolor1801{color:rgb(0,127,0)} +span#textcolor1802{color:rgb(0,127,0)} +span#textcolor1803{color:rgb(0,127,0)} +span#textcolor1804{color:rgb(0,127,0)} +span#textcolor1805{color:rgb(0,127,0)} +span#textcolor1806{color:rgb(0,0,255)} +span#textcolor1807{color:rgb(0,127,0)} +span#textcolor1808{color:rgb(0,127,0)} +span#textcolor1809{color:rgb(0,127,0)} +span#textcolor1810{color:rgb(0,127,0)} +span#textcolor1811{color:rgb(0,127,0)} +span#textcolor1812{color:rgb(0,127,0)} +span#textcolor1813{color:rgb(0,127,0)} +span#textcolor1814{color:rgb(0,127,0)} +span#textcolor1815{color:rgb(0,127,0)} +span#textcolor1816{color:rgb(0,127,0)} +span#textcolor1817{color:rgb(0,0,255)} +span#textcolor1818{color:rgb(0,0,255)} +span#textcolor1819{color:rgb(0,0,255)} +span#textcolor1820{color:rgb(0,0,255)} +span#textcolor1821{color:rgb(0,127,0)} +span#textcolor1822{color:rgb(0,127,0)} +span#textcolor1823{color:rgb(0,127,0)} +span#textcolor1824{color:rgb(0,127,0)} +span#textcolor1825{color:rgb(0,0,255)} +span#textcolor1826{color:rgb(0,0,255)} +span#textcolor1827{color:rgb(0,0,255)} +span#textcolor1828{color:rgb(0,0,255)} +span#textcolor1829{color:rgb(0,0,255)} +span#textcolor1830{color:rgb(0,127,0)} +span#textcolor1831{color:rgb(0,127,0)} +span#textcolor1832{color:rgb(0,127,0)} +span#textcolor1833{color:rgb(0,127,0)} +span#textcolor1834{color:rgb(0,127,0)} +span#textcolor1835{color:rgb(0,127,0)} +span#textcolor1836{color:rgb(43,145,175)} +span#textcolor1837{color:rgb(0,0,255)} +span#textcolor1838{color:rgb(163,20,20)} +span#textcolor1839{color:rgb(163,20,20)} +span#textcolor1840{color:rgb(163,20,20)} +span#textcolor1841{color:rgb(0,0,255)} +span#textcolor1842{color:rgb(163,20,20)} +span#textcolor1843{color:rgb(163,20,20)} +span#textcolor1844{color:rgb(163,20,20)} +span#textcolor1845{color:rgb(0,0,255)} +span#textcolor1846{color:rgb(0,127,0)} +span#textcolor1847{color:rgb(0,127,0)} +span#textcolor1848{color:rgb(0,127,0)} +span#textcolor1849{color:rgb(0,127,0)} +span#textcolor1850{color:rgb(0,127,0)} +span#textcolor1851{color:rgb(0,127,0)} +span#textcolor1852{color:rgb(43,145,175)} +span#textcolor1853{color:rgb(163,20,20)} +span#textcolor1854{color:rgb(163,20,20)} +span#textcolor1855{color:rgb(163,20,20)} +span#textcolor1856{color:rgb(163,20,20)} +pre#fancyvrb54{padding:5.69054pt;} +pre#fancyvrb54{ border-top: solid 0.4pt; } +pre#fancyvrb54{ border-left: solid 0.4pt; } +pre#fancyvrb54{ border-bottom: solid 0.4pt; } +pre#fancyvrb54{ border-right: solid 0.4pt; } +span#textcolor1857{color:rgb(0,127,0)} +span#textcolor1858{color:rgb(0,127,0)} +span#textcolor1859{color:rgb(0,127,0)} +span#textcolor1860{color:rgb(0,127,0)} +span#textcolor1861{color:rgb(0,0,255)} +span#textcolor1862{color:rgb(0,127,0)} +span#textcolor1863{color:rgb(0,0,255)} +span#textcolor1864{color:rgb(0,127,0)} +span#textcolor1865{color:rgb(0,0,255)} +span#textcolor1866{color:rgb(0,127,0)} +span#textcolor1867{color:rgb(0,0,255)} +span#textcolor1868{color:rgb(0,127,0)} +span#textcolor1869{color:rgb(0,0,255)} +span#textcolor1870{color:rgb(0,127,0)} +span#textcolor1871{color:rgb(0,0,255)} +span#textcolor1872{color:rgb(43,145,175)} +span#textcolor1873{color:rgb(43,145,175)} +span#textcolor1874{color:rgb(43,145,175)} +span#textcolor1875{color:rgb(43,145,175)} +span#textcolor1876{color:rgb(0,127,0)} +span#textcolor1877{color:rgb(43,145,175)} +span#textcolor1878{color:rgb(0,127,0)} +span#textcolor1879{color:rgb(43,145,175)} +span#textcolor1880{color:rgb(0,127,0)} +span#textcolor1881{color:rgb(0,127,0)} +span#textcolor1882{color:rgb(0,0,255)} +span#textcolor1883{color:rgb(163,20,20)} +span#textcolor1884{color:rgb(163,20,20)} +span#textcolor1885{color:rgb(163,20,20)} +span#textcolor1886{color:rgb(163,20,20)} +span#textcolor1887{color:rgb(0,127,0)} +span#textcolor1888{color:rgb(0,127,0)} +span#textcolor1889{color:rgb(0,0,255)} +span#textcolor1890{color:rgb(0,0,255)} +span#textcolor1891{color:rgb(163,20,20)} +span#textcolor1892{color:rgb(0,0,255)} +span#textcolor1893{color:rgb(163,20,20)} +span#textcolor1894{color:rgb(0,127,0)} +span#textcolor1895{color:rgb(0,0,255)} +span#textcolor1896{color:rgb(43,145,175)} +span#textcolor1897{color:rgb(0,127,0)} +span#textcolor1898{color:rgb(0,127,0)} +span#textcolor1899{color:rgb(0,0,255)} +span#textcolor1900{color:rgb(0,0,255)} +span#textcolor1901{color:rgb(163,20,20)} +span#textcolor1902{color:rgb(0,0,255)} +span#textcolor1903{color:rgb(163,20,20)} +span#textcolor1904{color:rgb(0,127,0)} +span#textcolor1905{color:rgb(0,0,255)} +span#textcolor1906{color:rgb(0,0,255)} +span#textcolor1907{color:rgb(0,127,0)} +span#textcolor1908{color:rgb(0,0,255)} +span#textcolor1909{color:rgb(0,0,255)} +pre#fancyvrb55{padding:5.69054pt;} +pre#fancyvrb55{ border-top: solid 0.4pt; } +pre#fancyvrb55{ border-left: solid 0.4pt; } +pre#fancyvrb55{ border-bottom: solid 0.4pt; } +pre#fancyvrb55{ border-right: solid 0.4pt; } +span#textcolor1910{color:rgb(0,127,0)} +span#textcolor1911{color:rgb(0,127,0)} +span#textcolor1912{color:rgb(0,127,0)} +span#textcolor1913{color:rgb(0,0,255)} +span#textcolor1914{color:rgb(0,127,0)} +span#textcolor1915{color:rgb(0,0,255)} +span#textcolor1916{color:rgb(0,127,0)} +span#textcolor1917{color:rgb(0,0,255)} +span#textcolor1918{color:rgb(0,127,0)} +span#textcolor1919{color:rgb(0,0,255)} +span#textcolor1920{color:rgb(0,127,0)} +span#textcolor1921{color:rgb(0,0,255)} +span#textcolor1922{color:rgb(0,127,0)} +span#textcolor1923{color:rgb(0,0,255)} +span#textcolor1924{color:rgb(0,0,255)} +span#textcolor1925{color:rgb(0,0,255)} +span#textcolor1926{color:rgb(0,0,255)} +span#textcolor1927{color:rgb(0,0,255)} +span#textcolor1928{color:rgb(43,145,175)} +span#textcolor1929{color:rgb(43,145,175)} +span#textcolor1930{color:rgb(163,20,20)} +span#textcolor1931{color:rgb(163,20,20)} +span#textcolor1932{color:rgb(163,20,20)} +span#textcolor1933{color:rgb(0,0,255)} +span#textcolor1934{color:rgb(43,145,175)} +span#textcolor1935{color:rgb(43,145,175)} +span#textcolor1936{color:rgb(163,20,20)} +span#textcolor1937{color:rgb(163,20,20)} +span#textcolor1938{color:rgb(163,20,20)} +span#textcolor1939{color:rgb(0,0,255)} +span#textcolor1940{color:rgb(43,145,175)} +span#textcolor1941{color:rgb(43,145,175)} +span#textcolor1942{color:rgb(0,0,255)} +span#textcolor1943{color:rgb(0,0,255)} +span#textcolor1944{color:rgb(163,20,20)} +span#textcolor1945{color:rgb(163,20,20)} +span#textcolor1946{color:rgb(163,20,20)} +span#textcolor1947{color:rgb(163,20,20)} +span#textcolor1948{color:rgb(0,0,255)} +span#textcolor1949{color:rgb(0,0,255)} +span#textcolor1950{color:rgb(163,20,20)} +span#textcolor1951{color:rgb(0,0,255)} +span#textcolor1952{color:rgb(0,0,255)} +span#textcolor1953{color:rgb(0,0,255)} +span#textcolor1954{color:rgb(0,0,255)} +span#textcolor1955{color:rgb(43,145,175)} +span#textcolor1956{color:rgb(43,145,175)} +span#textcolor1957{color:rgb(163,20,20)} +span#textcolor1958{color:rgb(163,20,20)} +span#textcolor1959{color:rgb(163,20,20)} +span#textcolor1960{color:rgb(163,20,20)} +span#textcolor1961{color:rgb(163,20,20)} +pre#fancyvrb56{padding:5.69054pt;} +pre#fancyvrb56{ border-top: solid 0.4pt; } +pre#fancyvrb56{ border-left: solid 0.4pt; } +pre#fancyvrb56{ border-bottom: solid 0.4pt; } +pre#fancyvrb56{ border-right: solid 0.4pt; } +span#textcolor1962{color:rgb(0,127,0)} +span#textcolor1963{color:rgb(0,127,0)} +span#textcolor1964{color:rgb(0,127,0)} +span#textcolor1965{color:rgb(0,0,255)} +span#textcolor1966{color:rgb(0,127,0)} +span#textcolor1967{color:rgb(0,0,255)} +span#textcolor1968{color:rgb(0,127,0)} +span#textcolor1969{color:rgb(0,0,255)} +span#textcolor1970{color:rgb(0,127,0)} +span#textcolor1971{color:rgb(0,0,255)} +span#textcolor1972{color:rgb(0,127,0)} +span#textcolor1973{color:rgb(0,0,255)} +span#textcolor1974{color:rgb(43,145,175)} +span#textcolor1975{color:rgb(43,145,175)} +span#textcolor1976{color:rgb(43,145,175)} +span#textcolor1977{color:rgb(163,20,20)} +span#textcolor1978{color:rgb(163,20,20)} +span#textcolor1979{color:rgb(163,20,20)} +span#textcolor1980{color:rgb(0,0,255)} +span#textcolor1981{color:rgb(163,20,20)} +span#textcolor1982{color:rgb(163,20,20)} +span#textcolor1983{color:rgb(163,20,20)} +span#textcolor1984{color:rgb(0,0,255)} +span#textcolor1985{color:rgb(163,20,20)} +span#textcolor1986{color:rgb(163,20,20)} +span#textcolor1987{color:rgb(163,20,20)} +span#textcolor1988{color:rgb(163,20,20)} +span#textcolor1989{color:rgb(163,20,20)} +span#textcolor1990{color:rgb(163,20,20)} +span#textcolor1991{color:rgb(0,0,255)} +span#textcolor1992{color:rgb(163,20,20)} +span#textcolor1993{color:rgb(163,20,20)} +span#textcolor1994{color:rgb(163,20,20)} +span#textcolor1995{color:rgb(0,0,255)} +span#textcolor1996{color:rgb(0,0,255)} +span#textcolor1997{color:rgb(43,145,175)} +span#textcolor1998{color:rgb(43,145,175)} +span#textcolor1999{color:rgb(163,20,20)} +span#textcolor2000{color:rgb(163,20,20)} +span#textcolor2001{color:rgb(163,20,20)} +span#textcolor2002{color:rgb(163,20,20)} +span#textcolor2003{color:rgb(163,20,20)} +pre#fancyvrb57{padding:5.69054pt;} +pre#fancyvrb57{ border-top: solid 0.4pt; } +pre#fancyvrb57{ border-left: solid 0.4pt; } +pre#fancyvrb57{ border-bottom: solid 0.4pt; } +pre#fancyvrb57{ border-right: solid 0.4pt; } +span#textcolor2004{color:rgb(0,127,0)} +span#textcolor2005{color:rgb(0,127,0)} +span#textcolor2006{color:rgb(0,127,0)} +span#textcolor2007{color:rgb(0,0,255)} +span#textcolor2008{color:rgb(0,127,0)} +span#textcolor2009{color:rgb(0,0,255)} +span#textcolor2010{color:rgb(0,127,0)} +span#textcolor2011{color:rgb(0,0,255)} +span#textcolor2012{color:rgb(0,127,0)} +span#textcolor2013{color:rgb(0,0,255)} +span#textcolor2014{color:rgb(0,127,0)} +span#textcolor2015{color:rgb(0,0,255)} +span#textcolor2016{color:rgb(0,127,0)} +span#textcolor2017{color:rgb(0,0,255)} +span#textcolor2018{color:rgb(43,145,175)} +span#textcolor2019{color:rgb(43,145,175)} +span#textcolor2020{color:rgb(43,145,175)} +span#textcolor2021{color:rgb(43,145,175)} +span#textcolor2022{color:rgb(163,20,20)} +span#textcolor2023{color:rgb(163,20,20)} +span#textcolor2024{color:rgb(163,20,20)} +span#textcolor2025{color:rgb(0,127,0)} +span#textcolor2026{color:rgb(0,127,0)} +span#textcolor2027{color:rgb(0,127,0)} +span#textcolor2028{color:rgb(0,127,0)} +span#textcolor2029{color:rgb(163,20,20)} +span#textcolor2030{color:rgb(163,20,20)} +span#textcolor2031{color:rgb(163,20,20)} +span#textcolor2032{color:rgb(0,0,255)} +span#textcolor2033{color:rgb(43,145,175)} +span#textcolor2034{color:rgb(43,145,175)} +span#textcolor2035{color:rgb(43,145,175)} +span#textcolor2036{color:rgb(43,145,175)} +span#textcolor2037{color:rgb(163,20,20)} +span#textcolor2038{color:rgb(163,20,20)} +span#textcolor2039{color:rgb(163,20,20)} +span#textcolor2040{color:rgb(0,127,0)} +span#textcolor2041{color:rgb(0,127,0)} +span#textcolor2042{color:rgb(0,127,0)} +span#textcolor2043{color:rgb(0,127,0)} +span#textcolor2044{color:rgb(163,20,20)} +span#textcolor2045{color:rgb(163,20,20)} +span#textcolor2046{color:rgb(163,20,20)} +span#textcolor2047{color:rgb(0,0,255)} +span#textcolor2048{color:rgb(43,145,175)} +span#textcolor2049{color:rgb(43,145,175)} +span#textcolor2050{color:rgb(163,20,20)} +span#textcolor2051{color:rgb(163,20,20)} +span#textcolor2052{color:rgb(163,20,20)} +span#textcolor2053{color:rgb(0,0,255)} +span#textcolor2054{color:rgb(0,0,255)} +span#textcolor2055{color:rgb(43,145,175)} +span#textcolor2056{color:rgb(43,145,175)} +span#textcolor2057{color:rgb(163,20,20)} +span#textcolor2058{color:rgb(163,20,20)} +span#textcolor2059{color:rgb(163,20,20)} +span#textcolor2060{color:rgb(163,20,20)} +span#textcolor2061{color:rgb(163,20,20)} +pre#fancyvrb58{padding:5.69054pt;} +pre#fancyvrb58{ border-top: solid 0.4pt; } +pre#fancyvrb58{ border-left: solid 0.4pt; } +pre#fancyvrb58{ border-bottom: solid 0.4pt; } +pre#fancyvrb58{ border-right: solid 0.4pt; } +span#textcolor2062{color:rgb(0,127,0)} +span#textcolor2063{color:rgb(0,127,0)} +span#textcolor2064{color:rgb(0,127,0)} +span#textcolor2065{color:rgb(0,0,255)} +span#textcolor2066{color:rgb(0,127,0)} +span#textcolor2067{color:rgb(0,0,255)} +span#textcolor2068{color:rgb(0,127,0)} +span#textcolor2069{color:rgb(0,0,255)} +span#textcolor2070{color:rgb(0,127,0)} +span#textcolor2071{color:rgb(0,0,255)} +span#textcolor2072{color:rgb(43,145,175)} +span#textcolor2073{color:rgb(43,145,175)} +span#textcolor2074{color:rgb(43,145,175)} +span#textcolor2075{color:rgb(43,145,175)} +span#textcolor2076{color:rgb(163,20,20)} +span#textcolor2077{color:rgb(163,20,20)} +span#textcolor2078{color:rgb(163,20,20)} +span#textcolor2079{color:rgb(0,127,0)} +span#textcolor2080{color:rgb(163,20,20)} +span#textcolor2081{color:rgb(163,20,20)} +span#textcolor2082{color:rgb(163,20,20)} +span#textcolor2083{color:rgb(0,0,255)} +span#textcolor2084{color:rgb(43,145,175)} +span#textcolor2085{color:rgb(43,145,175)} +span#textcolor2086{color:rgb(43,145,175)} +span#textcolor2087{color:rgb(43,145,175)} +span#textcolor2088{color:rgb(163,20,20)} +span#textcolor2089{color:rgb(163,20,20)} +span#textcolor2090{color:rgb(163,20,20)} +span#textcolor2091{color:rgb(0,127,0)} +span#textcolor2092{color:rgb(163,20,20)} +span#textcolor2093{color:rgb(163,20,20)} +span#textcolor2094{color:rgb(163,20,20)} +span#textcolor2095{color:rgb(0,0,255)} +span#textcolor2096{color:rgb(43,145,175)} +span#textcolor2097{color:rgb(43,145,175)} +span#textcolor2098{color:rgb(163,20,20)} +span#textcolor2099{color:rgb(163,20,20)} +span#textcolor2100{color:rgb(163,20,20)} +span#textcolor2101{color:rgb(0,0,255)} +span#textcolor2102{color:rgb(0,0,255)} +span#textcolor2103{color:rgb(43,145,175)} +span#textcolor2104{color:rgb(43,145,175)} +span#textcolor2105{color:rgb(163,20,20)} +span#textcolor2106{color:rgb(163,20,20)} +span#textcolor2107{color:rgb(163,20,20)} +span#textcolor2108{color:rgb(163,20,20)} +span#textcolor2109{color:rgb(163,20,20)} +pre#fancyvrb59{padding:5.69054pt;} +pre#fancyvrb59{ border-top: solid 0.4pt; } +pre#fancyvrb59{ border-left: solid 0.4pt; } +pre#fancyvrb59{ border-bottom: solid 0.4pt; } +pre#fancyvrb59{ border-right: solid 0.4pt; } +span#textcolor2110{color:rgb(0,127,0)} +span#textcolor2111{color:rgb(0,127,0)} +span#textcolor2112{color:rgb(0,127,0)} +span#textcolor2113{color:rgb(0,0,255)} +span#textcolor2114{color:rgb(0,127,0)} +span#textcolor2115{color:rgb(0,0,255)} +span#textcolor2116{color:rgb(0,127,0)} +span#textcolor2117{color:rgb(0,0,255)} +span#textcolor2118{color:rgb(0,127,0)} +span#textcolor2119{color:rgb(0,0,255)} +span#textcolor2120{color:rgb(0,0,255)} +span#textcolor2121{color:rgb(0,0,255)} +span#textcolor2122{color:rgb(0,0,255)} +span#textcolor2123{color:rgb(0,0,255)} +span#textcolor2124{color:rgb(0,0,255)} +span#textcolor2125{color:rgb(0,0,255)} +span#textcolor2126{color:rgb(43,145,175)} +span#textcolor2127{color:rgb(43,145,175)} +span#textcolor2128{color:rgb(0,127,0)} +span#textcolor2129{color:rgb(0,127,0)} +span#textcolor2130{color:rgb(163,20,20)} +span#textcolor2131{color:rgb(163,20,20)} +span#textcolor2132{color:rgb(163,20,20)} +span#textcolor2133{color:rgb(0,0,255)} +span#textcolor2134{color:rgb(43,145,175)} +span#textcolor2135{color:rgb(43,145,175)} +span#textcolor2136{color:rgb(43,145,175)} +span#textcolor2137{color:rgb(43,145,175)} +span#textcolor2138{color:rgb(163,20,20)} +span#textcolor2139{color:rgb(163,20,20)} +span#textcolor2140{color:rgb(163,20,20)} +span#textcolor2141{color:rgb(163,20,20)} +span#textcolor2142{color:rgb(0,0,255)} +span#textcolor2143{color:rgb(163,20,20)} +span#textcolor2144{color:rgb(163,20,20)} +span#textcolor2145{color:rgb(163,20,20)} +span#textcolor2146{color:rgb(163,20,20)} +span#textcolor2147{color:rgb(163,20,20)} +span#textcolor2148{color:rgb(0,0,255)} +span#textcolor2149{color:rgb(43,145,175)} +span#textcolor2150{color:rgb(43,145,175)} +span#textcolor2151{color:rgb(163,20,20)} +span#textcolor2152{color:rgb(163,20,20)} +span#textcolor2153{color:rgb(163,20,20)} +span#textcolor2154{color:rgb(0,0,255)} +span#textcolor2155{color:rgb(0,0,255)} +span#textcolor2156{color:rgb(43,145,175)} +span#textcolor2157{color:rgb(43,145,175)} +span#textcolor2158{color:rgb(163,20,20)} +span#textcolor2159{color:rgb(163,20,20)} +span#textcolor2160{color:rgb(163,20,20)} +span#textcolor2161{color:rgb(163,20,20)} +span#textcolor2162{color:rgb(163,20,20)} +pre#fancyvrb60{padding:5.69054pt;} +pre#fancyvrb60{ border-top: solid 0.4pt; } +pre#fancyvrb60{ border-left: solid 0.4pt; } +pre#fancyvrb60{ border-bottom: solid 0.4pt; } +pre#fancyvrb60{ border-right: solid 0.4pt; } +span#textcolor2163{color:rgb(0,127,0)} +span#textcolor2164{color:rgb(0,127,0)} +span#textcolor2165{color:rgb(0,127,0)} +span#textcolor2166{color:rgb(0,127,0)} +span#textcolor2167{color:rgb(0,127,0)} +span#textcolor2168{color:rgb(0,0,255)} +span#textcolor2169{color:rgb(0,127,0)} +span#textcolor2170{color:rgb(0,0,255)} +span#textcolor2171{color:rgb(0,127,0)} +span#textcolor2172{color:rgb(0,0,255)} +span#textcolor2173{color:rgb(0,127,0)} +span#textcolor2174{color:rgb(0,0,255)} +span#textcolor2175{color:rgb(0,127,0)} +span#textcolor2176{color:rgb(0,0,255)} +span#textcolor2177{color:rgb(0,127,0)} +span#textcolor2178{color:rgb(163,20,20)} +span#textcolor2179{color:rgb(0,0,255)} +span#textcolor2180{color:rgb(43,145,175)} +span#textcolor2181{color:rgb(43,145,175)} +span#textcolor2182{color:rgb(0,0,255)} +span#textcolor2183{color:rgb(0,0,255)} +span#textcolor2184{color:rgb(0,0,255)} +span#textcolor2185{color:rgb(0,127,0)} +span#textcolor2186{color:rgb(0,127,0)} +span#textcolor2187{color:rgb(0,127,0)} +span#textcolor2188{color:rgb(0,127,0)} +span#textcolor2189{color:rgb(0,127,0)} +span#textcolor2190{color:rgb(0,127,0)} +span#textcolor2191{color:rgb(0,127,0)} +span#textcolor2192{color:rgb(0,0,255)} +span#textcolor2193{color:rgb(0,127,0)} +span#textcolor2194{color:rgb(0,127,0)} +span#textcolor2195{color:rgb(0,127,0)} +span#textcolor2196{color:rgb(0,127,0)} +span#textcolor2197{color:rgb(0,127,0)} +span#textcolor2198{color:rgb(0,127,0)} +span#textcolor2199{color:rgb(0,127,0)} +span#textcolor2200{color:rgb(0,127,0)} +span#textcolor2201{color:rgb(0,127,0)} +span#textcolor2202{color:rgb(0,127,0)} +span#textcolor2203{color:rgb(0,127,0)} +span#textcolor2204{color:rgb(0,127,0)} +span#textcolor2205{color:rgb(0,127,0)} +span#textcolor2206{color:rgb(0,127,0)} +span#textcolor2207{color:rgb(0,127,0)} +span#textcolor2208{color:rgb(0,127,0)} +span#textcolor2209{color:rgb(0,127,0)} +span#textcolor2210{color:rgb(0,127,0)} +span#textcolor2211{color:rgb(0,127,0)} +span#textcolor2212{color:rgb(0,127,0)} +span#textcolor2213{color:rgb(0,127,0)} +span#textcolor2214{color:rgb(0,127,0)} +span#textcolor2215{color:rgb(0,127,0)} +span#textcolor2216{color:rgb(0,127,0)} +span#textcolor2217{color:rgb(0,127,0)} +span#textcolor2218{color:rgb(0,127,0)} +span#textcolor2219{color:rgb(0,127,0)} +span#textcolor2220{color:rgb(0,127,0)} +span#textcolor2221{color:rgb(0,127,0)} +span#textcolor2222{color:rgb(0,127,0)} +span#textcolor2223{color:rgb(0,127,0)} +span#textcolor2224{color:rgb(0,127,0)} +span#textcolor2225{color:rgb(0,127,0)} +span#textcolor2226{color:rgb(0,127,0)} +span#textcolor2227{color:rgb(0,127,0)} +span#textcolor2228{color:rgb(0,127,0)} +span#textcolor2229{color:rgb(163,20,20)} +span#textcolor2230{color:rgb(163,20,20)} +span#textcolor2231{color:rgb(163,20,20)} +span#textcolor2232{color:rgb(0,0,255)} +span#textcolor2233{color:rgb(43,145,175)} +span#textcolor2234{color:rgb(43,145,175)} +span#textcolor2235{color:rgb(163,20,20)} +span#textcolor2236{color:rgb(0,0,255)} +span#textcolor2237{color:rgb(0,0,255)} +span#textcolor2238{color:rgb(43,145,175)} +span#textcolor2239{color:rgb(43,145,175)} +span#textcolor2240{color:rgb(163,20,20)} +pre#fancyvrb61{padding:5.69054pt;} +pre#fancyvrb61{ border-top: solid 0.4pt; } +pre#fancyvrb61{ border-left: solid 0.4pt; } +pre#fancyvrb61{ border-bottom: solid 0.4pt; } +pre#fancyvrb61{ border-right: solid 0.4pt; } +span#textcolor2241{color:rgb(0,127,0)} +span#textcolor2242{color:rgb(0,127,0)} +span#textcolor2243{color:rgb(0,127,0)} +span#textcolor2244{color:rgb(0,0,255)} +span#textcolor2245{color:rgb(0,127,0)} +span#textcolor2246{color:rgb(0,0,255)} +span#textcolor2247{color:rgb(0,127,0)} +span#textcolor2248{color:rgb(0,0,255)} +span#textcolor2249{color:rgb(0,127,0)} +span#textcolor2250{color:rgb(0,0,255)} +span#textcolor2251{color:rgb(0,127,0)} +span#textcolor2252{color:rgb(0,0,255)} +span#textcolor2253{color:rgb(0,127,0)} +span#textcolor2254{color:rgb(0,0,255)} +span#textcolor2255{color:rgb(0,127,0)} +span#textcolor2256{color:rgb(0,0,255)} +span#textcolor2257{color:rgb(0,127,0)} +span#textcolor2258{color:rgb(163,20,20)} +span#textcolor2259{color:rgb(163,20,20)} +span#textcolor2260{color:rgb(0,0,255)} +span#textcolor2261{color:rgb(0,0,255)} +span#textcolor2262{color:rgb(43,145,175)} +span#textcolor2263{color:rgb(0,0,255)} +span#textcolor2264{color:rgb(0,0,255)} +span#textcolor2265{color:rgb(0,0,255)} +span#textcolor2266{color:rgb(0,127,0)} +span#textcolor2267{color:rgb(0,127,0)} +span#textcolor2268{color:rgb(0,127,0)} +span#textcolor2269{color:rgb(0,127,0)} +span#textcolor2270{color:rgb(0,127,0)} +span#textcolor2271{color:rgb(0,127,0)} +span#textcolor2272{color:rgb(0,127,0)} +span#textcolor2273{color:rgb(0,127,0)} +span#textcolor2274{color:rgb(0,127,0)} +span#textcolor2275{color:rgb(0,127,0)} +span#textcolor2276{color:rgb(0,127,0)} +span#textcolor2277{color:rgb(0,127,0)} +span#textcolor2278{color:rgb(0,127,0)} +span#textcolor2279{color:rgb(0,127,0)} +span#textcolor2280{color:rgb(0,0,255)} +span#textcolor2281{color:rgb(43,145,175)} +span#textcolor2282{color:rgb(43,145,175)} +span#textcolor2283{color:rgb(43,145,175)} +span#textcolor2284{color:rgb(43,145,175)} +span#textcolor2285{color:rgb(43,145,175)} +span#textcolor2286{color:rgb(43,145,175)} +span#textcolor2287{color:rgb(43,145,175)} +span#textcolor2288{color:rgb(0,0,255)} +span#textcolor2289{color:rgb(0,0,255)} +span#textcolor2290{color:rgb(0,0,255)} +span#textcolor2291{color:rgb(0,0,255)} +span#textcolor2292{color:rgb(43,145,175)} +span#textcolor2293{color:rgb(43,145,175)} +span#textcolor2294{color:rgb(43,145,175)} +span#textcolor2295{color:rgb(163,20,20)} +span#textcolor2296{color:rgb(163,20,20)} +span#textcolor2297{color:rgb(163,20,20)} +span#textcolor2298{color:rgb(163,20,20)} +span#textcolor2299{color:rgb(163,20,20)} +span#textcolor2300{color:rgb(163,20,20)} +span#textcolor2301{color:rgb(0,0,255)} +span#textcolor2302{color:rgb(0,0,255)} +span#textcolor2303{color:rgb(0,0,255)} +span#textcolor2304{color:rgb(163,20,20)} +span#textcolor2305{color:rgb(163,20,20)} +span#textcolor2306{color:rgb(163,20,20)} +span#textcolor2307{color:rgb(43,145,175)} +span#textcolor2308{color:rgb(43,145,175)} +span#textcolor2309{color:rgb(163,20,20)} +span#textcolor2310{color:rgb(163,20,20)} +span#textcolor2311{color:rgb(163,20,20)} +span#textcolor2312{color:rgb(163,20,20)} +span#textcolor2313{color:rgb(163,20,20)} +span#textcolor2314{color:rgb(163,20,20)} +span#textcolor2315{color:rgb(0,127,0)} +span#textcolor2316{color:rgb(0,127,0)} +span#textcolor2317{color:rgb(0,127,0)} +span#textcolor2318{color:rgb(43,145,175)} +span#textcolor2319{color:rgb(43,145,175)} +span#textcolor2320{color:rgb(43,145,175)} +span#textcolor2321{color:rgb(0,0,255)} +span#textcolor2322{color:rgb(0,0,255)} +span#textcolor2323{color:rgb(43,145,175)} +span#textcolor2324{color:rgb(43,145,175)} +span#textcolor2325{color:rgb(163,20,20)} +span#textcolor2326{color:rgb(163,20,20)} +span#textcolor2327{color:rgb(163,20,20)} +pre#fancyvrb62{padding:5.69054pt;} +pre#fancyvrb62{ border-top: solid 0.4pt; } +pre#fancyvrb62{ border-left: solid 0.4pt; } +pre#fancyvrb62{ border-bottom: solid 0.4pt; } +pre#fancyvrb62{ border-right: solid 0.4pt; } +span#textcolor2328{color:rgb(0,127,0)} +span#textcolor2329{color:rgb(0,127,0)} +span#textcolor2330{color:rgb(0,127,0)} +span#textcolor2331{color:rgb(0,0,255)} +span#textcolor2332{color:rgb(0,127,0)} +span#textcolor2333{color:rgb(0,0,255)} +span#textcolor2334{color:rgb(0,127,0)} +span#textcolor2335{color:rgb(0,0,255)} +span#textcolor2336{color:rgb(0,127,0)} +span#textcolor2337{color:rgb(0,0,255)} +span#textcolor2338{color:rgb(0,127,0)} +span#textcolor2339{color:rgb(0,0,255)} +span#textcolor2340{color:rgb(43,145,175)} +span#textcolor2341{color:rgb(43,145,175)} +span#textcolor2342{color:rgb(43,145,175)} +span#textcolor2343{color:rgb(163,20,20)} +span#textcolor2344{color:rgb(163,20,20)} +span#textcolor2345{color:rgb(163,20,20)} +span#textcolor2346{color:rgb(163,20,20)} +span#textcolor2347{color:rgb(163,20,20)} +span#textcolor2348{color:rgb(163,20,20)} +span#textcolor2349{color:rgb(0,0,255)} +span#textcolor2350{color:rgb(43,145,175)} +span#textcolor2351{color:rgb(43,145,175)} +span#textcolor2352{color:rgb(163,20,20)} +span#textcolor2353{color:rgb(163,20,20)} +span#textcolor2354{color:rgb(163,20,20)} +span#textcolor2355{color:rgb(163,20,20)} +span#textcolor2356{color:rgb(163,20,20)} +span#textcolor2357{color:rgb(163,20,20)} +span#textcolor2358{color:rgb(0,0,255)} +span#textcolor2359{color:rgb(0,0,255)} +span#textcolor2360{color:rgb(43,145,175)} +span#textcolor2361{color:rgb(43,145,175)} +span#textcolor2362{color:rgb(163,20,20)} +span#textcolor2363{color:rgb(163,20,20)} +span#textcolor2364{color:rgb(163,20,20)} +span#textcolor2365{color:rgb(163,20,20)} +span#textcolor2366{color:rgb(163,20,20)} +pre#fancyvrb63{padding:5.69054pt;} +pre#fancyvrb63{ border-top: solid 0.4pt; } +pre#fancyvrb63{ border-left: solid 0.4pt; } +pre#fancyvrb63{ border-bottom: solid 0.4pt; } +pre#fancyvrb63{ border-right: solid 0.4pt; } +span#textcolor2367{color:rgb(0,127,0)} +span#textcolor2368{color:rgb(0,127,0)} +span#textcolor2369{color:rgb(0,127,0)} +span#textcolor2370{color:rgb(0,0,255)} +span#textcolor2371{color:rgb(0,127,0)} +span#textcolor2372{color:rgb(0,0,255)} +span#textcolor2373{color:rgb(0,127,0)} +span#textcolor2374{color:rgb(0,0,255)} +span#textcolor2375{color:rgb(0,127,0)} +span#textcolor2376{color:rgb(0,0,255)} +span#textcolor2377{color:rgb(0,0,255)} +span#textcolor2378{color:rgb(0,0,255)} +span#textcolor2379{color:rgb(0,0,255)} +span#textcolor2380{color:rgb(0,0,255)} +span#textcolor2381{color:rgb(43,145,175)} +span#textcolor2382{color:rgb(0,0,255)} +span#textcolor2383{color:rgb(163,20,20)} +span#textcolor2384{color:rgb(163,20,20)} +span#textcolor2385{color:rgb(163,20,20)} +span#textcolor2386{color:rgb(43,145,175)} +span#textcolor2387{color:rgb(163,20,20)} +span#textcolor2388{color:rgb(0,0,255)} +span#textcolor2389{color:rgb(43,145,175)} +span#textcolor2390{color:rgb(163,20,20)} +span#textcolor2391{color:rgb(163,20,20)} +pre#fancyvrb64{padding:5.69054pt;} +pre#fancyvrb64{ border-top: solid 0.4pt; } +pre#fancyvrb64{ border-left: solid 0.4pt; } +pre#fancyvrb64{ border-bottom: solid 0.4pt; } +pre#fancyvrb64{ border-right: solid 0.4pt; } +span#textcolor2392{color:rgb(0,127,0)} +span#textcolor2393{color:rgb(0,127,0)} +span#textcolor2394{color:rgb(0,127,0)} +span#textcolor2395{color:rgb(0,127,0)} +span#textcolor2396{color:rgb(0,127,0)} +span#textcolor2397{color:rgb(0,127,0)} +span#textcolor2398{color:rgb(0,127,0)} +span#textcolor2399{color:rgb(0,127,0)} +span#textcolor2400{color:rgb(0,127,0)} +span#textcolor2401{color:rgb(0,0,255)} +span#textcolor2402{color:rgb(0,127,0)} +span#textcolor2403{color:rgb(0,0,255)} +span#textcolor2404{color:rgb(0,127,0)} +span#textcolor2405{color:rgb(0,0,255)} +span#textcolor2406{color:rgb(0,127,0)} +span#textcolor2407{color:rgb(0,0,255)} +span#textcolor2408{color:rgb(0,127,0)} +span#textcolor2409{color:rgb(0,0,255)} +span#textcolor2410{color:rgb(43,145,175)} +span#textcolor2411{color:rgb(0,127,0)} +span#textcolor2412{color:rgb(0,127,0)} +span#textcolor2413{color:rgb(0,0,255)} +span#textcolor2414{color:rgb(0,0,255)} +span#textcolor2415{color:rgb(163,20,20)} +span#textcolor2416{color:rgb(0,127,0)} +span#textcolor2417{color:rgb(0,127,0)} +span#textcolor2418{color:rgb(0,0,255)} +span#textcolor2419{color:rgb(0,0,255)} +span#textcolor2420{color:rgb(163,20,20)} +span#textcolor2421{color:rgb(163,20,20)} +span#textcolor2422{color:rgb(0,127,0)} +span#textcolor2423{color:rgb(0,127,0)} +span#textcolor2424{color:rgb(0,127,0)} +span#textcolor2425{color:rgb(0,0,255)} +span#textcolor2426{color:rgb(43,145,175)} +span#textcolor2427{color:rgb(43,145,175)} +span#textcolor2428{color:rgb(0,127,0)} +span#textcolor2429{color:rgb(0,0,255)} +span#textcolor2430{color:rgb(0,127,0)} +span#textcolor2431{color:rgb(0,0,255)} +span#textcolor2432{color:rgb(0,0,255)} +span#textcolor2433{color:rgb(0,0,255)} +span#textcolor2434{color:rgb(43,145,175)} +span#textcolor2435{color:rgb(43,145,175)} +span#textcolor2436{color:rgb(163,20,20)} +span#textcolor2437{color:rgb(163,20,20)} +span#textcolor2438{color:rgb(163,20,20)} +span#textcolor2439{color:rgb(0,127,0)} +span#textcolor2440{color:rgb(0,0,255)} +span#textcolor2441{color:rgb(163,20,20)} +span#textcolor2442{color:rgb(163,20,20)} +span#textcolor2443{color:rgb(163,20,20)} +span#textcolor2444{color:rgb(0,0,255)} +span#textcolor2445{color:rgb(0,127,0)} +span#textcolor2446{color:rgb(0,0,255)} +span#textcolor2447{color:rgb(163,20,20)} +span#textcolor2448{color:rgb(163,20,20)} +span#textcolor2449{color:rgb(163,20,20)} +span#textcolor2450{color:rgb(0,0,255)} +span#textcolor2451{color:rgb(163,20,20)} +span#textcolor2452{color:rgb(163,20,20)} +span#textcolor2453{color:rgb(163,20,20)} +span#textcolor2454{color:rgb(0,0,255)} +span#textcolor2455{color:rgb(163,20,20)} +span#textcolor2456{color:rgb(163,20,20)} +span#textcolor2457{color:rgb(163,20,20)} +span#textcolor2458{color:rgb(0,0,255)} +span#textcolor2459{color:rgb(163,20,20)} +span#textcolor2460{color:rgb(163,20,20)} +span#textcolor2461{color:rgb(163,20,20)} +span#textcolor2462{color:rgb(163,20,20)} +span#textcolor2463{color:rgb(0,0,255)} +span#textcolor2464{color:rgb(163,20,20)} +span#textcolor2465{color:rgb(163,20,20)} +span#textcolor2466{color:rgb(163,20,20)} +span#textcolor2467{color:rgb(0,0,255)} +span#textcolor2468{color:rgb(0,0,255)} +span#textcolor2469{color:rgb(163,20,20)} +span#textcolor2470{color:rgb(163,20,20)} +span#textcolor2471{color:rgb(163,20,20)} +span#textcolor2472{color:rgb(0,0,255)} +span#textcolor2473{color:rgb(163,20,20)} +span#textcolor2474{color:rgb(163,20,20)} +span#textcolor2475{color:rgb(163,20,20)} +span#textcolor2476{color:rgb(163,20,20)} +span#textcolor2477{color:rgb(0,0,255)} +span#textcolor2478{color:rgb(163,20,20)} +span#textcolor2479{color:rgb(163,20,20)} +span#textcolor2480{color:rgb(163,20,20)} +span#textcolor2481{color:rgb(0,0,255)} +span#textcolor2482{color:rgb(0,0,255)} +span#textcolor2483{color:rgb(0,127,0)} +span#textcolor2484{color:rgb(0,0,255)} +span#textcolor2485{color:rgb(43,145,175)} +span#textcolor2486{color:rgb(43,145,175)} +span#textcolor2487{color:rgb(163,20,20)} +span#textcolor2488{color:rgb(163,20,20)} +span#textcolor2489{color:rgb(163,20,20)} +span#textcolor2490{color:rgb(0,127,0)} +span#textcolor2491{color:rgb(0,127,0)} +span#textcolor2492{color:rgb(0,0,255)} +span#textcolor2493{color:rgb(0,127,0)} +span#textcolor2494{color:rgb(163,20,20)} +span#textcolor2495{color:rgb(163,20,20)} +pre#fancyvrb65{padding:5.69054pt;} +pre#fancyvrb65{ border-top: solid 0.4pt; } +pre#fancyvrb65{ border-left: solid 0.4pt; } +pre#fancyvrb65{ border-bottom: solid 0.4pt; } +pre#fancyvrb65{ border-right: solid 0.4pt; } +span#textcolor2496{color:rgb(0,127,0)} +span#textcolor2497{color:rgb(0,127,0)} +span#textcolor2498{color:rgb(0,127,0)} +span#textcolor2499{color:rgb(0,127,0)} +span#textcolor2500{color:rgb(0,127,0)} +span#textcolor2501{color:rgb(0,127,0)} +span#textcolor2502{color:rgb(0,127,0)} +span#textcolor2503{color:rgb(0,127,0)} +span#textcolor2504{color:rgb(0,127,0)} +span#textcolor2505{color:rgb(0,0,255)} +span#textcolor2506{color:rgb(0,127,0)} +span#textcolor2507{color:rgb(0,0,255)} +span#textcolor2508{color:rgb(0,127,0)} +span#textcolor2509{color:rgb(0,0,255)} +span#textcolor2510{color:rgb(0,127,0)} +span#textcolor2511{color:rgb(0,0,255)} +span#textcolor2512{color:rgb(0,127,0)} +span#textcolor2513{color:rgb(0,0,255)} +span#textcolor2514{color:rgb(0,127,0)} +span#textcolor2515{color:rgb(0,0,255)} +span#textcolor2516{color:rgb(43,145,175)} +span#textcolor2517{color:rgb(0,127,0)} +span#textcolor2518{color:rgb(0,127,0)} +span#textcolor2519{color:rgb(0,0,255)} +span#textcolor2520{color:rgb(0,0,255)} +span#textcolor2521{color:rgb(163,20,20)} +span#textcolor2522{color:rgb(0,127,0)} +span#textcolor2523{color:rgb(0,127,0)} +span#textcolor2524{color:rgb(0,0,255)} +span#textcolor2525{color:rgb(0,0,255)} +span#textcolor2526{color:rgb(163,20,20)} +span#textcolor2527{color:rgb(163,20,20)} +span#textcolor2528{color:rgb(0,127,0)} +span#textcolor2529{color:rgb(0,0,255)} +span#textcolor2530{color:rgb(43,145,175)} +span#textcolor2531{color:rgb(43,145,175)} +span#textcolor2532{color:rgb(43,145,175)} +span#textcolor2533{color:rgb(163,20,20)} +span#textcolor2534{color:rgb(163,20,20)} +span#textcolor2535{color:rgb(163,20,20)} +span#textcolor2536{color:rgb(0,127,0)} +span#textcolor2537{color:rgb(163,20,20)} +span#textcolor2538{color:rgb(163,20,20)} +span#textcolor2539{color:rgb(163,20,20)} +span#textcolor2540{color:rgb(0,127,0)} +span#textcolor2541{color:rgb(0,127,0)} +span#textcolor2542{color:rgb(0,127,0)} +span#textcolor2543{color:rgb(0,0,255)} +span#textcolor2544{color:rgb(43,145,175)} +span#textcolor2545{color:rgb(43,145,175)} +span#textcolor2546{color:rgb(0,127,0)} +span#textcolor2547{color:rgb(0,0,255)} +span#textcolor2548{color:rgb(0,0,255)} +span#textcolor2549{color:rgb(0,0,255)} +span#textcolor2550{color:rgb(0,127,0)} +span#textcolor2551{color:rgb(0,0,255)} +span#textcolor2552{color:rgb(43,145,175)} +span#textcolor2553{color:rgb(43,145,175)} +span#textcolor2554{color:rgb(163,20,20)} +span#textcolor2555{color:rgb(163,20,20)} +span#textcolor2556{color:rgb(163,20,20)} +span#textcolor2557{color:rgb(0,127,0)} +span#textcolor2558{color:rgb(0,0,255)} +span#textcolor2559{color:rgb(163,20,20)} +span#textcolor2560{color:rgb(163,20,20)} +span#textcolor2561{color:rgb(163,20,20)} +span#textcolor2562{color:rgb(0,0,255)} +span#textcolor2563{color:rgb(0,127,0)} +span#textcolor2564{color:rgb(0,0,255)} +span#textcolor2565{color:rgb(163,20,20)} +span#textcolor2566{color:rgb(163,20,20)} +span#textcolor2567{color:rgb(163,20,20)} +span#textcolor2568{color:rgb(0,0,255)} +span#textcolor2569{color:rgb(163,20,20)} +span#textcolor2570{color:rgb(163,20,20)} +span#textcolor2571{color:rgb(163,20,20)} +span#textcolor2572{color:rgb(0,0,255)} +span#textcolor2573{color:rgb(163,20,20)} +span#textcolor2574{color:rgb(163,20,20)} +span#textcolor2575{color:rgb(163,20,20)} +span#textcolor2576{color:rgb(0,0,255)} +span#textcolor2577{color:rgb(163,20,20)} +span#textcolor2578{color:rgb(163,20,20)} +span#textcolor2579{color:rgb(163,20,20)} +span#textcolor2580{color:rgb(163,20,20)} +span#textcolor2581{color:rgb(0,0,255)} +span#textcolor2582{color:rgb(163,20,20)} +span#textcolor2583{color:rgb(163,20,20)} +span#textcolor2584{color:rgb(163,20,20)} +span#textcolor2585{color:rgb(0,0,255)} +span#textcolor2586{color:rgb(0,0,255)} +span#textcolor2587{color:rgb(163,20,20)} +span#textcolor2588{color:rgb(163,20,20)} +span#textcolor2589{color:rgb(163,20,20)} +span#textcolor2590{color:rgb(0,0,255)} +span#textcolor2591{color:rgb(163,20,20)} +span#textcolor2592{color:rgb(163,20,20)} +span#textcolor2593{color:rgb(163,20,20)} +span#textcolor2594{color:rgb(163,20,20)} +span#textcolor2595{color:rgb(0,0,255)} +span#textcolor2596{color:rgb(163,20,20)} +span#textcolor2597{color:rgb(163,20,20)} +span#textcolor2598{color:rgb(163,20,20)} +span#textcolor2599{color:rgb(0,0,255)} +span#textcolor2600{color:rgb(0,0,255)} +span#textcolor2601{color:rgb(0,127,0)} +span#textcolor2602{color:rgb(0,0,255)} +span#textcolor2603{color:rgb(43,145,175)} +span#textcolor2604{color:rgb(43,145,175)} +span#textcolor2605{color:rgb(163,20,20)} +span#textcolor2606{color:rgb(163,20,20)} +span#textcolor2607{color:rgb(163,20,20)} +span#textcolor2608{color:rgb(0,127,0)} +span#textcolor2609{color:rgb(0,127,0)} +span#textcolor2610{color:rgb(0,0,255)} +span#textcolor2611{color:rgb(0,127,0)} +span#textcolor2612{color:rgb(163,20,20)} +span#textcolor2613{color:rgb(163,20,20)} +pre#fancyvrb66{padding:5.69054pt;} +pre#fancyvrb66{ border-top: solid 0.4pt; } +pre#fancyvrb66{ border-left: solid 0.4pt; } +pre#fancyvrb66{ border-bottom: solid 0.4pt; } +pre#fancyvrb66{ border-right: solid 0.4pt; } +span#textcolor2614{color:rgb(0,127,0)} +span#textcolor2615{color:rgb(0,127,0)} +span#textcolor2616{color:rgb(0,127,0)} +span#textcolor2617{color:rgb(0,0,255)} +span#textcolor2618{color:rgb(0,127,0)} +span#textcolor2619{color:rgb(0,0,255)} +span#textcolor2620{color:rgb(0,127,0)} +span#textcolor2621{color:rgb(0,0,255)} +span#textcolor2622{color:rgb(0,0,255)} +span#textcolor2623{color:rgb(43,145,175)} +span#textcolor2624{color:rgb(43,145,175)} +span#textcolor2625{color:rgb(43,145,175)} +span#textcolor2626{color:rgb(43,145,175)} +span#textcolor2627{color:rgb(43,145,175)} +span#textcolor2628{color:rgb(163,20,20)} +span#textcolor2629{color:rgb(163,20,20)} +span#textcolor2630{color:rgb(163,20,20)} +span#textcolor2631{color:rgb(163,20,20)} +span#textcolor2632{color:rgb(163,20,20)} +span#textcolor2633{color:rgb(0,0,255)} +span#textcolor2634{color:rgb(163,20,20)} +span#textcolor2635{color:rgb(43,145,175)} +span#textcolor2636{color:rgb(43,145,175)} +span#textcolor2637{color:rgb(163,20,20)} +span#textcolor2638{color:rgb(163,20,20)} +span#textcolor2639{color:rgb(163,20,20)} +span#textcolor2640{color:rgb(43,145,175)} +span#textcolor2641{color:rgb(43,145,175)} +span#textcolor2642{color:rgb(43,145,175)} +span#textcolor2643{color:rgb(163,20,20)} +span#textcolor2644{color:rgb(43,145,175)} +span#textcolor2645{color:rgb(0,0,255)} +span#textcolor2646{color:rgb(0,0,255)} +span#textcolor2647{color:rgb(163,20,20)} +span#textcolor2648{color:rgb(0,0,255)} +span#textcolor2649{color:rgb(0,0,255)} +span#textcolor2650{color:rgb(0,0,255)} +span#textcolor2651{color:rgb(0,0,255)} +span#textcolor2652{color:rgb(0,0,255)} +span#textcolor2653{color:rgb(0,0,255)} +span#textcolor2654{color:rgb(0,0,255)} +span#textcolor2655{color:rgb(0,0,255)} +span#textcolor2656{color:rgb(0,0,255)} +span#textcolor2657{color:rgb(0,0,255)} +span#textcolor2658{color:rgb(0,0,255)} +span#textcolor2659{color:rgb(0,0,255)} +span#textcolor2660{color:rgb(0,0,255)} +span#textcolor2661{color:rgb(43,145,175)} +span#textcolor2662{color:rgb(43,145,175)} +span#textcolor2663{color:rgb(163,20,20)} +span#textcolor2664{color:rgb(163,20,20)} +pre#fancyvrb67{padding:5.69054pt;} +pre#fancyvrb67{ border-top: solid 0.4pt; } +pre#fancyvrb67{ border-left: solid 0.4pt; } +pre#fancyvrb67{ border-bottom: solid 0.4pt; } +pre#fancyvrb67{ border-right: solid 0.4pt; } +pre#fancyvrb68{padding:5.69054pt;} +pre#fancyvrb68{ border-top: solid 0.4pt; } +pre#fancyvrb68{ border-left: solid 0.4pt; } +pre#fancyvrb68{ border-bottom: solid 0.4pt; } +pre#fancyvrb68{ border-right: solid 0.4pt; } +pre#fancyvrb69{padding:5.69054pt;} +pre#fancyvrb69{ border-top: solid 0.4pt; } +pre#fancyvrb69{ border-left: solid 0.4pt; } +pre#fancyvrb69{ border-bottom: solid 0.4pt; } +pre#fancyvrb69{ border-right: solid 0.4pt; } +span#textcolor2665{color:rgb(0,127,0)} +span#textcolor2666{color:rgb(0,127,0)} +span#textcolor2667{color:rgb(0,127,0)} +span#textcolor2668{color:rgb(0,0,255)} +span#textcolor2669{color:rgb(0,127,0)} +span#textcolor2670{color:rgb(0,0,255)} +span#textcolor2671{color:rgb(0,127,0)} +span#textcolor2672{color:rgb(0,0,255)} +span#textcolor2673{color:rgb(0,127,0)} +span#textcolor2674{color:rgb(0,0,255)} +span#textcolor2675{color:rgb(0,0,255)} +span#textcolor2676{color:rgb(0,0,255)} +span#textcolor2677{color:rgb(0,0,255)} +span#textcolor2678{color:rgb(43,145,175)} +span#textcolor2679{color:rgb(0,0,255)} +span#textcolor2680{color:rgb(0,0,255)} +span#textcolor2681{color:rgb(0,0,255)} +span#textcolor2682{color:rgb(0,0,255)} +span#textcolor2683{color:rgb(0,0,255)} +span#textcolor2684{color:rgb(43,145,175)} +span#textcolor2685{color:rgb(43,145,175)} +span#textcolor2686{color:rgb(43,145,175)} +span#textcolor2687{color:rgb(0,0,255)} +span#textcolor2688{color:rgb(0,0,255)} +span#textcolor2689{color:rgb(0,0,255)} +span#textcolor2690{color:rgb(43,145,175)} +span#textcolor2691{color:rgb(0,0,255)} +span#textcolor2692{color:rgb(0,0,255)} +span#textcolor2693{color:rgb(0,0,255)} +span#textcolor2694{color:rgb(0,0,255)} +span#textcolor2695{color:rgb(0,0,255)} +span#textcolor2696{color:rgb(0,0,255)} +span#textcolor2697{color:rgb(0,0,255)} +span#textcolor2698{color:rgb(43,145,175)} +span#textcolor2699{color:rgb(0,0,255)} +span#textcolor2700{color:rgb(43,145,175)} +span#textcolor2701{color:rgb(0,0,255)} +span#textcolor2702{color:rgb(0,0,255)} +span#textcolor2703{color:rgb(0,0,255)} +span#textcolor2704{color:rgb(0,0,255)} +span#textcolor2705{color:rgb(0,0,255)} +span#textcolor2706{color:rgb(0,0,255)} +span#textcolor2707{color:rgb(163,20,20)} +span#textcolor2708{color:rgb(163,20,20)} +span#textcolor2709{color:rgb(163,20,20)} +span#textcolor2710{color:rgb(0,0,255)} +span#textcolor2711{color:rgb(0,0,255)} +span#textcolor2712{color:rgb(163,20,20)} +span#textcolor2713{color:rgb(163,20,20)} +span#textcolor2714{color:rgb(163,20,20)} +span#textcolor2715{color:rgb(0,0,255)} +span#textcolor2716{color:rgb(0,0,255)} +span#textcolor2717{color:rgb(0,0,255)} +span#textcolor2718{color:rgb(43,145,175)} +span#textcolor2719{color:rgb(0,0,255)} +span#textcolor2720{color:rgb(43,145,175)} +span#textcolor2721{color:rgb(0,0,255)} +span#textcolor2722{color:rgb(0,127,0)} +span#textcolor2723{color:rgb(0,0,255)} +span#textcolor2724{color:rgb(0,0,255)} +span#textcolor2725{color:rgb(163,20,20)} +span#textcolor2726{color:rgb(163,20,20)} +span#textcolor2727{color:rgb(163,20,20)} +span#textcolor2728{color:rgb(0,127,0)} +span#textcolor2729{color:rgb(0,127,0)} +span#textcolor2730{color:rgb(0,127,0)} +span#textcolor2731{color:rgb(0,127,0)} +span#textcolor2732{color:rgb(0,127,0)} +span#textcolor2733{color:rgb(0,127,0)} +span#textcolor2734{color:rgb(0,127,0)} +span#textcolor2735{color:rgb(0,127,0)} +span#textcolor2736{color:rgb(0,127,0)} +span#textcolor2737{color:rgb(0,127,0)} +span#textcolor2738{color:rgb(0,127,0)} +span#textcolor2739{color:rgb(0,127,0)} +span#textcolor2740{color:rgb(0,0,255)} +span#textcolor2741{color:rgb(43,145,175)} +span#textcolor2742{color:rgb(43,145,175)} +span#textcolor2743{color:rgb(43,145,175)} +span#textcolor2744{color:rgb(0,0,255)} +span#textcolor2745{color:rgb(43,145,175)} +span#textcolor2746{color:rgb(43,145,175)} +span#textcolor2747{color:rgb(43,145,175)} +span#textcolor2748{color:rgb(0,0,255)} +span#textcolor2749{color:rgb(163,20,20)} +span#textcolor2750{color:rgb(0,0,255)} +span#textcolor2751{color:rgb(163,20,20)} +span#textcolor2752{color:rgb(163,20,20)} +span#textcolor2753{color:rgb(163,20,20)} +span#textcolor2754{color:rgb(0,0,255)} +span#textcolor2755{color:rgb(0,0,255)} +span#textcolor2756{color:rgb(0,0,255)} +span#textcolor2757{color:rgb(163,20,20)} +span#textcolor2758{color:rgb(163,20,20)} +span#textcolor2759{color:rgb(163,20,20)} +span#textcolor2760{color:rgb(0,0,255)} +span#textcolor2761{color:rgb(0,127,0)} +span#textcolor2762{color:rgb(43,145,175)} +span#textcolor2763{color:rgb(163,20,20)} +span#textcolor2764{color:rgb(0,127,0)} +span#textcolor2765{color:rgb(43,145,175)} +span#textcolor2766{color:rgb(163,20,20)} +span#textcolor2767{color:rgb(0,127,0)} +span#textcolor2768{color:rgb(0,0,255)} +span#textcolor2769{color:rgb(163,20,20)} +span#textcolor2770{color:rgb(163,20,20)} +span#textcolor2771{color:rgb(163,20,20)} +span#textcolor2772{color:rgb(0,0,255)} +span#textcolor2773{color:rgb(163,20,20)} +span#textcolor2774{color:rgb(163,20,20)} +span#textcolor2775{color:rgb(163,20,20)} +span#textcolor2776{color:rgb(163,20,20)} +span#textcolor2777{color:rgb(163,20,20)} +span#textcolor2778{color:rgb(163,20,20)} +span#textcolor2779{color:rgb(0,0,255)} +span#textcolor2780{color:rgb(0,127,0)} +span#textcolor2781{color:rgb(0,0,255)} +span#textcolor2782{color:rgb(163,20,20)} +span#textcolor2783{color:rgb(163,20,20)} +span#textcolor2784{color:rgb(163,20,20)} +span#textcolor2785{color:rgb(0,0,255)} +span#textcolor2786{color:rgb(0,0,255)} +span#textcolor2787{color:rgb(0,127,0)} +span#textcolor2788{color:rgb(0,0,255)} +span#textcolor2789{color:rgb(163,20,20)} +span#textcolor2790{color:rgb(163,20,20)} +span#textcolor2791{color:rgb(163,20,20)} +span#textcolor2792{color:rgb(0,0,255)} +span#textcolor2793{color:rgb(43,145,175)} +span#textcolor2794{color:rgb(163,20,20)} +span#textcolor2795{color:rgb(0,127,0)} +span#textcolor2796{color:rgb(0,0,255)} +span#textcolor2797{color:rgb(0,0,255)} +span#textcolor2798{color:rgb(163,20,20)} +span#textcolor2799{color:rgb(163,20,20)} +span#textcolor2800{color:rgb(163,20,20)} +span#textcolor2801{color:rgb(0,0,255)} +span#textcolor2802{color:rgb(43,145,175)} +span#textcolor2803{color:rgb(43,145,175)} +span#textcolor2804{color:rgb(0,127,0)} +span#textcolor2805{color:rgb(43,145,175)} +span#textcolor2806{color:rgb(163,20,20)} +span#textcolor2807{color:rgb(163,20,20)} +span#textcolor2808{color:rgb(0,0,255)} +span#textcolor2809{color:rgb(43,145,175)} +span#textcolor2810{color:rgb(43,145,175)} +span#textcolor2811{color:rgb(163,20,20)} +span#textcolor2812{color:rgb(163,20,20)} +pre#fancyvrb70{padding:5.69054pt;} +pre#fancyvrb70{ border-top: solid 0.4pt; } +pre#fancyvrb70{ border-left: solid 0.4pt; } +pre#fancyvrb70{ border-bottom: solid 0.4pt; } +pre#fancyvrb70{ border-right: solid 0.4pt; } +span#textcolor2813{color:rgb(0,127,0)} +span#textcolor2814{color:rgb(0,127,0)} +span#textcolor2815{color:rgb(0,127,0)} +span#textcolor2816{color:rgb(0,0,255)} +span#textcolor2817{color:rgb(0,127,0)} +span#textcolor2818{color:rgb(0,0,255)} +span#textcolor2819{color:rgb(0,127,0)} +span#textcolor2820{color:rgb(0,0,255)} +span#textcolor2821{color:rgb(0,127,0)} +span#textcolor2822{color:rgb(0,0,255)} +span#textcolor2823{color:rgb(43,145,175)} +span#textcolor2824{color:rgb(43,145,175)} +span#textcolor2825{color:rgb(0,0,255)} +span#textcolor2826{color:rgb(43,145,175)} +span#textcolor2827{color:rgb(0,0,255)} +span#textcolor2828{color:rgb(0,0,255)} +span#textcolor2829{color:rgb(0,0,255)} +span#textcolor2830{color:rgb(163,20,20)} +span#textcolor2831{color:rgb(163,20,20)} +span#textcolor2832{color:rgb(163,20,20)} +span#textcolor2833{color:rgb(163,20,20)} +span#textcolor2834{color:rgb(163,20,20)} +span#textcolor2835{color:rgb(163,20,20)} +span#textcolor2836{color:rgb(0,127,0)} +span#textcolor2837{color:rgb(0,0,255)} +span#textcolor2838{color:rgb(0,0,255)} +span#textcolor2839{color:rgb(43,145,175)} +span#textcolor2840{color:rgb(0,0,255)} +span#textcolor2841{color:rgb(163,20,20)} +span#textcolor2842{color:rgb(163,20,20)} +span#textcolor2843{color:rgb(163,20,20)} +span#textcolor2844{color:rgb(0,127,0)} +span#textcolor2845{color:rgb(0,0,255)} +span#textcolor2846{color:rgb(0,0,255)} +span#textcolor2847{color:rgb(43,145,175)} +span#textcolor2848{color:rgb(0,0,255)} +span#textcolor2849{color:rgb(163,20,20)} +span#textcolor2850{color:rgb(163,20,20)} +span#textcolor2851{color:rgb(163,20,20)} +span#textcolor2852{color:rgb(0,127,0)} +span#textcolor2853{color:rgb(0,0,255)} +span#textcolor2854{color:rgb(0,0,255)} +span#textcolor2855{color:rgb(43,145,175)} +span#textcolor2856{color:rgb(0,0,255)} +span#textcolor2857{color:rgb(163,20,20)} +span#textcolor2858{color:rgb(163,20,20)} +span#textcolor2859{color:rgb(163,20,20)} +span#textcolor2860{color:rgb(0,127,0)} +span#textcolor2861{color:rgb(0,0,255)} +span#textcolor2862{color:rgb(0,0,255)} +span#textcolor2863{color:rgb(0,0,255)} +span#textcolor2864{color:rgb(0,0,255)} +span#textcolor2865{color:rgb(0,0,255)} +span#textcolor2866{color:rgb(0,0,255)} +span#textcolor2867{color:rgb(163,20,20)} +span#textcolor2868{color:rgb(0,0,255)} +span#textcolor2869{color:rgb(43,145,175)} +span#textcolor2870{color:rgb(43,145,175)} +span#textcolor2871{color:rgb(43,145,175)} +span#textcolor2872{color:rgb(163,20,20)} +span#textcolor2873{color:rgb(163,20,20)} +span#textcolor2874{color:rgb(163,20,20)} +span#textcolor2875{color:rgb(0,0,255)} +span#textcolor2876{color:rgb(163,20,20)} +span#textcolor2877{color:rgb(163,20,20)} +span#textcolor2878{color:rgb(163,20,20)} +span#textcolor2879{color:rgb(0,0,255)} +span#textcolor2880{color:rgb(0,0,255)} +span#textcolor2881{color:rgb(0,0,255)} +span#textcolor2882{color:rgb(43,145,175)} +span#textcolor2883{color:rgb(43,145,175)} +span#textcolor2884{color:rgb(163,20,20)} +span#textcolor2885{color:rgb(163,20,20)} +span#textcolor2886{color:rgb(163,20,20)} +span#textcolor2887{color:rgb(163,20,20)} +span#textcolor2888{color:rgb(163,20,20)} +pre#fancyvrb71{padding:5.69054pt;} +pre#fancyvrb71{ border-top: solid 0.4pt; } +pre#fancyvrb71{ border-left: solid 0.4pt; } +pre#fancyvrb71{ border-bottom: solid 0.4pt; } +pre#fancyvrb71{ border-right: solid 0.4pt; } +span#textcolor2889{color:rgb(0,0,255)} +span#textcolor2890{color:rgb(0,0,255)} +/* end css.sty */ + diff --git a/lkmpg.html b/lkmpg.html new file mode 100644 index 0000000..fe5018c --- /dev/null +++ b/lkmpg.html @@ -0,0 +1,5148 @@ + + + The Linux Kernel Module Programming Guide + + + + + + +
+ + + + + + + +

The Linux Kernel Module Programming Guide

+
Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang

+
August 2, 2021
+ + + +
+
+  0.1 Introduction +
  0.1.1 Authorship +
  0.1.2 Acknowledgements +
  0.1.3 What Is A Kernel Module? +
  0.1.4 Kernel module package +
  0.1.5 What Modules are in my Kernel? +
  0.1.6 Do I need to download and compile the kernel? +
  0.1.7 Before We Begin +
 0.2 Headers +
 0.3 Examples +
 0.4 Hello World +
  0.4.1 The Simplest Module +
  0.4.2 Hello and Goodbye +
  0.4.3 The __init and __exit Macros +
  0.4.4 Licensing and Module Documentation +
  0.4.5 Passing Command Line Arguments to a Module +
  0.4.6 Modules Spanning Multiple Files +
  0.4.7 Building modules for a precompiled kernel +
 0.5 Preliminaries +
  0.5.1 How modules begin and end +
  0.5.2 Functions available to modules +
  0.5.3 User Space vs Kernel Space +
  0.5.4 Name Space +
  0.5.5 Code space +
  0.5.6 Device Drivers +
 0.6 Character Device drivers +
  0.6.1 The proc_ops Structure +
  0.6.2 The file structure +
  0.6.3 Registering A Device +
  0.6.4 Unregistering A Device +
  0.6.5 chardev.c +
  0.6.6 Writing Modules for Multiple Kernel Versions +
 0.7 The /proc File System +
  0.7.1 Read and Write a /proc File +
  0.7.2 Manage /proc file with standard filesystem +
  0.7.3 Manage /proc file with seq_file +
 0.8 sysfs: Interacting with your module +
 0.9 Talking To Device Files +
 0.10 System Calls +
 0.11 Blocking Processes and threads +
  0.11.1 Sleep + + + +
  0.11.2 Completions +
 0.12 Avoiding Collisions and Deadlocks +
  0.12.1 Mutex +
  0.12.2 Spinlocks +
  0.12.3 Read and write locks +
  0.12.4 Atomic operations +
 0.13 Replacing Print Macros +
  0.13.1 Replacement +
  0.13.2 Flashing keyboard LEDs +
 0.14 Scheduling Tasks +
  0.14.1 Tasklets +
  0.14.2 Work queues +
 0.15 Interrupt Handlers +
  0.15.1 Interrupt Handlers +
  0.15.2 Detecting button presses +
  0.15.3 Bottom Half +
 0.16 Crypto +
  0.16.1 Hash functions +
  0.16.2 Symmetric key encryption +
 0.17 Standardising the interfaces: The Device Model +
 0.18 Optimizations +
  0.18.1 Likely and Unlikely conditions +
 0.19 Common Pitfalls +
  0.19.1 Using standard libraries +
  0.19.2 Disabling interrupts +
  0.19.3 Sticking your head inside a large carnivore +
 0.20 Where To Go From Here? +
+

0.1 Introduction

+

The Linux Kernel Module Programming Guide is a free book; you may reproduce +and/or modify it under the terms of the Open Software License, version +3.0. +

This book is distributed in the hope it will be useful, but without any warranty, +without even the implied warranty of merchantability or fitness for a particular +purpose. +

The author encourages wide distribution of this book for personal or commercial +use, provided the above copyright notice remains intact and the method adheres to +the provisions of the Open Software License. In summary, you may copy and +distribute this book free of charge or for a profit. No explicit permission is required +from the author for reproduction of this book in any medium, physical or +electronic. +

Derivative works and translations of this document must be placed under the +Open Software License, and the original copyright notice must remain intact. If you +have contributed new material to this book, you must make the material and source +code available for your revisions. Please make revisions and updates available directly + + + +to the document maintainer, Peter Jay Salzman <p@dirac.org>. This will allow +for the merging of updates and provide consistent revisions to the Linux +community. +

If you publish or distribute this book commercially, donations, royalties, and/or +printed copies are greatly appreciated by the author and the Linux Documentation +Project (LDP). Contributing in this way shows your support for free software and +the LDP. If you have questions or comments, please contact the address +above. +

+

+

0.1.1 Authorship

+

The Linux Kernel Module Programming Guide was originally written for the 2.2 +kernels by Ori Pomerantz. Eventually, Ori no longer had time to maintain the +document. After all, the Linux kernel is a fast moving target. Peter Jay Salzman took +over maintenance and updated it for the 2.4 kernels. Eventually, Peter no longer had +time to follow developments with the 2.6 kernel, so Michael Burian became a +co-maintainer to update the document for the 2.6 kernels. Bob Mottram updated the +examples for 3.8+ kernels. Jim Huang upgraded to recent kernel versions (v5.x) and +revise LaTeX scripts. +

+

+

0.1.2 Acknowledgements

+

The following people have contributed corrections or good suggestions: Ignacio +Martin, David Porter, Daniele Paolo Scarpazza, Dimo Velev, Francois Audeon, Horst +Schirmeier, and Roman Lakeev. +

+

+

0.1.3 What Is A Kernel Module?

+

So, you want to write a kernel module. You know C, you have written a few normal +programs to run as processes, and now you want to get to where the real action is, to +where a single wild pointer can wipe out your file system and a core dump means a +reboot. +

What exactly is a kernel module? Modules are pieces of code that can be loaded +and unloaded into the kernel upon demand. They extend the functionality of the +kernel without the need to reboot the system. For example, one type of module is the +device driver, which allows the kernel to access hardware connected to the system. +Without modules, we would have to build monolithic kernels and add new +functionality directly into the kernel image. Besides having larger kernels, this has +the disadvantage of requiring us to rebuild and reboot the kernel every time we want + + + +new functionality. +

+

+

0.1.4 Kernel module package

+

Linux distributions provide the commands modprobe, insmod and depmod within a +package. +

On Ubuntu/Debian: +

+
1sudo apt-get install build-essential kmod
+

On Arch Linux: +

+
1sudo pacman -S gcc kmod
+

+

+

0.1.5 What Modules are in my Kernel?

+

To discover what modules are already loaded within your current kernel use the +command lsmod. +

+
1sudo lsmod
+

Modules are stored within the file /proc/modules, so you can also see them with: +

+
1sudo cat /proc/modules
+

This can be a long list, and you might prefer to search for something particular. +To search for the fat module: +

+
1sudo lsmod | grep fat
+ + + +

+

+

0.1.6 Do I need to download and compile the kernel?

+

For the purposes of following this guide you don’t necessarily need to do that. +However, it would be wise to run the examples within a test distribution running +on a virtual machine in order to avoid any possibility of messing up your +system. +

+

+

0.1.7 Before We Begin

+

Before we delve into code, there are a few issues we need to cover. Everyone’s system +is different and everyone has their own groove. Getting your first "hello world" +program to compile and load correctly can sometimes be a trick. Rest assured, after +you get over the initial hurdle of doing it for the first time, it will be smooth sailing +thereafter. +

+

    +
  1. Modversioning. A module compiled for one kernel will not load if you boot + a different kernel unless you enable CONFIG_MODVERSIONS in the kernel. + We will not go into module versioning until later in this guide. Until + we cover modversions, the examples in the guide may not work if you + are running a kernel with modversioning turned on. However, most stock + Linux distribution kernels come with it turned on. If you are having trouble + loading the modules because of versioning errors, compile a kernel with + modversioning turned off. +
  2. +
  3. +

    Using X Window System. It is highly recommended that you extract, + compile and load all the examples this guide discusses. It is also highly + recommended you do this from a console. You should not be working on + this stuff in X Window System. +

    Modules can not print to the screen like printf() can, but they can log + information and warnings, which ends up being printed on your screen, but + only on a console. If you insmod a module from an xterm, the information + and warnings will be logged, but only to your systemd journal. You will + not see it unless you look through your journalctl. See 0.4 for details. + To have immediate access to this information, do all your work from the + console.

+ + + +

+

+

0.2 Headers

+

Before you can build anything you’ll need to install the header files for your +kernel. +

On Ubuntu/Debian: +

+
1sudo apt-get update 
+2apt-cache search linux-headers-`uname -r`
+

On Arch Linux: +

+
1sudo pacman -S linux-libre-headers
+

This will tell you what kernel header files are available. Then for example: +

+
1sudo apt-get install kmod linux-headers-5.4.0-80-generic
+

+

+

0.3 Examples

+

All the examples from this document are available within the examples subdirectory. +

If there are any compile errors then you might have a more recent kernel version +or need to install the corresponding kernel header files. +

+

+

0.4 Hello World

+ + + +

+

+

0.4.1 The Simplest Module

+

Most people learning programming start out with some sort of "hello world" +example. I don’t know what happens to people who break with this tradition, but I +think it is safer not to find out. We will start with a series of hello world +programs that demonstrate the different aspects of the basics of writing a kernel +module. +

Here is the simplest module possible. +

Make a test directory: +

+
1mkdir -p ~/develop/kernel/hello-1 
+2cd ~/develop/kernel/hello-1
+

Paste this into you favorite editor and save it as hello-1.c: +

+

+
1/* 
+2 *  hello-1.c - The simplest kernel module. 
+3 */ 
+4#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+5#include <linux/module.h> /* Needed by all modules */ 
+6 
+7int init_module(void) 
+8{ 
+9    pr_info("Hello world 1.\n"); 
+10 
+11    /* 
+12     * A non 0 return means init_module failed; module can't be loaded. 
+13     */ 
+14    return 0; 
+15} 
+16 
+17void cleanup_module(void) 
+18{ 
+19    pr_info("Goodbye world 1.\n"); 
+20} 
+21 
+22MODULE_LICENSE("GPL");
+

Now you will need a Makefile. If you copy and paste this, change the indentation +to use tabs, not spaces. +

+

+
1obj-m += hello-1.o 
+2 
+3all: 
+4              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+5 
+6clean: 
+7              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

And finally just: +

+
1make
+

If all goes smoothly you should then find that you have a compiled hello-1.ko +module. You can find info on it with the command: +

+
1sudo modinfo hello-1.ko
+

At this point the command: +

+
1sudo lsmod | grep hello
+

should return nothing. You can try loading your shiny new module with: + + + +

+
1sudo insmod hello-1.ko
+

The dash character will get converted to an underscore, so when you again try: +

+
1sudo lsmod | grep hello
+

you should now see your loaded module. It can be removed again with: +

+
1sudo rmmod hello_1
+

Notice that the dash was replaced by an underscore. To see what just happened in +the logs: +

+
1journalctl --since "1 hour ago" | grep kernel
+

You now know the basics of creating, compiling, installing and removing modules. +Now for more of a description of how this module works. +

Kernel modules must have at least two functions: a "start" (initialization) +function called init_module() which is called when the module is insmoded into +the kernel, and an "end" (cleanup) function called cleanup_module() which is +called just before it is removed from the kernel. Actually, things have changed +starting with kernel 2.3.13. You can now use whatever name you like for the start and +end functions of a module, and you will learn how to do this in Section 2.3. +In fact, the new method is the preferred method. However, many people +still use init_module() and cleanup_module() for their start and end +functions. +

Typically, init_module() either registers a handler for something with the kernel, +or it replaces one of the kernel functions with its own code (usually code to do +something and then call the original function). The cleanup_module() function is +supposed to undo whatever init_module() did, so the module can be unloaded +safely. +

Lastly, every kernel module needs to include linux/module.h. We needed to +include linux/kernel.h only for the macro expansion for the pr_alert() log level, +which you’ll learn about in Section 2.1.1. +

+

    + + + +
  1. A point about coding style. Another thing which may not be immediately + obvious to anyone getting started with kernel programming is that + indentation within your code should be using tabs and not spaces. It is + one of the coding conventions of the kernel. You may not like it, but you’ll + need to get used to it if you ever submit a patch upstream. +
  2. +
  3. Introducing print macros. In the beginning there was printk, usually + followed by a priority such as KERN_INFO or KERN_DEBUG. More recently + this can also be expressed in abbreviated form using a set of print macros, + such as pr_info and pr_debug. This just saves some mindless keyboard + bashing and looks a bit neater. They can be found within linux/printk.h. + Take time to read through the available priority macros. +
  4. +
  5. +

    About Compiling. Kernel modules need to be compiled a bit differently + from regular userspace apps. Former kernel versions required us to + care much about these settings, which are usually stored in Makefiles. + Although hierarchically organized, many redundant settings accumulated + in sublevel Makefiles and made them large and rather difficult to maintain. + Fortunately, there is a new way of doing these things, called kbuild, and + the build process for external loadable modules is now fully integrated into + the standard kernel build mechanism. To learn more on how to compile + modules which are not part of the official kernel (such as all the examples + you will find in this guide), see file Documentation/kbuild/modules.rst. +

    Additional details about Makefiles for kernel modules are available in + Documentation/kbuild/makefiles.rst. Be sure to read this and the + related files before starting to hack Makefiles. It will probably save you + lots of work. +

    +

    +

    Here is another exercise for the reader. See that comment above + the return statement in init_module()? Change the return + value to something negative, recompile and load the module + again. What happens?

    +
+ + + +

+

+

0.4.2 Hello and Goodbye

+

In early kernel versions you had to use the init_module and cleanup_module +functions, as in the first hello world example, but these days you can name those +anything you want by using the module_init and module_exit macros. +These macros are defined in linux/init.h. The only requirement is that +your init and cleanup functions must be defined before calling the those +macros, otherwise you’ll get compilation errors. Here is an example of this +technique: +

+

+
1/* 
+2 *  hello-2.c - Demonstrating the module_init() and module_exit() macros. 
+3 *  This is preferred over using init_module() and cleanup_module(). 
+4 */ 
+5#include <linux/init.h>   /* Needed for the macros */ 
+6#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+7#include <linux/module.h> /* Needed by all modules */ 
+8 
+9static int __init hello_2_init(void) 
+10{ 
+11    pr_info("Hello, world 2\n"); 
+12    return 0; 
+13} 
+14 
+15static void __exit hello_2_exit(void) 
+16{ 
+17    pr_info("Goodbye, world 2\n"); 
+18} 
+19 
+20module_init(hello_2_init); 
+21module_exit(hello_2_exit); 
+22 
+23MODULE_LICENSE("GPL");
+

So now we have two real kernel modules under our belt. Adding another module +is as simple as this: +

+

+
1obj-m += hello-1.o 
+2obj-m += hello-2.o 
+3 
+4all: 
+5              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+6 
+7clean: 
+8              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

Now have a look at linux/drivers/char/Makefile for a real world example. As +you can see, some things get hardwired into the kernel (obj-y) but where are all +those obj-m gone? Those familiar with shell scripts will easily be able to spot them. +For those not, the obj-$(CONFIG_FOO) entries you see everywhere expand into obj-y +or obj-m, depending on whether the CONFIG_FOO variable has been set to y or m. +While we are at it, those were exactly the kind of variables that you have set in the +linux/.config file, the last time when you said make menuconfig or something like +that. +

+

+

0.4.3 The __init and __exit Macros

+

This demonstrates a feature of kernel 2.2 and later. Notice the change in the +definitions of the init and cleanup functions. The __init macro causes the init +function to be discarded and its memory freed once the init function finishes for +built-in drivers, but not loadable modules. If you think about when the init function +is invoked, this makes perfect sense. +

There is also an __initdata which works similarly to __init but for init +variables rather than functions. +

The __exit macro causes the omission of the function when the module is +built into the kernel, and like __init, has no effect for loadable modules. +Again, if you consider when the cleanup function runs, this makes complete +sense; built-in drivers do not need a cleanup function, while loadable modules +do. + + + +

These macros are defined in linux/init.h and serve to free up kernel memory. +When you boot your kernel and see something like Freeing unused kernel memory: +236k freed, this is precisely what the kernel is freeing. +

+

+
1/* 
+2 *  hello-3.c - Illustrating the __init, __initdata and __exit macros. 
+3 */ 
+4#include <linux/init.h>   /* Needed for the macros */ 
+5#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+6#include <linux/module.h> /* Needed by all modules */ 
+7 
+8static int hello3_data __initdata = 3; 
+9 
+10static int __init hello_3_init(void) 
+11{ 
+12    pr_info("Hello, world %d\n", hello3_data); 
+13    return 0; 
+14} 
+15 
+16static void __exit hello_3_exit(void) 
+17{ 
+18    pr_info("Goodbye, world 3\n"); 
+19} 
+20 
+21module_init(hello_3_init); 
+22module_exit(hello_3_exit); 
+23 
+24MODULE_LICENSE("GPL");
+

+

+

0.4.4 Licensing and Module Documentation

+

Honestly, who loads or even cares about proprietary modules? If you do then you +might have seen something like this: + + + +

+
+$ sudo insmod xxxxxx.ko
+loading out-of-tree module taints kernel.
+module license 'unspecified' taints kernel.
+
+

+

You can use a few macros to indicate the license for your module. Some examples +are "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual +MIT/GPL", "Dual MPL/GPL" and "Proprietary". They are defined within +linux/module.h. +

To reference what license you’re using a macro is available called +MODULE_LICENSE. This and a few other macros describing the module are +illustrated in the below example. +

+

+
1/* 
+2 *  hello-4.c - Demonstrates module documentation. 
+3 */ 
+4#include <linux/init.h>   /* Needed for the macros */ 
+5#include <linux/kernel.h> /* Needed for KERN_INFO */ 
+6#include <linux/module.h> /* Needed by all modules */ 
+7 
+8MODULE_LICENSE("GPL"); 
+9MODULE_AUTHOR("LKMPG"); 
+10MODULE_DESCRIPTION("A sample driver"); 
+11MODULE_SUPPORTED_DEVICE("testdevice"); 
+12 
+13static int __init init_hello_4(void) 
+14{ 
+15    pr_info("Hello, world 4\n"); 
+16    return 0; 
+17} 
+18 
+19static void __exit cleanup_hello_4(void) 
+20{ 
+21    pr_info("Goodbye, world 4\n"); 
+22} 
+23 
+24module_init(init_hello_4); 
+25module_exit(cleanup_hello_4);
+

+

+

0.4.5 Passing Command Line Arguments to a Module

+

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, (defined in linux/moduleparam.h) 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 example code should clear up my admittedly lousy +explanation. +

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. If you’d like to use arrays of integers or strings see +module_param_array() and module_param_string(). +

+

+
1int myint = 3; 
+2module_param(myint, int, 0);
+

Arrays are supported too, but things are a bit different now than they were in the +olden days. To keep track of the number of parameters you need to pass a + + + +pointer to a count variable as third parameter. At your option, you could +also ignore the count and pass NULL instead. We show both possibilities +here: +

+

+
1int myintarray[2]; 
+2module_param_array(myintarray, int, NULL, 0); /* not interested in count */ 
+3 
+4short myshortarray[4]; 
+5int count; 
+6module_param_array(myshortarray, short, &count, 0); /* put count into "count" variable */
+

A good use for this is to have the module variable’s default values set, like an port +or IO address. If the variables contain the default values, then perform autodetection +(explained elsewhere). Otherwise, keep the current value. This will be made clear +later on. +

Lastly, there’s a macro function, MODULE_PARM_DESC(), that is used to +document arguments that the module can take. It takes two parameters: a variable +name and a free form string describing that variable. +

+

+
1/* 
+2 *  hello-5.c - Demonstrates command line argument passing to a module. 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/moduleparam.h> 
+8#include <linux/stat.h> 
+9 
+10MODULE_LICENSE("GPL"); 
+11 
+12static short int myshort = 1; 
+13static int myint = 420; 
+14static long int mylong = 9999; 
+15static char *mystring = "blah"; 
+16static int myintArray[2] = {-1, -1}; 
+17static int arr_argc = 0; 
+18 
+19/* 
+20 * module_param(foo, int, 0000) 
+21 * The first param is the parameters name 
+22 * The second param is it's data type 
+23 * The final argument is the permissions bits, 
+24 * for exposing parameters in sysfs (if non-zero) at a later stage. 
+25 */ 
+26 
+27module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 
+28MODULE_PARM_DESC(myshort, "A short integer"); 
+29module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 
+30MODULE_PARM_DESC(myint, "An integer"); 
+31module_param(mylong, long, S_IRUSR); 
+32MODULE_PARM_DESC(mylong, "A long integer"); 
+33module_param(mystring, charp, 0000); 
+34MODULE_PARM_DESC(mystring, "A character string"); 
+35 
+36/* 
+37 * module_param_array(name, type, num, perm); 
+38 * The first param is the parameter's (in this case the array's) name 
+39 * The second param is the data type of the elements of the array 
+40 * The third argument is a pointer to the variable that will store the number 
+41 * of elements of the array initialized by the user at module loading time 
+42 * The fourth argument is the permission bits 
+43 */ 
+44module_param_array(myintArray, int, &arr_argc, 0000); 
+45MODULE_PARM_DESC(myintArray, "An array of integers"); 
+46 
+47static int __init hello_5_init(void) 
+48{ 
+49    int i; 
+50    pr_info("Hello, world 5\n=============\n"); 
+51    pr_info("myshort is a short integer: %hd\n", myshort); 
+52    pr_info("myint is an integer: %d\n", myint); 
+53    pr_info("mylong is a long integer: %ld\n", mylong); 
+54    pr_info("mystring is a string: %s\n", mystring); 
+55 
+56    for (i = 0; i < (sizeof myintArray / sizeof(int)); i++) 
+57        pr_info("myintArray[%d] = %d\n", i, myintArray[i]); 
+58 
+59    pr_info("got %d arguments for myintArray.\n", arr_argc); 
+60    return 0; 
+61} 
+62 
+63static void __exit hello_5_exit(void) 
+64{ 
+65    pr_info("Goodbye, world 5\n"); 
+66} 
+67 
+68module_init(hello_5_init); 
+69module_exit(hello_5_exit);
+

I would recommend playing around with this code: +

+
1$ sudo insmod hello-5.ko mystring="bebop" myintArray=-1 
+2myshort is a short integer: 1 
+3myint is an integer: 20 
+4mylong is a long integer: 9999 
+5mystring is a string: bebop 
+6myintArray is -1 and 420 
+7 
+8$ sudo rmmod hello-5 
+9Goodbye, world 5 
+10 
+11$ sudo insmod hello-5.ko mystring="supercalifragilisticexpialidocious" myintArray=-1,-1 
+12myshort is a short integer: 1 
+13myint is an integer: 20 
+14mylong is a long integer: 9999 
+15mystring is a string: supercalifragilisticexpialidocious 
+16myintArray is -1 and -1 
+17 
+18$ sudo rmmod hello-5 
+19Goodbye, world 5 
+20 
+21$ sudo insmod hello-5.ko mylong=hello 
+22hello-5.o: invalid argument syntax for mylong: 'h'
+

+

+

0.4.6 Modules Spanning Multiple Files

+

Sometimes it makes sense to divide a kernel module between several source +files. +

Here is an example of such a kernel module. +

+
1/* 
+2 *  start.c - Illustration of multi filed modules 
+3 */ 
+4 
+5#include <linux/kernel.h> /* We're doing kernel work */ 
+6#include <linux/module.h> /* Specifically, a module */ 
+7 
+8int init_module(void) 
+9{ 
+10    pr_info("Hello, world - this is the kernel speaking\n"); 
+11    return 0; 
+12} 
+13 
+14MODULE_LICENSE("GPL");
+

The next file: +

+
1/* 
+2 *  stop.c - Illustration of multi filed modules 
+3 */ 
+4 
+5#include <linux/kernel.h> /* We're doing kernel work */ 
+6#include <linux/module.h> /* Specifically, a module  */ 
+7 
+8void cleanup_module() 
+9{ 
+10    pr_info("Short is the life of a kernel module\n"); 
+11} 
+12 
+13MODULE_LICENSE("GPL");
+

And finally, the makefile: +

+

+
1obj-m += hello-1.o 
+2obj-m += hello-2.o 
+3obj-m += hello-3.o 
+4obj-m += hello-4.o 
+5obj-m += hello-5.o 
+6obj-m += startstop.o 
+7startstop-objs := start.o stop.o 
+8 
+9all: 
+10              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 
+11 
+12clean: 
+13              make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
+

This is the complete makefile for all the examples we have seen so far. The first +five lines are nothing special, but for the last example we will need two lines. First we +invent an object name for our combined module, second we tell make what object +files are part of that module. + + + +

+

+

0.4.7 Building modules for a precompiled kernel

+

Obviously, we strongly suggest you to recompile your kernel, so that you can enable +a number of useful debugging features, such as forced module unloading +(MODULE_FORCE_UNLOAD): when this option is enabled, you can force the +kernel to unload a module even when it believes it is unsafe, via a sudo rmmod -f +module command. This option can save you a lot of time and a number of reboots +during the development of a module. If you do not want to recompile your kernel +then you should consider running the examples within a test distribution on a virtual +machine. If you mess anything up then you can easily reboot or restore the virtual +machine (VM). +

There are a number of cases in which you may want to load your module into a +precompiled running kernel, such as the ones shipped with common Linux +distributions, or a kernel you have compiled in the past. In certain circumstances you +could require to compile and insert a module into a running kernel which you are not +allowed to recompile, or on a machine that you prefer not to reboot. If you +can’t think of a case that will force you to use modules for a precompiled +kernel you might want to skip this and treat the rest of this chapter as a big +footnote. +

Now, if you just install a kernel source tree, use it to compile your kernel module +and you try to insert your module into the kernel, in most cases you would obtain an +error as follows: + + + +

+
+insmod: error inserting 'poet_atkm.ko': -1 Invalid module format
+
+

+

Less cryptical information are logged to the systemd journal: + + + +

+
+Jun  4 22:07:54 localhost kernel: poet_atkm: version magic '2.6.5-1.358custom 686
+REGPARM 4KSTACKS gcc-3.3' should be '2.6.5-1.358 686 REGPARM 4KSTACKS gcc-3.3'
+
+

+

In other words, your kernel refuses to accept your module because version strings +(more precisely, version magics) do not match. Incidentally, version magics are stored +in the module object in the form of a static string, starting with vermagic:. Version +data are inserted in your module when it is linked against the init/vermagic.o file. +To inspect version magics and other strings stored in a given module, issue the +modinfo module.ko command: + + + +

+
+$ modinfo hello-4.ko
+description:    A sample driver
+author:         LKMPG
+license:        GPL
+srcversion:     B2AA7FBFCC2C39AED665382
+depends:
+retpoline:      Y
+name:           hello_4
+vermagic:       5.4.0-70-generic SMP mod_unload modversions
+
+

+

To overcome this problem we could resort to the –force-vermagic option, but +this solution is potentially unsafe, and unquestionably inacceptable in production +modules. Consequently, we want to compile our module in an environment which was +identical to the one in which our precompiled kernel was built. How to do this, is the +subject of the remainder of this chapter. +

First of all, make sure that a kernel source tree is available, having exactly the +same version as your current kernel. Then, find the configuration file which was used +to compile your precompiled kernel. Usually, this is available in your current boot +directory, under a name like config-2.6.x. You may just want to copy it to your kernel +source tree: cp /boot/config-`uname -r` .config. +

Let’s focus again on the previous error message: a closer look at the version magic +strings suggests that, even with two configuration files which are exactly the same, a +slight difference in the version magic could be possible, and it is sufficient to prevent +insertion of the module into the kernel. That slight difference, namely the custom +string which appears in the module’s version magic and not in the kernel’s one, +is due to a modification with respect to the original, in the makefile that +some distribution include. Then, examine your /usr/src/linux/Makefile, +and make sure that the specified version information matches exactly the +one used for your current kernel. For example, you makefile could start as +follows: + + + +

+
+VERSION = 5
+PATCHLEVEL = 14
+SUBLEVEL = 0
+EXTRAVERSION = -rc2
+
+

+

In this case, you need to restore the value of symbol EXTRAVERSION to +-rc2. We suggest to keep a backup copy of the makefile used to compile +your kernel available in /lib/modules/5.14.0-rc2/build. A simple cp +/lib/modules/‘uname-r‘/build/Makefile /usr/src/linux-‘uname -r‘ should +suffice. Additionally, if you already started a kernel build with the previous (wrong) +Makefile, you should also rerun make, or directly modify symbol UTS_RELEASE in +file /usr/src/linux-5.14.0/include/linux/version.h according to contents of file +/lib/modules/5.14.0/build/include/linux/version.h, or overwrite the latter +with the first. +

Now, please run make to update configuration and version headers and +objects: + + + +

+
+$ make
+CHK     include/linux/version.h
+UPD     include/linux/version.h
+SYMLINK include/asm -> include/asm-i386
+SPLIT   include/linux/autoconf.h -> include/config/*
+HOSTCC  scripts/basic/fixdep
+HOSTCC  scripts/basic/split-include
+HOSTCC  scripts/basic/docproc
+HOSTCC  scripts/conmakehash
+HOSTCC  scripts/kallsyms
+CC      scripts/empty.o
+
+

+

If you do not desire to actually compile the kernel, you can interrupt the build +process (CTRL-C) just after the SPLIT line, because at that time, the files you need +will be are ready. Now you can turn back to the directory of your module and +compile it: It will be built exactly according to your current kernel settings, and it +will load into it without any errors. +

+

+

0.5 Preliminaries

+

+

+

0.5.1 How modules begin and end

+

A program usually begins with a main() function, executes a bunch of instructions +and terminates upon completion of those instructions. Kernel modules work a bit +differently. A module always begin with either the init_module or the function you +specify with module_init call. This is the entry function for modules; it tells the +kernel what functionality the module provides and sets up the kernel to run the +module’s functions when they are needed. Once it does this, entry function returns +and the module does nothing until the kernel wants to do something with the code +that the module provides. +

All modules end by calling either cleanup_module or the function you specify +with the module_exit call. This is the exit function for modules; it undoes +whatever entry function did. It unregisters the functionality that the entry function +registered. + + + +

Every module must have an entry function and an exit function. Since there’s +more than one way to specify entry and exit functions, I’ll try my best to use the +terms “entry function” and “exit function”, but if I slip and simply refer +to them as init_module and cleanup_module, I think you’ll know what I +mean. +

+

+

0.5.2 Functions available to modules

+

Programmers use functions they do not define all the time. A prime example of +this is printf(). You use these library functions which are provided by the +standard C library, libc. The definitions for these functions do not actually +enter your program until the linking stage, which insures that the code (for +printf() for example) is available, and fixes the call instruction to point to that +code. +

Kernel modules are different here, too. In the hello world example, you might +have noticed that we used a function, pr_info() but did not include a standard I/O +library. That is 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. +

One point to keep in mind is the difference between library functions +and system calls. Library functions are higher level, run completely in user +space and provide a more convenient interface for the programmer to the +functions that do the real work — system calls. System calls run in kernel +mode on the user’s behalf and are provided by the kernel itself. The library +function printf() may look like a very general printing function, but all it +really does is format the data into strings and write the string data using +the low-level system call write(), which then sends the data to standard +output. +

Would you like to see what system calls are made by printf()? It is easy! Compile +the following program: +

+

+
1#include <stdio.h> 
+2 
+3int main(void) 
+4{ 
+5    printf("hello"); 
+6    return 0; 
+7}
+

with gcc -Wall -o hello hello.c. Run the exectable with strace ./hello. Are +you impressed? Every line you see corresponds to a system call. strace is a handy +program that gives you details about what system calls a program is making, +including which call is made, what its arguments are and what it returns. It is an +invaluable tool for figuring out things like what files a program is trying to access. +Towards the end, you will see a line which looks like write(1, "hello", 5hello). +There it is. The face behind the printf() mask. You may not be familiar with write, +since most people use library functions for file I/O (like fopen, fputs, fclose). If that + + + +is the case, try looking at man 2 write. The 2nd man section is devoted +to system calls (like kill() and read()). The 3rd man section is devoted to +library calls, which you would probably be more familiar with (like cosh() and +random()). +

You can even write modules to replace the kernel’s system calls, which we will do +shortly. Crackers often make use of this sort of thing for backdoors or trojans, but +you can write your own modules to do more benign things, like have the kernel +write Tee hee, that tickles! everytime someone tries to delete a file on your +system. +

+

+

0.5.3 User Space vs Kernel Space

+

A kernel is all about access to resources, whether the resource in question happens to +be a video card, a hard drive or even memory. Programs often compete for the same +resource. As I just saved this document, updatedb started updating the locate +database. My vim session and updatedb are both using the hard drive concurrently. +The kernel needs to keep things orderly, and not give users access to resources +whenever they feel like it. To this end, a CPU can run in different modes. Each mode +gives a different level of freedom to do what you want on the system. The Intel 80386 +architecture had 4 of these modes, which were called rings. Unix uses only +two rings; the highest ring (ring 0, also known as “supervisor mode” where +everything is allowed to happen) and the lowest ring, which is called “user +mode”. +

Recall the discussion about library functions vs system calls. Typically, you use a +library function in user mode. The library function calls one or more system calls, +and these system calls execute on the library function’s behalf, but do so in +supervisor mode since they are part of the kernel itself. Once the system call +completes its task, it returns and execution gets transfered back to user +mode. +

+

+

0.5.4 Name Space

+

When you write a small C program, you use variables which are convenient and make +sense to the reader. If, on the other hand, you are writing routines which will be part +of a bigger problem, any global variables you have are part of a community of other +peoples’ global variables; some of the variable names can clash. When a program has +lots of global variables which aren’t meaningful enough to be distinguished, you get +namespace pollution. In large projects, effort must be made to remember reserved +names, and to find ways to develop a scheme for naming unique variable names and +symbols. +

When writing kernel code, even the smallest module will be linked against the + + + +entire kernel, so this is definitely an issue. The best way to deal with this is to declare +all your variables as static and to use a well-defined prefix for your symbols. By +convention, all kernel prefixes are lowercase. If you do not want to declare everything +as static, another option is to declare a symbol table and register it with a kernel. We +will get to this later. +

The file /proc/kallsyms holds all the symbols that the kernel knows about and +which are therefore accessible to your modules since they share the kernel’s +codespace. +

+

+

0.5.5 Code space

+

Memory management is a very complicated subject and the majority of O’Reilly’s +"Understanding The Linux Kernel" exclusively covers memory management! +We are not setting out to be experts on memory managements, but we do +need to know a couple of facts to even begin worrying about writing real +modules. +

If you have not thought about what a segfault really means, you may be surprised +to hear that pointers do not actually point to memory locations. Not real +ones, anyway. When a process is created, the kernel sets aside a portion of +real physical memory and hands it to the process to use for its executing +code, variables, stack, heap and other things which a computer scientist +would know about. This memory begins with 0x00000000 and extends up to +whatever it needs to be. Since the memory space for any two processes do not +overlap, every process that can access a memory address, say 0xbffff978, would +be accessing a different location in real physical memory! The processes +would be accessing an index named 0xbffff978 which points to some kind of +offset into the region of memory set aside for that particular process. For +the most part, a process like our Hello, World program can’t access the +space of another process, although there are ways which we will talk about +later. +

The kernel has its own space of memory as well. Since a module is code which +can be dynamically inserted and removed in the kernel (as opposed to a +semi-autonomous object), it shares the kernel’s codespace rather than having its own. +Therefore, if your module segfaults, the kernel segfaults. And if you start writing +over data because of an off-by-one error, then you’re trampling on kernel +data (or code). This is even worse than it sounds, so try your best to be +careful. +

By the way, I would like to point out that the above discussion is true for any +operating system which uses a monolithic kernel. This is not quite the same thing as +"building all your modules into the kernel", although the idea is the same. There are +things called microkernels which have modules which get their own codespace. The +GNU Hurd and the Zircon kernel of Google Fuchsia are two examples of a +microkernel. + + + +

+

+

0.5.6 Device Drivers

+

One class of module is the device driver, which provides functionality for hardware +like a serial port. On Unix, each piece of hardware is represented by a file located in +/dev named a device file which provides the means to communicate with the +hardware. The device driver provides the communication on behalf of a +user program. So the es1370.ko sound card device driver might connect the +/dev/sound device file to the Ensoniq IS1370 sound card. A userspace program like +mp3blaster can use /dev/sound without ever knowing what kind of sound card is +installed. +

Let’s look at some device files. Here are device files which represent the first three +partitions on the primary master IDE hard drive: + + + +

+
+$ ls -l /dev/hda[1-3]
+brw-rw----  1 root  disk  3, 1 Jul  5  2000 /dev/hda1
+brw-rw----  1 root  disk  3, 2 Jul  5  2000 /dev/hda2
+brw-rw----  1 root  disk  3, 3 Jul  5  2000 /dev/hda3
+
+

+

Notice the column of numbers separated by a comma. The first number is called +the device’s major number. The second number is the minor number. The major +number tells you which driver is used to access the hardware. Each driver is assigned +a unique major number; all device files with the same major number are controlled +by the same driver. All the above major numbers are 3, because they’re all controlled +by the same driver. +

The minor number is used by the driver to distinguish between the various +hardware it controls. Returning to the example above, although all three devices are +handled by the same driver they have unique minor numbers because the driver sees +them as being different pieces of hardware. +

Devices are divided into two types: character devices and block devices. The +difference is that block devices have a buffer for requests, so they can choose the best +order in which to respond to the requests. This is important in the case of storage +devices, where it is faster to read or write sectors which are close to each other, +rather than those which are further apart. Another difference is that block devices +can only accept input and return output in blocks (whose size can vary according to +the device), whereas character devices are allowed to use as many or as few bytes +as they like. Most devices in the world are character, because they don’t +need this type of buffering, and they don’t operate with a fixed block size. +You can tell whether a device file is for a block device or a character device +by looking at the first character in the output of ls -l. If it is ‘b’ then it +is a block device, and if it is ‘c’ then it is a character device. The devices +you see above are block devices. Here are some character devices (the serial +ports): + + + +

+
+crw-rw----  1 root  dial 4, 64 Feb 18 23:34 /dev/ttyS0
+crw-r-----  1 root  dial 4, 65 Nov 17 10:26 /dev/ttyS1
+crw-rw----  1 root  dial 4, 66 Jul  5  2000 /dev/ttyS2
+crw-rw----  1 root  dial 4, 67 Jul  5  2000 /dev/ttyS3
+
+

+

If you want to see which major numbers have been assigned, you can look at +Documentation/devices.txt. +

When the system was installed, all of those device files were created by the +mknod command. To create a new char device named ‘coffee’ with major/minor +number 12 and 2, simply do mknod /dev/coffee c 12 2. You do not have to put your +device files into /dev, but it is done by convention. Linus put his device files in /dev, +and so should you. However, when creating a device file for testing purposes, it is +probably OK to place it in your working directory where you compile the kernel +module. Just be sure to put it in the right place when you’re done writing the device +driver. +

I would like to make a few last points which are implicit from the above +discussion, but I would like to make them explicit just in case. When a device file is +accessed, the kernel uses the major number of the file to determine which driver +should be used to handle the access. This means that the kernel doesn’t really need +to use or even know about the minor number. The driver itself is the only thing that +cares about the minor number. It uses the minor number to distinguish between +different pieces of hardware. +

By the way, when I say "hardware", I mean something a bit more abstract +than a PCI card that you can hold in your hand. Look at these two device +files: + + + +

+
+$ ls -l /dev/sda /dev/sdb
+brw-rw---- 1 root disk 8,  0 Jan  3 09:02 /dev/sda
+brw-rw---- 1 root disk 8, 16 Jan  3 09:02 /dev/sdb
+
+

+

By now you can look at these two device files and know instantly that they are +block devices and are handled by same driver (block major 8). Sometimes two device +files with the same major but different minor number can actually represent the same +piece of physical hardware. So just be aware that the word “hardware” in our +discussion can mean something very abstract. +

+

+

0.6 Character Device drivers

+

+

+

0.6.1 The proc_ops Structure

+

The proc_ops structure is defined in /usr/include/linux/fs.h, and holds pointers +to functions defined by the driver that perform various operations on the device. +Each field of the structure corresponds to the address of some function defined by the +driver to handle a requested operation. +

For example, every character driver needs to define a function that reads from the +device. The proc_ops structure holds the address of the module’s function that +performs that operation. Here is what the definition looks like for kernel +3.0: +

+

+
1struct proc_ops { 
+2    struct module *owner; 
+3    loff_t (*llseek) (struct file *, loff_t, int); 
+4    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 
+5    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 
+6    ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); 
+7    ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); 
+8    int (*iterate) (struct file *, struct dir_context *); 
+9    unsigned int (*poll) (struct file *, struct poll_table_struct *); 
+10    long (*unlocked_ioctl) (struct file *, unsigned intunsigned long); 
+11    long (*compat_ioctl) (struct file *, unsigned intunsigned long); 
+12    int (*mmap) (struct file *, struct vm_area_struct *); 
+13    int (*open) (struct inode *, struct file *); 
+14    int (*flush) (struct file *, fl_owner_t id); 
+15    int (*release) (struct inode *, struct file *); 
+16    int (*fsync) (struct file *, loff_t, loff_t, int datasync); 
+17    int (*aio_fsync) (struct kiocb *, int datasync); 
+18    int (*fasync) (intstruct file *, int); 
+19    int (*lock) (struct file *, intstruct file_lock *); 
+20    ssize_t (*sendpage) (struct file *, struct page *, intsize_t, loff_t *, int); 
+21    unsigned long (*get_unmapped_area)(struct file *, unsigned longunsigned longunsigned longunsigned long); 
+22    int (*check_flags)(int); 
+23    int (*flock) (struct file *, intstruct file_lock *); 
+24    ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_tunsigned int); 
+25    ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_tunsigned int); 
+26    int (*setlease)(struct file *, longstruct file_lock **); 
+27    long (*fallocate)(struct file *file, int mode, loff_t offset, 
+28                    loff_t len); 
+29    int (*show_fdinfo)(struct seq_file *m, struct file *f); 
+30};
+

Some operations are not implemented by a driver. For example, a driver that +handles a video card will not need to read from a directory structure. The +corresponding entries in the proc_ops structure should be set to NULL. +

There is a gcc extension that makes assigning to this structure more convenient. +You will see it in modern drivers, and may catch you by surprise. This is what the +new way of assigning to the structure looks like: +

+

+
1struct proc_ops fops = { 
+2              proc_read: device_read, 
+3              proc_write: device_write, 
+4              proc_open: device_open, 
+5              proc_release: device_release 
+6};
+ + + +

However, there is also a C99 way of assigning to elements of a structure, +designated initializers, and this is definitely preferred over using the GNU extension. +You should use this syntax in case someone wants to port your driver. It will help +with compatibility: +

+

+
1struct proc_ops fops = { 
+2              .proc_read = device_read, 
+3              .proc_write = device_write, 
+4              .proc_open = device_open, 
+5              .proc_release = device_release 
+6};
+

The meaning is clear, and you should be aware that any member of the +structure which you do not explicitly assign will be initialized to NULL by +gcc. +

An instance of struct proc_ops containing pointers to functions that are used to +implement read, write, open, … syscalls is commonly named fops. +

+

+

0.6.2 The file structure

+

Each device is represented in the kernel by a file structure, which is defined in +linux/fs.h. Be aware that a file is a kernel level structure and never appears in a +user space program. It is not the same thing as a FILE, which is defined by glibc and +would never appear in a kernel space function. Also, its name is a bit misleading; it +represents an abstract open ‘file’, not a file on a disk, which is represented by a +structure named inode. +

An instance of struct file is commonly named filp. You’ll also see it refered to as +struct file file. Resist the temptation. +

Go ahead and look at the definition of file. Most of the entries you see, like struct +dentry are not used by device drivers, and you can ignore them. This is because +drivers do not fill file directly; they only use structures contained in file which are +created elsewhere. +

+

+

0.6.3 Registering A Device

+

As discussed earlier, char devices are accessed through device files, usually located in +/dev. This is by convention. When writing a driver, it is OK to put the +device file in your current directory. Just make sure you place it in /dev for a +production driver. The major number tells you which driver handles which +device file. The minor number is used only by the driver itself to differentiate +which device it is operating on, just in case the driver handles more than one +device. +

Adding a driver to your system means registering it with the kernel. +This is synonymous with assigning it a major number during the module’s +initialization. You do this by using the register_chrdev function, defined by + + + +linux/fs.h. +

+

+
1int register_chrdev(unsigned int major, const char *name, struct proc_ops *fops);
+

where unsigned int major is the major number you want to request, const char +*name is the name of the device as it will appear in /proc/devices and struct +proc_ops *fops is a pointer to the proc_ops table for your driver. A negative return +value means the registration failed. Note that we didn’t pass the minor number to +register_chrdev. That is because the kernel doesn’t care about the minor number; +only our driver uses it. +

Now the question is, how do you get a major number without hijacking one that’s +already in use? The easiest way would be to look through Documentation +/devices.txt and pick an unused one. That is a bad way of doing things +because you will never be sure if the number you picked will be assigned later. +The answer is that you can ask the kernel to assign you a dynamic major +number. +

If you pass a major number of 0 to register_chrdev, the return value will be the +dynamically allocated major number. The downside is that you ca not make a device +file in advance, since you don’t know what the major number will be. There are a +couple of ways to do this. First, the driver itself can print the newly assigned number +and we can make the device file by hand. Second, the newly registered device will +have an entry in /proc/devices, and we can either make the device file by hand or +write a shell script to read the file in and make the device file. The third method is +we can have our driver make the the device file using the device_create +function after a successful registration and device_destroy during the call to +cleanup_module. +

+

+

0.6.4 Unregistering A Device

+

We can not allow the kernel module to be rmmod’ed whenever root feels like it. If the +device file is opened by a process and then we remove the kernel module, using the +file would cause a call to the memory location where the appropriate function +(read/write) used to be. If we are lucky, no other code was loaded there, and we’ll get +an ugly error message. If we are unlucky, another kernel module was loaded into the +same location, which means a jump into the middle of another function within the +kernel. The results of this would be impossible to predict, but they can not be very +positive. +

Normally, when you don’t want to allow something, you return an error code +(a negative number) from the function which is supposed to do it. With +cleanup_module that’s impossible because it is a void function. However, there is a +counter which keeps track of how many processes are using your module. You can see +what its value is by looking at the 3rd field of /proc/modules. If this number isn’t +zero, rmmod will fail. Note that you don’t have to check the counter from within + + + +cleanup_module because the check will be performed for you by the system call +sys_delete_module, defined in linux/module.c. You should not use this counter +directly, but there are functions defined in linux/module.h which let you increase, +decrease and display this counter: +

+ +

It is important to keep the counter accurate; if you ever do lose track of the +correct usage count, you will never be able to unload the module; it’s now reboot +time, boys and girls. This is bound to happen to you sooner or later during a +module’s development. +

+

+

0.6.5 chardev.c

+

The next code sample creates a char driver named chardev. You can cat its device +file. +

+

+
1cat /proc/devices
+

(or open the file with a program) and the driver will put the number of times the +device file has been read from into the file. We do not support writing to the file +(like echo "hi" > /dev/hello), but catch these attempts and tell the user +that the operation is not supported. Don’t worry if you don’t see what we +do with the data we read into the buffer; we don’t do much with it. We +simply read in the data and print a message acknowledging that we received +it. +

+

+
1/* 
+2 *  chardev.c: Creates a read-only char device that says how many times 
+3 *  you've read from the dev file 
+4 */ 
+5 
+6#include <linux/cdev.h> 
+7#include <linux/delay.h> 
+8#include <linux/device.h> 
+9#include <linux/fs.h> 
+10#include <linux/init.h> 
+11#include <linux/irq.h> 
+12#include <linux/kernel.h> 
+13#include <linux/module.h> 
+14#include <linux/poll.h> 
+15 
+16/* 
+17 *  Prototypes - this would normally go in a .h file 
+18 */ 
+19int init_module(void); 
+20void cleanup_module(void); 
+21static int device_open(struct inode *, struct file *); 
+22static int device_release(struct inode *, struct file *); 
+23static ssize_t device_read(struct file *, char *, size_t, loff_t *); 
+24static ssize_t device_write(struct file *, const char *, size_t, loff_t *); 
+25 
+26#define SUCCESS 0 
+27#define DEVICE_NAME "chardev" /* Dev name as it appears in /proc/devices   */ 
+28#define BUF_LEN 80            /* Max length of the message from the device */ 
+29 
+30/* 
+31 * Global variables are declared as static, so are global within the file. 
+32 */ 
+33 
+34static int Major;           /* Major number assigned to our device driver */ 
+35static int Device_Open = 0; /* Is device open? 
+36                             * Used to prevent multiple access to device */ 
+37static char msg[BUF_LEN];   /* The msg the device will give when asked */ 
+38static char *msg_Ptr; 
+39 
+40static struct class *cls; 
+41 
+42static struct file_operations chardev_fops = {.read = device_read, 
+43                                              .write = device_write, 
+44                                              .open = device_open, 
+45                                              .release = device_release}; 
+46 
+47/* 
+48 * This function is called when the module is loaded 
+49 */ 
+50int init_module(void) 
+51{ 
+52    Major = register_chrdev(0, DEVICE_NAME, &chardev_fops); 
+53 
+54    if (Major < 0) { 
+55        pr_alert("Registering char device failed with %d\n", Major); 
+56        return Major; 
+57    } 
+58 
+59    pr_info("I was assigned major number %d.\n", Major); 
+60 
+61    cls = class_create(THIS_MODULE, DEVICE_NAME); 
+62    device_create(cls, NULL, MKDEV(Major, 0), NULL, DEVICE_NAME); 
+63 
+64    pr_info("Device created on /dev/%s\n", DEVICE_NAME); 
+65 
+66    return SUCCESS; 
+67} 
+68 
+69/* 
+70 * This function is called when the module is unloaded 
+71 */ 
+72void cleanup_module(void) 
+73{ 
+74    device_destroy(cls, MKDEV(Major, 0)); 
+75    class_destroy(cls); 
+76 
+77    /* 
+78     * Unregister the device 
+79     */ 
+80    unregister_chrdev(Major, DEVICE_NAME); 
+81} 
+82 
+83/* 
+84 * Methods 
+85 */ 
+86 
+87/* 
+88 * Called when a process tries to open the device file, like 
+89 * "sudo cat /dev/chardev" 
+90 */ 
+91static int device_open(struct inode *inode, struct file *file) 
+92{ 
+93    static int counter = 0; 
+94 
+95    if (Device_Open) 
+96        return -EBUSY; 
+97 
+98    Device_Open++; 
+99    sprintf(msg, "I already told you %d times Hello world!\n", counter++); 
+100    msg_Ptr = msg; 
+101    try_module_get(THIS_MODULE); 
+102 
+103    return SUCCESS; 
+104} 
+105 
+106/* 
+107 * Called when a process closes the device file. 
+108 */ 
+109static int device_release(struct inode *inode, struct file *file) 
+110{ 
+111    Device_Open--; /* We're now ready for our next caller */ 
+112 
+113    /* 
+114     * Decrement the usage count, or else once you opened the file, you'll 
+115     * never get get rid of the module. 
+116     */ 
+117    module_put(THIS_MODULE); 
+118 
+119    return SUCCESS; 
+120} 
+121 
+122/* 
+123 * Called when a process, which already opened the dev file, attempts to 
+124 * read from it. 
+125 */ 
+126static ssize_t device_read(struct file *filp, /* see include/linux/fs.h   */ 
+127                           char *buffer,      /* buffer to fill with data */ 
+128                           size_t length,     /* length of the buffer     */ 
+129                           loff_t *offset) 
+130{ 
+131    /* 
+132     * Number of bytes actually written to the buffer 
+133     */ 
+134    int bytes_read = 0; 
+135 
+136    /* 
+137     * If we're at the end of the message, 
+138     * return 0 signifying end of file 
+139     */ 
+140    if (*msg_Ptr == 0) 
+141        return 0; 
+142 
+143    /* 
+144     * Actually put the data into the buffer 
+145     */ 
+146    while (length && *msg_Ptr) { 
+147        /* 
+148         * The buffer is in the user data segment, not the kernel 
+149         * segment so "*" assignment won't work.  We have to use 
+150         * put_user which copies data from the kernel data segment to 
+151         * the user data segment. 
+152         */ 
+153        put_user(*(msg_Ptr++), buffer++); 
+154 
+155        length--; 
+156        bytes_read++; 
+157    } 
+158 
+159    /* 
+160     * Most read functions return the number of bytes put into the buffer 
+161     */ 
+162    return bytes_read; 
+163} 
+164 
+165/* 
+166 * Called when a process writes to dev file: echo "hi" > /dev/hello 
+167 */ 
+168static ssize_t device_write(struct file *filp, 
+169                            const char *buff, 
+170                            size_t len, 
+171                            loff_t *off) 
+172{ 
+173    pr_alert("Sorry, this operation isn't supported.\n"); 
+174    return -EINVAL; 
+175} 
+176 
+177MODULE_LICENSE("GPL");
+ + + +

+

+

0.6.6 Writing Modules for Multiple Kernel Versions

+

The system calls, which are the major interface the kernel shows to the processes, +generally stay the same across versions. A new system call may be added, but +usually the old ones will behave exactly like they used to. This is necessary for +backward compatibility – a new kernel version is not supposed to break regular +processes. In most cases, the device files will also remain the same. On the other +hand, the internal interfaces within the kernel can and do change between +versions. +

There are differences between different kernel versions, and if you want to support +multiple kernel versions, you will find yourself having to code conditional compilation +directives. The way to do this to compare the macro LINUX_VERSION_CODE to the +macro KERNEL_VERSION. In version a.b.c of the kernel, the value of this macro would +be 216a + 28b+ c  . +

While previous versions of this guide showed how you can write backward +compatible code with such constructs in great detail, we decided to break with this +tradition for the better. People interested in doing such might now use a LKMPG +with a version matching to their kernel. +

+

+

0.7 The /proc File System

+

In Linux, there is an additional mechanism for the kernel and kernel modules to send +information to processes — the /proc file system. Originally designed to allow easy +access to information about processes (hence the name), it is now used by every bit +of the kernel which has something interesting to report, such as /proc/modules +which provides the list of modules and /proc/meminfo which stats memory usage +statistics. +

The method to use the proc file system is very similar to the one used with device +drivers — a structure is created with all the information needed for the /proc file, +including pointers to any handler functions (in our case there is only one, the +one called when somebody attempts to read from the /proc file). Then, +init_module registers the structure with the kernel and cleanup_module unregisters +it. +

Normal file systems are located on a disk, rather than just in memory (which is +where /proc is), and in that case the inode number is a pointer to a disk +location where the file’s index-node (inode for short) is located. The inode +contains information about the file, for example the file’s permissions, together +with a pointer to the disk location or locations where the file’s data can be +found. +

Because we don’t get called when the file is opened or closed, there’s nowhere for +us to put try_module_get and try_module_put in this module, and if the +file is opened and then the module is removed, there’s no way to avoid the + + + +consequences. +

Here a simple example showing how to use a /proc file. This is the HelloWorld +for the /proc filesystem. There are three parts: create the file proc helloworld +in the function init_module, return a value (and a buffer) when the file +/proc/helloworld is read in the callback function procfile_read, and delete the +file /proc/helloworld in the function cleanup_module. +

The /proc/helloworld is created when the module is loaded with the function +proc_create. The return value is a struct proc_dir_entry , and it will be used +to configure the file /proc/helloworld (for example, the owner of this file). A null +return value means that the creation has failed. +

Each time, everytime the file /proc/helloworld is read, the function +procfile_read is called. Two parameters of this function are very important: the +buffer (the first parameter) and the offset (the third one). The content of the +buffer will be returned to the application which read it (for example the +cat command). The offset is the current position in the file. If the return +value of the function is not null, then this function is called again. So be +careful with this function, if it never returns zero, the read function is called +endlessly. + + + +

+
+$ cat /proc/helloworld
+HelloWorld!
+
+

+

+

+
1/* 
+2 *  procfs1.c 
+3 */ 
+4 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/proc_fs.h> 
+8#include <linux/uaccess.h> 
+9#include <linux/version.h> 
+10 
+11#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+12#define HAVE_PROC_OPS 
+13#endif 
+14 
+15#define procfs_name "helloworld" 
+16 
+17struct proc_dir_entry *Our_Proc_File; 
+18 
+19 
+20ssize_t procfile_read(struct file *filePointer, 
+21                      char *buffer, 
+22                      size_t buffer_length, 
+23                      loff_t *offset) 
+24{ 
+25    char s[13] = "HelloWorld!\n"; 
+26    int len = sizeof(s); 
+27    ssize_t ret = len; 
+28 
+29    if (*offset >= len || copy_to_user(buffer, s, len)) { 
+30                  pr_info("copy_to_user failed\n"); 
+31                  ret = 0; 
+32    } 
+33    else { 
+34        pr_info("procfile read %s\n", filePointer->f_path.dentry->d_name.name); 
+35        *offset += len; 
+36    } 
+37 
+38    return ret; 
+39} 
+40 
+41#ifdef HAVE_PROC_OPS 
+42static const struct proc_ops proc_file_fops = { 
+43    .proc_read = procfile_read, 
+44}; 
+45#else 
+46static const struct file_operations proc_file_fops = { 
+47    .read = procfile_read, 
+48}; 
+49#endif 
+50 
+51int init_module() 
+52{ 
+53    Our_Proc_File = proc_create(procfs_name, 0644, NULL, &proc_file_fops); 
+54    if (NULL == Our_Proc_File) { 
+55        proc_remove(Our_Proc_File); 
+56        pr_alert("Error:Could not initialize /proc/%s\n", procfs_name); 
+57        return -ENOMEM; 
+58    } 
+59 
+60    pr_info("/proc/%s created\n", procfs_name); 
+61    return 0; 
+62} 
+63 
+64void cleanup_module() 
+65{ 
+66    proc_remove(Our_Proc_File); 
+67    pr_info("/proc/%s removed\n", procfs_name); 
+68} 
+69 
+70MODULE_LICENSE("GPL");
+

+

+

0.7.1 Read and Write a /proc File

+

We have seen a very simple example for a /proc file where we only read the +file /proc/helloworld. It is also possible to write in a /proc file. It works +the same way as read, a function is called when the /proc file is written. +But there is a little difference with read, data comes from user, so you have +to import data from user space to kernel space (with copy_from_user or +get_user) +

The reason for copy_from_user or get_user is that Linux memory (on Intel +architecture, it may be different under some other processors) is segmented. This +means that a pointer, by itself, does not reference a unique location in memory, only +a location in a memory segment, and you need to know which memory segment it is +to be able to use it. There is one memory segment for the kernel, and one for each of +the processes. +

The only memory segment accessible to a process is its own, so when +writing regular programs to run as processes, there is no need to worry about +segments. When you write a kernel module, normally you want to access +the kernel memory segment, which is handled automatically by the system. +However, when the content of a memory buffer needs to be passed between +the currently running process and the kernel, the kernel function receives a +pointer to the memory buffer which is in the process segment. The put_user +and get_user macros allow you to access that memory. These functions +handle only one caracter, you can handle several caracters with copy_to_user +and copy_from_user. As the buffer (in read or write function) is in kernel +space, for write function you need to import data because it comes from +user space, but not for the read function because data is already in kernel +space. +

+

+
1/* 
+2 *  procfs2.c -  create a "file" in /proc 
+3 */ 
+4 
+5#include <linux/kernel.h>  /* We're doing kernel work */ 
+6#include <linux/module.h>  /* Specifically, a module */ 
+7#include <linux/proc_fs.h> /* Necessary because we use the proc fs */ 
+8#include <linux/uaccess.h> /* for copy_from_user */ 
+9#include <linux/version.h> 
+10 
+11#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+12#define HAVE_PROC_OPS 
+13#endif 
+14 
+15#define PROCFS_MAX_SIZE 1024 
+16#define PROCFS_NAME "buffer1k" 
+17 
+18/** 
+19 * This structure hold information about the /proc file 
+20 * 
+21 */ 
+22static struct proc_dir_entry *Our_Proc_File; 
+23 
+24/** 
+25 * The buffer used to store character for this module 
+26 * 
+27 */ 
+28static char procfs_buffer[PROCFS_MAX_SIZE]; 
+29 
+30/** 
+31 * The size of the buffer 
+32 * 
+33 */ 
+34static unsigned long procfs_buffer_size = 0; 
+35 
+36/** 
+37 * This function is called then the /proc file is read 
+38 * 
+39 */ 
+40ssize_t procfile_read(struct file *filePointer, 
+41                      char *buffer, 
+42                      size_t buffer_length, 
+43                      loff_t *offset) 
+44{ 
+45    char s[13] = "HelloWorld!\n"; 
+46    int len = sizeof(s); 
+47    ssize_t ret = len; 
+48 
+49    if (*offset >= len || copy_to_user(buffer, s, len)) { 
+50                  pr_info("copy_to_user failed\n"); 
+51                  ret = 0; 
+52    } 
+53    else { 
+54        pr_info("procfile read %s\n", filePointer->f_path.dentry->d_name.name); 
+55        *offset += len; 
+56    } 
+57 
+58    return ret; 
+59} 
+60 
+61 
+62/** 
+63 * This function is called with the /proc file is written 
+64 * 
+65 */ 
+66static ssize_t procfile_write(struct file *file, 
+67                              const char *buff, 
+68                              size_t len, 
+69                              loff_t *off) 
+70{ 
+71    procfs_buffer_size = len; 
+72    if (procfs_buffer_size > PROCFS_MAX_SIZE) 
+73        procfs_buffer_size = PROCFS_MAX_SIZE; 
+74 
+75    if (copy_from_user(procfs_buffer, buff, procfs_buffer_size)) 
+76        return -EFAULT; 
+77 
+78    procfs_buffer[procfs_buffer_size] = '\0'; 
+79    return procfs_buffer_size; 
+80} 
+81 
+82#ifdef HAVE_PROC_OPS 
+83static const struct proc_ops proc_file_fops = { 
+84    .proc_read = procfile_read, 
+85    .proc_write = procfile_write, 
+86}; 
+87#else 
+88static const struct file_operations proc_file_fops = { 
+89    .read = procfile_read, 
+90    .write = procfile_write, 
+91}; 
+92#endif 
+93 
+94/** 
+95 *This function is called when the module is loaded 
+96 * 
+97 */ 
+98int init_module() 
+99{ 
+100    Our_Proc_File = proc_create(PROCFS_NAME, 0644, NULL, &proc_file_fops); 
+101    if (NULL == Our_Proc_File) { 
+102        proc_remove(Our_Proc_File); 
+103        pr_alert("Error:Could not initialize /proc/%s\n", PROCFS_NAME); 
+104        return -ENOMEM; 
+105    } 
+106 
+107    pr_info("/proc/%s created\n", PROCFS_NAME); 
+108    return 0; 
+109} 
+110 
+111/** 
+112 *This function is called when the module is unloaded 
+113 * 
+114 */ 
+115void cleanup_module() 
+116{ 
+117    proc_remove(Our_Proc_File); 
+118    pr_info("/proc/%s removed\n", PROCFS_NAME); 
+119} 
+120 
+121MODULE_LICENSE("GPL");
+ + + +

+

+

0.7.2 Manage /proc file with standard filesystem

+

We have seen how to read and write a /proc file with the /proc interface. But it is +also possible to manage /proc file with inodes. The main concern is to use advanced +functions, like permissions. +

In Linux, there is a standard mechanism for file system registration. Since every +file system has to have its own functions to handle inode and file operations, there is +a special structure to hold pointers to all those functions, struct inode_operations, +which includes a pointer to struct proc_ops. +

The difference between file and inode operations is that file operations deal with +the file itself whereas inode operations deal with ways of referencing the file, such as +creating links to it. +

In /proc, whenever we register a new file, we’re allowed to specify which struct +inode_operations will be used to access to it. This is the mechanism we use, a struct +inode_operations which includes a pointer to a struct proc_ops which includes +pointers to our procfs_read and procfs_write functions. +

Another interesting point here is the module_permission function. This function +is called whenever a process tries to do something with the /proc file, and it +can decide whether to allow access or not. Right now it is only based on +the operation and the uid of the current user (as available in current, a +pointer to a structure which includes information on the currently running +process), but it could be based on anything we like, such as what other +processes are doing with the same file, the time of day, or the last input we +received. +

It is important to note that the standard roles of read and write are reversed in +the kernel. Read functions are used for output, whereas write functions are used for +input. The reason for that is that read and write refer to the user’s point of view — if +a process reads something from the kernel, then the kernel needs to output it, and +if a process writes something to the kernel, then the kernel receives it as +input. +

+

+
1/* 
+2 *  procfs3.c 
+3 */ 
+4 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/proc_fs.h> 
+8#include <linux/sched.h> 
+9#include <linux/uaccess.h> 
+10#include <linux/version.h> 
+11 
+12#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+13#define HAVE_PROC_OPS 
+14#endif 
+15 
+16#define PROCFS_MAX_SIZE 2048 
+17#define PROCFS_ENTRY_FILENAME "buffer2k" 
+18 
+19struct proc_dir_entry *Our_Proc_File; 
+20static char procfs_buffer[PROCFS_MAX_SIZE]; 
+21static unsigned long procfs_buffer_size = 0; 
+22 
+23static ssize_t procfs_read(struct file *filp, 
+24                           char *buffer, 
+25                           size_t length, 
+26                           loff_t *offset) 
+27{ 
+28    static int finished = 0; 
+29    if (finished) { 
+30        pr_debug("procfs_read: END\n"); 
+31        finished = 0; 
+32        return 0; 
+33    } 
+34    finished = 1; 
+35    if (copy_to_user(buffer, procfs_buffer, procfs_buffer_size)) 
+36        return -EFAULT; 
+37    pr_debug("procfs_read: read %lu bytes\n", procfs_buffer_size); 
+38    return procfs_buffer_size; 
+39} 
+40static ssize_t procfs_write(struct file *file, 
+41                            const char *buffer, 
+42                            size_t len, 
+43                            loff_t *off) 
+44{ 
+45    if (len > PROCFS_MAX_SIZE) 
+46        procfs_buffer_size = PROCFS_MAX_SIZE; 
+47    else 
+48        procfs_buffer_size = len; 
+49    if (copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) 
+50        return -EFAULT; 
+51    pr_debug("procfs_write: write %lu bytes\n", procfs_buffer_size); 
+52    return procfs_buffer_size; 
+53} 
+54int procfs_open(struct inode *inode, struct file *file) 
+55{ 
+56    try_module_get(THIS_MODULE); 
+57    return 0; 
+58} 
+59int procfs_close(struct inode *inode, struct file *file) 
+60{ 
+61    module_put(THIS_MODULE); 
+62    return 0; 
+63} 
+64 
+65#ifdef HAVE_PROC_OPS 
+66static struct proc_ops File_Ops_4_Our_Proc_File = { 
+67    .proc_read = procfs_read, 
+68    .proc_write = procfs_write, 
+69    .proc_open = procfs_open, 
+70    .proc_release = procfs_close, 
+71}; 
+72#else 
+73static const struct file_operations File_Ops_4_Our_Proc_File = { 
+74    .read = procfs_read, 
+75    .write = procfs_write, 
+76    .open = procfs_open, 
+77    .release = procfs_close, 
+78}; 
+79#endif 
+80 
+81int init_module() 
+82{ 
+83    Our_Proc_File = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL, 
+84                                &File_Ops_4_Our_Proc_File); 
+85    if (Our_Proc_File == NULL) { 
+86        remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); 
+87        pr_debug("Error: Could not initialize /proc/%s\n", 
+88                 PROCFS_ENTRY_FILENAME); 
+89        return -ENOMEM; 
+90    } 
+91    proc_set_size(Our_Proc_File, 80); 
+92    proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); 
+93 
+94    pr_debug("/proc/%s created\n", PROCFS_ENTRY_FILENAME); 
+95    return 0; 
+96} 
+97void cleanup_module() 
+98{ 
+99    remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); 
+100    pr_debug("/proc/%s removed\n", PROCFS_ENTRY_FILENAME); 
+101} 
+102 
+103MODULE_LICENSE("GPL");
+

Still hungry for procfs examples? Well, first of all keep in mind, there are rumors +around, claiming that procfs is on its way out, consider using sysfs instead. Consider +using this mechanism, in case you want to document something kernel related +yourself. +

+

+

0.7.3 Manage /proc file with seq_file

+

As we have seen, writing a /proc file may be quite “complex”. So to help people +writting /proc file, there is an API named seq_file that helps formating a /proc file + + + +for output. It is based on sequence, which is composed of 3 functions: start(), next(), +and stop(). The seq_file API starts a sequence when a user read the /proc +file. +

A sequence begins with the call of the function start(). If the return is a non +NULL value, the function next() is called. This function is an iterator, the goal is to +go thought all the data. Each time next() is called, the function show() is also called. +It writes data values in the buffer read by the user. The function next() is called until +it returns NULL. The sequence ends when next() returns NULL, then the function +stop() is called. +

BE CAREFUL: when a sequence is finished, another one starts. That means that +at the end of function stop(), the function start() is called again. This loop finishes +when the function start() returns NULL. You can see a scheme of this in the +Figure 1. +

+
+ + + + + + + + +

srYrsNNYtaeenetoooertusetupstrxr((ntn))( tis)istrr teeaNreNatUaUtmLtLmeLmLen?e?ntntt  +

+
Figure 1:How seq_file works
+ + + +
+

The seq_file provides basic functions for proc_ops, such as seq_read, +seq_lseek, and some others. But nothing to write in the /proc file. Of course, you can +still use the same way as in the previous example. +

+
1/* 
+2 *  procfs4.c -  create a "file" in /proc 
+3 *  This program uses the seq_file library to manage the /proc file. 
+4 * 
+5 */ 
+6 
+7#include <linux/kernel.h>   /* We're doing kernel work */ 
+8#include <linux/module.h>   /* Specifically, a module */ 
+9#include <linux/proc_fs.h>  /* Necessary because we use proc fs */ 
+10#include <linux/seq_file.h> /* for seq_file */ 
+11#include <linux/version.h> 
+12 
+13#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+14#define HAVE_PROC_OPS 
+15#endif 
+16 
+17#define PROC_NAME "iter" 
+18 
+19MODULE_LICENSE("GPL"); 
+20 
+21/** 
+22 * This function is called at the beginning of a sequence. 
+23 * ie, when: 
+24 *      - the /proc file is read (first time) 
+25 *      - after the function stop (end of sequence) 
+26 * 
+27 */ 
+28static void *my_seq_start(struct seq_file *s, loff_t *pos) 
+29{ 
+30    static unsigned long counter = 0; 
+31 
+32    /* beginning a new sequence ? */ 
+33    if (*pos == 0) { 
+34        /* yes => return a non null value to begin the sequence */ 
+35        return &counter; 
+36    } else { 
+37        /* no => it's the end of the sequence, return end to stop reading */ 
+38        *pos = 0; 
+39        return NULL; 
+40    } 
+41} 
+42 
+43/** 
+44 * This function is called after the beginning of a sequence. 
+45 * It's called untill the return is NULL (this ends the sequence). 
+46 * 
+47 */ 
+48static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos) 
+49{ 
+50    unsigned long *tmp_v = (unsigned long *) v; 
+51    (*tmp_v)++; 
+52    (*pos)++; 
+53    return NULL; 
+54} 
+55 
+56/** 
+57 * This function is called at the end of a sequence 
+58 * 
+59 */ 
+60static void my_seq_stop(struct seq_file *s, void *v) 
+61{ 
+62    /* nothing to do, we use a static value in start() */ 
+63} 
+64 
+65/** 
+66 * This function is called for each "step" of a sequence 
+67 * 
+68 */ 
+69static int my_seq_show(struct seq_file *s, void *v) 
+70{ 
+71    loff_t *spos = (loff_t *) v; 
+72 
+73    seq_printf(s, "%Ld\n", *spos); 
+74    return 0; 
+75} 
+76 
+77/** 
+78 * This structure gather "function" to manage the sequence 
+79 * 
+80 */ 
+81static struct seq_operations my_seq_ops = {.start = my_seq_start, 
+82                                           .next = my_seq_next, 
+83                                           .stop = my_seq_stop, 
+84                                           .show = my_seq_show}; 
+85 
+86/** 
+87 * This function is called when the /proc file is open. 
+88 * 
+89 */ 
+90static int my_open(struct inode *inode, struct file *file) 
+91{ 
+92    return seq_open(file, &my_seq_ops); 
+93}; 
+94 
+95/** 
+96 * This structure gather "function" that manage the /proc file 
+97 * 
+98 */ 
+99#ifdef HAVE_PROC_OPS 
+100static const struct proc_ops my_file_ops = { 
+101    .proc_open = my_open, 
+102    .proc_read = seq_read, 
+103    .proc_lseek = seq_lseek, 
+104    .proc_release = seq_release, 
+105}; 
+106#else 
+107static const struct file_operations my_file_ops = { 
+108    .open = my_open, 
+109    .read = seq_read, 
+110    .llseek = seq_lseek, 
+111    .release = seq_release, 
+112}; 
+113#endif 
+114 
+115/** 
+116 * This function is called when the module is loaded 
+117 * 
+118 */ 
+119int init_module(void) 
+120{ 
+121    struct proc_dir_entry *entry; 
+122 
+123    entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops); 
+124    if (entry == NULL) { 
+125        remove_proc_entry(PROC_NAME, NULL); 
+126        pr_debug("Error: Could not initialize /proc/%s\n", PROC_NAME); 
+127        return -ENOMEM; 
+128    } 
+129 
+130    return 0; 
+131} 
+132 
+133/** 
+134 * This function is called when the module is unloaded. 
+135 * 
+136 */ 
+137void cleanup_module(void) 
+138{ 
+139    remove_proc_entry(PROC_NAME, NULL); 
+140    pr_debug("/proc/%s removed\n", PROC_NAME); 
+141}
+

If you want more information, you can read this web page: +

+ +

You can also read the code of fs/seq_file.c in the linux kernel. +

+

0.8 sysfs: Interacting with your module

+

sysfs allows you to interact with the running kernel from userspace by reading or +setting variables inside of modules. This can be useful for debugging purposes, or just +as an interface for applications or scripts. You can find sysfs directories and files +under the sys directory on your system. +

+

+
1ls -l /sys
+

An example of a hello world module which includes the creation of a variable +accessible via sysfs is given below. +

+

+
1/* 
+2 *  hello-sysfs.c sysfs example 
+3 */ 
+4#include <linux/fs.h> 
+5#include <linux/init.h> 
+6#include <linux/kobject.h> 
+7#include <linux/module.h> 
+8#include <linux/string.h> 
+9#include <linux/sysfs.h> 
+10 
+11MODULE_LICENSE("GPL"); 
+12 
+13static struct kobject *mymodule; 
+14 
+15/* the variable you want to be able to change */ 
+16static int myvariable = 0; 
+17 
+18static ssize_t myvariable_show(struct kobject *kobj, 
+19                               struct kobj_attribute *attr, 
+20                               char *buf) 
+21{ 
+22    return sprintf(buf, "%d\n", myvariable); 
+23} 
+24 
+25static ssize_t myvariable_store(struct kobject *kobj, 
+26                                struct kobj_attribute *attr, 
+27                                char *buf, 
+28                                size_t count) 
+29{ 
+30    sscanf(buf, "%du", &myvariable); 
+31    return count; 
+32} 
+33 
+34 
+35static struct kobj_attribute myvariable_attribute = 
+36    __ATTR(myvariable, 0660, myvariable_show, (void *) myvariable_store); 
+37 
+38static int __init mymodule_init(void) 
+39{ 
+40    int error = 0; 
+41 
+42    pr_info("mymodule: initialised\n"); 
+43 
+44    mymodule = kobject_create_and_add("mymodule", kernel_kobj); 
+45    if (!mymodule) 
+46        return -ENOMEM; 
+47 
+48    error = sysfs_create_file(mymodule, &myvariable_attribute.attr); 
+49    if (error) { 
+50        pr_info( 
+51            "failed to create the myvariable file " 
+52            "in /sys/kernel/mymodule\n"); 
+53    } 
+54 
+55    return error; 
+56} 
+57 
+58static void __exit mymodule_exit(void) 
+59{ 
+60    pr_info("mymodule: Exit success\n"); 
+61    kobject_put(mymodule); 
+62} 
+63 
+64module_init(mymodule_init); 
+65module_exit(mymodule_exit);
+

Make and install the module: +

+

+
1make 
+2sudo insmod hello-sysfs.ko
+

Check that it exists: +

+ + + +

+
1sudo lsmod | grep hello_sysfs
+

What is the current value of myvariable ? +

+

+
1cat /sys/kernel/mymodule/myvariable
+

Set the value of myvariable and check that it changed. +

+

+
1echo "32" > /sys/kernel/mymodule/myvariable 
+2cat /sys/kernel/mymodule/myvariable
+

Finally, remove the test module: +

+

+
1sudo rmmod hello_sysfs
+

+

+

0.9 Talking To Device Files

+

Device files are supposed to represent physical devices. Most physical devices are +used for output as well as input, so there has to be some mechanism for +device drivers in the kernel to get the output to send to the device from +processes. This is done by opening the device file for output and writing to it, +just like writing to a file. In the following example, this is implemented by +device_write. +

This is not always enough. Imagine you had a serial port connected to a modem +(even if you have an internal modem, it is still implemented from the CPU’s +perspective as a serial port connected to a modem, so you don’t have to tax +your imagination too hard). The natural thing to do would be to use the +device file to write things to the modem (either modem commands or data to +be sent through the phone line) and read things from the modem (either +responses for commands or the data received through the phone line). However, +this leaves open the question of what to do when you need to talk to the +serial port itself, for example to send the rate at which data is sent and +received. +

The answer in Unix is to use a special function called ioctl (short for +Input Output ConTroL). Every device can have its own ioctl commands, +which can be read ioctl’s (to send information from a process to the kernel), +write ioctl’s (to return information to a process), both or neither. Notice + + + +here the roles of read and write are reversed again, so in ioctl’s read is to +send information to the kernel and write is to receive information from the +kernel. +

The ioctl function is called with three parameters: the file descriptor of the +appropriate device file, the ioctl number, and a parameter, which is of type +long so you can use a cast to use it to pass anything. You will not be able +to pass a structure this way, but you will be able to pass a pointer to the +structure. +

The ioctl number encodes the major device number, the type of the ioctl, the +command, and the type of the parameter. This ioctl number is usually created by a +macro call (_IO, _IOR, _IOW or _IOWR — depending on the type) in a header +file. This header file should then be included both by the programs which will use +ioctl (so they can generate the appropriate ioctl’s) and by the kernel module (so it +can understand it). In the example below, the header file is chardev.h and the +program which uses it is ioctl.c. +

If you want to use ioctls in your own kernel modules, it is best to receive an +official ioctl assignment, so if you accidentally get somebody else’s ioctls, or if they +get yours, you’ll know something is wrong. For more information, consult the kernel +source tree at Documentation/ioctl-number.txt. +

+

+
1/* 
+2 *  chardev2.c - Create an input/output character device 
+3 */ 
+4 
+5#include <linux/cdev.h> 
+6#include <linux/delay.h> 
+7#include <linux/device.h> 
+8#include <linux/fs.h> 
+9#include <linux/init.h> 
+10#include <linux/irq.h> 
+11#include <linux/kernel.h> /* We're doing kernel work */ 
+12#include <linux/module.h> /* Specifically, a module */ 
+13#include <linux/poll.h> 
+14 
+15#include "chardev.h" 
+16#define SUCCESS 0 
+17#define DEVICE_NAME "char_dev" 
+18#define BUF_LEN 80 
+19 
+20/* 
+21 * Is the device open right now? Used to prevent 
+22 * concurent access into the same device 
+23 */ 
+24static int Device_Open = 0; 
+25 
+26/* 
+27 * The message the device will give when asked 
+28 */ 
+29static char Message[BUF_LEN]; 
+30 
+31/* 
+32 * How far did the process reading the message get? 
+33 * Useful if the message is larger than the size of the 
+34 * buffer we get to fill in device_read. 
+35 */ 
+36static char *Message_Ptr; 
+37 
+38static int Major; /* Major number assigned to our device driver */ 
+39static struct class *cls; 
+40 
+41/* 
+42 * This is called whenever a process attempts to open the device file 
+43 */ 
+44static int device_open(struct inode *inode, struct file *file) 
+45{ 
+46    pr_info("device_open(%p)\n", file); 
+47 
+48    /* 
+49     * We don't want to talk to two processes at the same time 
+50     */ 
+51    if (Device_Open) 
+52        return -EBUSY; 
+53 
+54    Device_Open++; 
+55    /* 
+56     * Initialize the message 
+57     */ 
+58    Message_Ptr = Message; 
+59    try_module_get(THIS_MODULE); 
+60    return SUCCESS; 
+61} 
+62 
+63static int device_release(struct inode *inode, struct file *file) 
+64{ 
+65    pr_info("device_release(%p,%p)\n", inode, file); 
+66 
+67    /* 
+68     * We're now ready for our next caller 
+69     */ 
+70    Device_Open--; 
+71 
+72    module_put(THIS_MODULE); 
+73    return SUCCESS; 
+74} 
+75 
+76/* 
+77 * This function is called whenever a process which has already opened the 
+78 * device file attempts to read from it. 
+79 */ 
+80static ssize_t device_read(struct file *file,   /* see include/linux/fs.h   */ 
+81                           char __user *buffer, /* buffer to be 
+82                                                 * filled with data */ 
+83                           size_t length,       /* length of the buffer     */ 
+84                           loff_t *offset) 
+85{ 
+86    /* 
+87     * Number of bytes actually written to the buffer 
+88     */ 
+89    int bytes_read = 0; 
+90 
+91    pr_info("device_read(%p,%p,%ld)\n", file, buffer, length); 
+92 
+93    /* 
+94     * If we're at the end of the message, return 0 
+95     * (which signifies end of file) 
+96     */ 
+97    if (*Message_Ptr == 0) 
+98        return 0; 
+99 
+100    /* 
+101     * Actually put the data into the buffer 
+102     */ 
+103    while (length && *Message_Ptr) { 
+104        /* 
+105         * Because the buffer is in the user data segment, 
+106         * not the kernel data segment, assignment wouldn't 
+107         * work. Instead, we have to use put_user which 
+108         * copies data from the kernel data segment to the 
+109         * user data segment. 
+110         */ 
+111        put_user(*(Message_Ptr++), buffer++); 
+112        length--; 
+113        bytes_read++; 
+114    } 
+115 
+116    pr_info("Read %d bytes, %ld left\n", bytes_read, length); 
+117 
+118    /* 
+119     * Read functions are supposed to return the number 
+120     * of bytes actually inserted into the buffer 
+121     */ 
+122    return bytes_read; 
+123} 
+124 
+125/* 
+126 * This function is called when somebody tries to 
+127 * write into our device file. 
+128 */ 
+129static ssize_t device_write(struct file *file, 
+130                            const char __user *buffer, 
+131                            size_t length, 
+132                            loff_t *offset) 
+133{ 
+134    int i; 
+135 
+136    pr_info("device_write(%p,%s,%ld)", file, buffer, length); 
+137 
+138    for (i = 0; i < length && i < BUF_LEN; i++) 
+139        get_user(Message[i], buffer + i); 
+140 
+141    Message_Ptr = Message; 
+142 
+143    /* 
+144     * Again, return the number of input characters used 
+145     */ 
+146    return i; 
+147} 
+148 
+149/* 
+150 * This function is called whenever a process tries to do an ioctl on our 
+151 * device file. We get two extra parameters (additional to the inode and file 
+152 * structures, which all device functions get): the number of the ioctl called 
+153 * and the parameter given to the ioctl function. 
+154 * 
+155 * If the ioctl is write or read/write (meaning output is returned to the 
+156 * calling process), the ioctl call returns the output of this function. 
+157 * 
+158 */ 
+159long device_ioctl(struct file *file,      /* ditto */ 
+160                  unsigned int ioctl_num, /* number and param for ioctl */ 
+161                  unsigned long ioctl_param) 
+162{ 
+163    int i; 
+164    char *temp; 
+165    char ch; 
+166 
+167    /* 
+168     * Switch according to the ioctl called 
+169     */ 
+170    switch (ioctl_num) { 
+171    case IOCTL_SET_MSG: 
+172        /* 
+173         * Receive a pointer to a message (in user space) and set that 
+174         * to be the device's message.  Get the parameter given to 
+175         * ioctl by the process. 
+176         */ 
+177        temp = (char *) ioctl_param; 
+178 
+179        /* 
+180         * Find the length of the message 
+181         */ 
+182        get_user(ch, temp); 
+183        for (i = 0; ch && i < BUF_LEN; i++, temp++) 
+184            get_user(ch, temp); 
+185 
+186        device_write(file, (char *) ioctl_param, i, 0); 
+187        break; 
+188 
+189    case IOCTL_GET_MSG: 
+190        /* 
+191         * Give the current message to the calling process - 
+192         * the parameter we got is a pointer, fill it. 
+193         */ 
+194        i = device_read(file, (char *) ioctl_param, 99, 0); 
+195 
+196        /* 
+197         * Put a zero at the end of the buffer, so it will be 
+198         * properly terminated 
+199         */ 
+200        put_user('\0', (char *) ioctl_param + i); 
+201        break; 
+202 
+203    case IOCTL_GET_NTH_BYTE: 
+204        /* 
+205         * This ioctl is both input (ioctl_param) and 
+206         * output (the return value of this function) 
+207         */ 
+208        return Message[ioctl_param]; 
+209        break; 
+210    } 
+211 
+212    return SUCCESS; 
+213} 
+214 
+215/* Module Declarations */ 
+216 
+217/* 
+218 * This structure will hold the functions to be called 
+219 * when a process does something to the device we 
+220 * created. Since a pointer to this structure is kept in 
+221 * the devices table, it can't be local to 
+222 * init_module. NULL is for unimplemented functions. 
+223 */ 
+224struct file_operations Fops = { 
+225    .read = device_read, 
+226    .write = device_write, 
+227    .unlocked_ioctl = device_ioctl, 
+228    .open = device_open, 
+229    .release = device_release, /* a.k.a. close */ 
+230}; 
+231 
+232/* 
+233 * Initialize the module - Register the character device 
+234 */ 
+235int init_module() 
+236{ 
+237    int ret_val; 
+238    /* 
+239     * Register the character device (atleast try) 
+240     */ 
+241    ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops); 
+242 
+243    /* 
+244     * Negative values signify an error 
+245     */ 
+246    if (ret_val < 0) { 
+247        pr_alert("%s failed with %d\n", 
+248                 "Sorry, registering the character device ", ret_val); 
+249        return ret_val; 
+250    } 
+251 
+252    Major = ret_val; 
+253 
+254    cls = class_create(THIS_MODULE, DEVICE_FILE_NAME); 
+255    device_create(cls, NULL, MKDEV(Major, MAJOR_NUM), NULL, DEVICE_FILE_NAME); 
+256 
+257    pr_info("Device created on /dev/%s\n", DEVICE_FILE_NAME); 
+258 
+259    return 0; 
+260} 
+261 
+262/* 
+263 * Cleanup - unregister the appropriate file from /proc 
+264 */ 
+265void cleanup_module() 
+266{ 
+267    device_destroy(cls, MKDEV(Major, 0)); 
+268    class_destroy(cls); 
+269 
+270    /* 
+271     * Unregister the device 
+272     */ 
+273    unregister_chrdev(Major, DEVICE_NAME); 
+274} 
+275 
+276MODULE_LICENSE("GPL");
+ +

+

+
1/* 
+2 *  chardev.h - the header file with the ioctl definitions. 
+3 * 
+4 *  The declarations here have to be in a header file, because 
+5 *  they need to be known both to the kernel module 
+6 *  (in chardev.c) and the process calling ioctl (ioctl.c) 
+7 */ 
+8 
+9#ifndef CHARDEV_H 
+10#define CHARDEV_H 
+11 
+12#include <linux/ioctl.h> 
+13 
+14/* 
+15 * The major device number. We can't rely on dynamic 
+16 * registration any more, because ioctls need to know 
+17 * it. 
+18 */ 
+19#define MAJOR_NUM 100 
+20 
+21/* 
+22 * Set the message of the device driver 
+23 */ 
+24#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *) 
+25/* 
+26 * _IOW means that we're creating an ioctl command 
+27 * number for passing information from a user process 
+28 * to the kernel module. 
+29 * 
+30 * The first arguments, MAJOR_NUM, is the major device 
+31 * number we're using. 
+32 * 
+33 * The second argument is the number of the command 
+34 * (there could be several with different meanings). 
+35 * 
+36 * The third argument is the type we want to get from 
+37 * the process to the kernel. 
+38 */ 
+39 
+40/* 
+41 * Get the message of the device driver 
+42 */ 
+43#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *) 
+44/* 
+45 * This IOCTL is used for output, to get the message 
+46 * of the device driver. However, we still need the 
+47 * buffer to place the message in to be input, 
+48 * as it is allocated by the process. 
+49 */ 
+50 
+51/* 
+52 * Get the n'th byte of the message 
+53 */ 
+54#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int) 
+55/* 
+56 * The IOCTL is used for both input and output. It 
+57 * receives from the user a number, n, and returns 
+58 * Message[n]. 
+59 */ 
+60 
+61/* 
+62 * The name of the device file 
+63 */ 
+64#define DEVICE_FILE_NAME "char_dev" 
+65 
+66#endif
+ +

+

+
1/* 
+2 *  ioctl.c 
+3 */ 
+4#include <linux/cdev.h> 
+5#include <linux/fs.h> 
+6#include <linux/init.h> 
+7#include <linux/ioctl.h> 
+8#include <linux/module.h> 
+9#include <linux/slab.h> 
+10#include <linux/uaccess.h> 
+11 
+12struct ioctl_arg { 
+13    unsigned int reg; 
+14    unsigned int val; 
+15}; 
+16 
+17/* Documentation/ioctl/ioctl-number.txt */ 
+18#define IOC_MAGIC '\x66' 
+19 
+20#define IOCTL_VALSET _IOW(IOC_MAGIC, 0, struct ioctl_arg) 
+21#define IOCTL_VALGET _IOR(IOC_MAGIC, 1, struct ioctl_arg) 
+22#define IOCTL_VALGET_NUM _IOR(IOC_MAGIC, 2, int) 
+23#define IOCTL_VALSET_NUM _IOW(IOC_MAGIC, 3, int) 
+24 
+25#define IOCTL_VAL_MAXNR 3 
+26#define DRIVER_NAME "ioctltest" 
+27 
+28static unsigned int test_ioctl_major = 0; 
+29static unsigned int num_of_dev = 1; 
+30static struct cdev test_ioctl_cdev; 
+31static int ioctl_num = 0; 
+32 
+33struct test_ioctl_data { 
+34    unsigned char val; 
+35    rwlock_t lock; 
+36}; 
+37 
+38static long test_ioctl_ioctl(struct file *filp, 
+39                             unsigned int cmd, 
+40                             unsigned long arg) 
+41{ 
+42    struct test_ioctl_data *ioctl_data = filp->private_data; 
+43    int retval = 0; 
+44    unsigned char val; 
+45    struct ioctl_arg data; 
+46    memset(&data, 0, sizeof(data)); 
+47 
+48    switch (cmd) { 
+49    case IOCTL_VALSET: 
+50 
+51        /* 
+52        if (!capable(CAP_SYS_ADMIN)) { 
+53         retval = -EPERM; 
+54         goto done; 
+55        } 
+56        if (!access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd))) { 
+57         retval = -EFAULT; 
+58         goto done; 
+59        } 
+60        */ 
+61        if (copy_from_user(&data, (int __user *) arg, sizeof(data))) { 
+62            retval = -EFAULT; 
+63            goto done; 
+64        } 
+65 
+66        pr_alert("IOCTL set val:%x .\n", data.val); 
+67        write_lock(&ioctl_data->lock); 
+68        ioctl_data->val = data.val; 
+69        write_unlock(&ioctl_data->lock); 
+70        break; 
+71 
+72    case IOCTL_VALGET: 
+73        /* 
+74        if (!access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd))) { 
+75                                     retval = -EFAULT; 
+76                                     goto done; 
+77                             } 
+78        */ 
+79        read_lock(&ioctl_data->lock); 
+80        val = ioctl_data->val; 
+81        read_unlock(&ioctl_data->lock); 
+82        data.val = val; 
+83 
+84        if (copy_to_user((int __user *) arg, &data, sizeof(data))) { 
+85            retval = -EFAULT; 
+86            goto done; 
+87        } 
+88 
+89        break; 
+90 
+91    case IOCTL_VALGET_NUM: 
+92        retval = __put_user(ioctl_num, (int __user *) arg); 
+93        break; 
+94 
+95    case IOCTL_VALSET_NUM: 
+96        /* 
+97        if (!capable(CAP_SYS_ADMIN)) 
+98         return -EPERM; 
+99        */ 
+100        ioctl_num = arg; 
+101        break; 
+102 
+103    default: 
+104        retval = -ENOTTY; 
+105    } 
+106 
+107done: 
+108    return retval; 
+109} 
+110 
+111ssize_t test_ioctl_read(struct file *filp, 
+112                        char __user *buf, 
+113                        size_t count, 
+114                        loff_t *f_pos) 
+115{ 
+116    struct test_ioctl_data *ioctl_data = filp->private_data; 
+117    unsigned char val; 
+118    int retval; 
+119    int i = 0; 
+120    read_lock(&ioctl_data->lock); 
+121    val = ioctl_data->val; 
+122    read_unlock(&ioctl_data->lock); 
+123 
+124    for (; i < count; i++) { 
+125        if (copy_to_user(&buf[i], &val, 1)) { 
+126            retval = -EFAULT; 
+127            goto out; 
+128        } 
+129    } 
+130 
+131    retval = count; 
+132out: 
+133    return retval; 
+134} 
+135 
+136static int test_ioctl_close(struct inode *inode, struct file *filp) 
+137{ 
+138    pr_alert("%s call.\n", __func__); 
+139 
+140    if (filp->private_data) { 
+141        kfree(filp->private_data); 
+142        filp->private_data = NULL; 
+143    } 
+144 
+145    return 0; 
+146} 
+147 
+148static int test_ioctl_open(struct inode *inode, struct file *filp) 
+149{ 
+150    struct test_ioctl_data *ioctl_data; 
+151    pr_alert("%s call.\n", __func__); 
+152    ioctl_data = kmalloc(sizeof(struct test_ioctl_data), GFP_KERNEL); 
+153 
+154    if (ioctl_data == NULL) { 
+155        return -ENOMEM; 
+156    } 
+157 
+158    rwlock_init(&ioctl_data->lock); 
+159    ioctl_data->val = 0xFF; 
+160    filp->private_data = ioctl_data; 
+161    return 0; 
+162} 
+163 
+164struct file_operations fops = { 
+165    .owner = THIS_MODULE, 
+166    .open = test_ioctl_open, 
+167    .release = test_ioctl_close, 
+168    .read = test_ioctl_read, 
+169    .unlocked_ioctl = test_ioctl_ioctl, 
+170}; 
+171 
+172static int ioctl_init(void) 
+173{ 
+174    dev_t dev = MKDEV(test_ioctl_major, 0); 
+175    int alloc_ret = 0; 
+176    int cdev_ret = 0; 
+177    alloc_ret = alloc_chrdev_region(&dev, 0, num_of_dev, DRIVER_NAME); 
+178 
+179    if (alloc_ret) { 
+180        goto error; 
+181    } 
+182 
+183    test_ioctl_major = MAJOR(dev); 
+184    cdev_init(&test_ioctl_cdev, &fops); 
+185    cdev_ret = cdev_add(&test_ioctl_cdev, dev, num_of_dev); 
+186 
+187    if (cdev_ret) { 
+188        goto error; 
+189    } 
+190 
+191    pr_alert("%s driver(major: %d) installed.\n", DRIVER_NAME, 
+192             test_ioctl_major); 
+193    return 0; 
+194error: 
+195 
+196    if (cdev_ret == 0) { 
+197        cdev_del(&test_ioctl_cdev); 
+198    } 
+199 
+200    if (alloc_ret == 0) { 
+201        unregister_chrdev_region(dev, num_of_dev); 
+202    } 
+203 
+204    return -1; 
+205} 
+206 
+207static void ioctl_exit(void) 
+208{ 
+209    dev_t dev = MKDEV(test_ioctl_major, 0); 
+210    cdev_del(&test_ioctl_cdev); 
+211    unregister_chrdev_region(dev, num_of_dev); 
+212    pr_alert("%s driver removed.\n", DRIVER_NAME); 
+213} 
+214 
+215module_init(ioctl_init); 
+216module_exit(ioctl_exit); 
+217 
+218MODULE_LICENSE("GPL"); 
+219MODULE_DESCRIPTION("This is test_ioctl module");
+

+

+

0.10 System Calls

+

So far, the only thing we’ve done was to use well defined kernel mechanisms to +register /proc files and device handlers. This is fine if you want to do something the +kernel programmers thought you’d want, such as write a device driver. But what if +you want to do something unusual, to change the behavior of the system in some +way? Then, you are mostly on your own. +

If you are not being sensible and using a virtual machine then this is where kernel +programming can become hazardous. While writing the example below, +I killed the open() system call. This meant I could not open any files, I +could not run any programs, and I could not shutdown the system. I had +to restart the virtual machine. No important files got anihilated, but if I + + + +was doing this on some live mission critical system then that could have +been a possible outcome. To ensure you do not lose any files, even within a +test environment, please run sync right before you do the insmod and the +rmmod. +

Forget about /proc files, forget about device files. They are just minor details. +Minutiae in the vast expanse of the universe. The real process to kernel +communication mechanism, the one used by all processes, is system calls. When a +process requests a service from the kernel (such as opening a file, forking to a new +process, or requesting more memory), this is the mechanism used. If you want to +change the behaviour of the kernel in interesting ways, this is the place to do +it. By the way, if you want to see which system calls a program uses, run +strace <arguments>. +

In general, a process is not supposed to be able to access the kernel. It can not +access kernel memory and it can’t call kernel functions. The hardware of the CPU +enforces this (that is the reason why it is called “protected mode” or “page +protection”). +

System calls are an exception to this general rule. What happens is that the +process fills the registers with the appropriate values and then calls a special +instruction which jumps to a previously defined location in the kernel (of course, that +location is readable by user processes, it is not writable by them). Under Intel CPUs, +this is done by means of interrupt 0x80. The hardware knows that once you jump to +this location, you are no longer running in restricted user mode, but as the +operating system kernel — and therefore you’re allowed to do whatever you +want. +

The location in the kernel a process can jump to is called system_call. The +procedure at that location checks the system call number, which tells the kernel what +service the process requested. Then, it looks at the table of system calls +(sys_call_table) to see the address of the kernel function to call. Then it calls the +function, and after it returns, does a few system checks and then return back to the +process (or to a different process, if the process time ran out). If you want to read +this code, it is at the source file arch/$(architecture)/kernel/entry.S, after the +line ENTRY(system_call). +

So, if we want to change the way a certain system call works, what we need to do +is to write our own function to implement it (usually by adding a bit of our own +code, and then calling the original function) and then change the pointer at +sys_call_table to point to our function. Because we might be removed later and +we don’t want to leave the system in an unstable state, it’s important for +cleanup_module to restore the table to its original state. +

The source code here is an example of such a kernel module. We want to “spy” on +a certain user, and to pr_info() a message whenever that user opens a file. +Towards this end, we replace the system call to open a file with our own +function, called our_sys_open. This function checks the uid (user’s id) of the +current process, and if it is equal to the uid we spy on, it calls pr_info() +to display the name of the file to be opened. Then, either way, it calls the +original open() function with the same parameters, to actually open the +file. + + + +

The init_module function replaces the appropriate location in sys_call_table +and keeps the original pointer in a variable. The cleanup_module function uses that +variable to restore everything back to normal. This approach is dangerous, because of +the possibility of two kernel modules changing the same system call. Imagine we have +two kernel modules, A and B. A’s open system call will be A_open and B’s will be +B_open. Now, when A is inserted into the kernel, the system call is replaced with +A_open, which will call the original sys_open when it is done. Next, B +is inserted into the kernel, which replaces the system call with B_open, +which will call what it thinks is the original system call, A_open, when it’s +done. +

Now, if B is removed first, everything will be well — it will simply restore the +system call to A_open, which calls the original. However, if A is removed and then B +is removed, the system will crash. A’s removal will restore the system call to the +original, sys_open, cutting B out of the loop. Then, when B is removed, it will +restore the system call to what it thinks is the original, A_open, which is no +longer in memory. At first glance, it appears we could solve this particular +problem by checking if the system call is equal to our open function and if so +not changing it at all (so that B won’t change the system call when it is +removed), but that will cause an even worse problem. When A is removed, it +sees that the system call was changed to B_open so that it is no longer +pointing to A_open, so it will not restore it to sys_open before it is +removed from memory. Unfortunately, B_open will still try to call A_open +which is no longer there, so that even without removing B the system would +crash. +

Note that all the related problems make syscall stealing unfeasiable for production +use. In order to keep people from doing potential harmful things sys_call_table is +no longer exported. This means, if you want to do something more than a mere dry +run of this example, you will have to patch your current kernel in order to +have sys_call_table exported. In the example directory you will find a +README and the patch. As you can imagine, such modifications are not to be +taken lightly. Do not try this on valueable systems (ie systems that you +do not own - or cannot restore easily). You will need to get the complete +sourcecode of this guide as a tarball in order to get the patch and the README. +Depending on your kernel version, you might even need to hand apply the +patch. +

+

+
1/* 
+2 *  syscall.c 
+3 * 
+4 *  System call "stealing" sample. 
+5 * 
+6 *  Disables page protection at a processor level by 
+7 *  changing the 16th bit in the cr0 register (could be Intel specific) 
+8 * 
+9 *  Based on example by Peter Jay Salzman and 
+10 *  https://bbs.archlinux.org/viewtopic.php?id=139406 
+11 */ 
+12 
+13#include <linux/delay.h> 
+14#include <linux/kernel.h> 
+15#include <linux/module.h> 
+16#include <linux/moduleparam.h> /* which will have params */ 
+17#include <linux/syscalls.h> 
+18#include <linux/unistd.h> /* The list of system calls */ 
+19 
+20/* 
+21 * For the current (process) structure, we need 
+22 * this to know who the current user is. 
+23 */ 
+24#include <linux/sched.h> 
+25#include <linux/uaccess.h> 
+26 
+27unsigned long **sys_call_table; 
+28unsigned long original_cr0; 
+29 
+30/* 
+31 * UID we want to spy on - will be filled from the 
+32 * command line 
+33 */ 
+34static int uid; 
+35module_param(uid, int, 0644); 
+36 
+37/* 
+38 * A pointer to the original system call. The reason 
+39 * we keep this, rather than call the original function 
+40 * (sys_open), is because somebody else might have 
+41 * replaced the system call before us. Note that this 
+42 * is not 100% safe, because if another module 
+43 * replaced sys_open before us, then when we're inserted 
+44 * we'll call the function in that module - and it 
+45 * might be removed before we are. 
+46 * 
+47 * Another reason for this is that we can't get sys_open. 
+48 * It's a static variable, so it is not exported. 
+49 */ 
+50asmlinkage int (*original_call)(const char *, intint); 
+51 
+52/* 
+53 * The function we'll replace sys_open (the function 
+54 * called when you call the open system call) with. To 
+55 * find the exact prototype, with the number and type 
+56 * of arguments, we find the original function first 
+57 * (it's at fs/open.c). 
+58 * 
+59 * In theory, this means that we're tied to the 
+60 * current version of the kernel. In practice, the 
+61 * system calls almost never change (it would wreck havoc 
+62 * and require programs to be recompiled, since the system 
+63 * calls are the interface between the kernel and the 
+64 * processes). 
+65 */ 
+66asmlinkage int our_sys_open(const char *filename, int flags, int mode) 
+67{ 
+68    int i = 0; 
+69    char ch; 
+70 
+71    /* 
+72     * Report the file, if relevant 
+73     */ 
+74    pr_info("Opened file by %d: ", uid); 
+75    do { 
+76        get_user(ch, filename + i); 
+77        i++; 
+78        pr_info("%c", ch); 
+79    } while (ch != 0); 
+80    pr_info("\n"); 
+81 
+82    /* 
+83     * Call the original sys_open - otherwise, we lose 
+84     * the ability to open files 
+85     */ 
+86    return original_call(filename, flags, mode); 
+87} 
+88 
+89static unsigned long **aquire_sys_call_table(void) 
+90{ 
+91    unsigned long int offset = PAGE_OFFSET; 
+92    unsigned long **sct; 
+93 
+94    while (offset < ULLONG_MAX) { 
+95        sct = (unsigned long **) offset; 
+96 
+97        if (sct[__NR_close] == (unsigned long *) ksys_close) 
+98            return sct; 
+99 
+100        offset += sizeof(void *); 
+101    } 
+102 
+103    return NULL; 
+104} 
+105 
+106static int __init syscall_start(void) 
+107{ 
+108    if (!(sys_call_table = aquire_sys_call_table())) 
+109        return -1; 
+110 
+111    original_cr0 = read_cr0(); 
+112 
+113    write_cr0(original_cr0 & ~0x00010000); 
+114 
+115    /* keep track of the original open function */ 
+116    original_call = (void *) sys_call_table[__NR_open]; 
+117 
+118    /* use our open function instead */ 
+119    sys_call_table[__NR_open] = (unsigned long *) our_sys_open; 
+120 
+121    write_cr0(original_cr0); 
+122 
+123    pr_info("Spying on UID:%d\n", uid); 
+124 
+125    return 0; 
+126} 
+127 
+128static void __exit syscall_end(void) 
+129{ 
+130    if (!sys_call_table) { 
+131        return; 
+132    } 
+133 
+134    /* 
+135     * Return the system call back to normal 
+136     */ 
+137    if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) { 
+138        pr_alert("Somebody else also played with the "); 
+139        pr_alert("open system call\n"); 
+140        pr_alert("The system may be left in "); 
+141        pr_alert("an unstable state.\n"); 
+142    } 
+143 
+144    write_cr0(original_cr0 & ~0x00010000); 
+145    sys_call_table[__NR_open] = (unsigned long *) original_call; 
+146    write_cr0(original_cr0); 
+147 
+148    msleep(2000); 
+149} 
+150 
+151module_init(syscall_start); 
+152module_exit(syscall_end); 
+153 
+154MODULE_LICENSE("GPL");
+

+

+

0.11 Blocking Processes and threads

+ + + +

+

+

0.11.1 Sleep

+

What do you do when somebody asks you for something you can’t do right away? If +you’re a human being and you’re bothered by a human being, the only thing you can +say is: "Not right now, I’m busy. Go away!". But if you’re a kernel module and +you’re bothered by a process, you have another possibility. You can put the process +to sleep until you can service it. After all, processes are being put to sleep by the +kernel and woken up all the time (that’s the way multiple processes appear to run on +the same time on a single CPU). +

This kernel module is an example of this. The file (called /proc/sleep) can only +be opened by a single process at a time. If the file is already open, the kernel module +calls wait_event_interruptible. The easiest way to keep a file open is to open it +with: +

+

+
1tail -f
+

This function changes the status of the task (a task is the kernel data +structure which holds information about a process and the system call it’s in, if +any) to TASK_INTERRUPTIBLE, which means that the task will +not run until it is woken up somehow, and adds it to WaitQ, the queue +of tasks waiting to access the file. Then, the function calls the scheduler +to context switch to a different process, one which has some use for the +CPU. +

When a process is done with the file, it closes it, and module_close is called. That +function wakes up all the processes in the queue (there’s no mechanism +to only wake up one of them). It then returns and the process which just +closed the file can continue to run. In time, the scheduler decides that that +process has had enough and gives control of the CPU to another process. +Eventually, one of the processes which was in the queue will be given control +of the CPU by the scheduler. It starts at the point right after the call to +module_interruptible_sleep_on. +

This means that the process is still in kernel mode - as far as the process is +concerned, it issued the open system call and the system call hasn’t returned yet. +The process doesn’t know somebody else used the CPU for most of the time between +the moment it issued the call and the moment it returned. +

It can then proceed to set a global variable to tell all the other processes that the +file is still open and go on with its life. When the other processes get a piece of the +CPU, they’ll see that global variable and go back to sleep. +

So we’ll use tail -f to keep the file open in the background, while trying to +access it with another process (again in the background, so that we need not +switch to a different vt). As soon as the first background process is killed +with kill %1 , the second is woken up, is able to access the file and finally +terminates. + + + +

To make our life more interesting, module_close doesn’t have a monopoly +on waking up the processes which wait to access the file. A signal, such as +Ctrl +c (SIGINT) can also wake up a process. This is because we used +module_interruptible_sleep_on. We could have used module_sleep_on +instead, but that would have resulted in extremely angry users whose Ctrl+c’s are +ignored. +

In that case, we want to return with -EINTR immediately. This is important so +users can, for example, kill the process before it receives the file. +

There is one more point to remember. Some times processes don’t want to sleep, +they want either to get what they want immediately, or to be told it cannot be done. +Such processes use the O_NONBLOCK flag when opening the file. The kernel is +supposed to respond by returning with the error code -EAGAIN from operations +which would otherwise block, such as opening the file in this example. The program +cat_noblock, available in the source directory for this chapter, can be used to open a +file with O_NONBLOCK. + + + +

+
+$ sudo insmod sleep.ko
+$ cat_noblock /proc/sleep
+Last input:
+$ tail -f /proc/sleep &
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+Last input:
+tail: /proc/sleep: file truncated
+[1] 6540
+$ cat_noblock /proc/sleep
+Open would block
+$ kill %1
+[1]+  Terminated              tail -f /proc/sleep
+$ cat_noblock /proc/sleep
+Last input:
+$
+
+

+

+

+
1/* 
+2 *  sleep.c - create a /proc file, and if several processes try to open it at 
+3 *  the same time, put all but one to sleep 
+4 */ 
+5 
+6#include <linux/kernel.h>  /* We're doing kernel work */ 
+7#include <linux/module.h>  /* Specifically, a module */ 
+8#include <linux/proc_fs.h> /* Necessary because we use proc fs */ 
+9#include <linux/sched.h>   /* For putting processes to sleep and 
+10                                   waking them up */  
+11#include <linux/uaccess.h> /* for get_user and put_user */ 
+12#include <linux/version.h> 
+13 
+14#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 
+15#define HAVE_PROC_OPS 
+16#endif 
+17 
+18/* 
+19 * The module's file functions 
+20 */ 
+21 
+22/* 
+23 * Here we keep the last message received, to prove that we can process our 
+24 * input 
+25 */ 
+26#define MESSAGE_LENGTH 80 
+27static char Message[MESSAGE_LENGTH]; 
+28 
+29static struct proc_dir_entry *Our_Proc_File; 
+30#define PROC_ENTRY_FILENAME "sleep" 
+31 
+32/* 
+33 * Since we use the file operations struct, we can't use the special proc 
+34 * output provisions - we have to use a standard read function, which is this 
+35 * function 
+36 */ 
+37static ssize_t module_output(struct file *file, /* see include/linux/fs.h   */ 
+38                             char *buf,         /* The buffer to put data to 
+39                                                   (in the user segment)    */  
+40                             size_t len,        /* The length of the buffer */ 
+41                             loff_t *offset) 
+42{ 
+43    static int finished = 0; 
+44    int i; 
+45    char message[MESSAGE_LENGTH + 30]; 
+46 
+47    /* 
+48     * Return 0 to signify end of file - that we have nothing 
+49     * more to say at this point. 
+50     */ 
+51    if (finished) { 
+52        finished = 0; 
+53        return 0; 
+54    } 
+55 
+56    /* 
+57     * If you don't understand this by now, you're hopeless as a kernel 
+58     * programmer. 
+59     */ 
+60    sprintf(message, "Last input:%s\n", Message); 
+61    for (i = 0; i < len && message[i]; i++) 
+62        put_user(message[i], buf + i); 
+63 
+64    finished = 1; 
+65    return i; /* Return the number of bytes "read" */ 
+66} 
+67 
+68/* 
+69 * This function receives input from the user when the user writes to the /proc 
+70 * file. 
+71 */ 
+72static ssize_t module_input(struct file *file, /* The file itself */ 
+73                            const char *buf,   /* The buffer with input */ 
+74                            size_t length,     /* The buffer's length */ 
+75                            loff_t *offset)    /* offset to file - ignore */ 
+76{ 
+77    int i; 
+78 
+79    /* 
+80     * Put the input into Message, where module_output will later be 
+81     * able to use it 
+82     */ 
+83    for (i = 0; i < MESSAGE_LENGTH - 1 && i < length; i++) 
+84        get_user(Message[i], buf + i); 
+85    /* 
+86     * we want a standard, zero terminated string 
+87     */ 
+88    Message[i] = '\0'; 
+89 
+90    /* 
+91     * We need to return the number of input characters used 
+92     */ 
+93    return i; 
+94} 
+95 
+96/* 
+97 * 1 if the file is currently open by somebody 
+98 */ 
+99int Already_Open = 0; 
+100 
+101/* 
+102 * Queue of processes who want our file 
+103 */ 
+104DECLARE_WAIT_QUEUE_HEAD(WaitQ); 
+105/* 
+106 * Called when the /proc file is opened 
+107 */ 
+108static int module_open(struct inode *inode, struct file *file) 
+109{ 
+110    /* 
+111     * If the file's flags include O_NONBLOCK, it means the process doesn't 
+112     * want to wait for the file.  In this case, if the file is already 
+113     * open, we should fail with -EAGAIN, meaning "you'll have to try 
+114     * again", instead of blocking a process which would rather stay awake. 
+115     */ 
+116    if ((file->f_flags & O_NONBLOCK) && Already_Open) 
+117        return -EAGAIN; 
+118 
+119    /* 
+120     * This is the correct place for try_module_get(THIS_MODULE) because 
+121     * if a process is in the loop, which is within the kernel module, 
+122     * the kernel module must not be removed. 
+123     */ 
+124    try_module_get(THIS_MODULE); 
+125 
+126    /* 
+127     * If the file is already open, wait until it isn't 
+128     */ 
+129 
+130    while (Already_Open) { 
+131        int i, is_sig = 0; 
+132 
+133        /* 
+134         * This function puts the current process, including any system 
+135         * calls, such as us, to sleep.  Execution will be resumed right 
+136         * after the function call, either because somebody called 
+137         * wake_up(&WaitQ) (only module_close does that, when the file 
+138         * is closed) or when a signal, such as Ctrl-C, is sent 
+139         * to the process 
+140         */ 
+141        wait_event_interruptible(WaitQ, !Already_Open); 
+142 
+143        /* 
+144         * If we woke up because we got a signal we're not blocking, 
+145         * return -EINTR (fail the system call).  This allows processes 
+146         * to be killed or stopped. 
+147         */ 
+148 
+149        /* 
+150         * Emmanuel Papirakis: 
+151         * 
+152         * This is a little update to work with 2.2.*.  Signals now are 
+153         * contained in two words (64 bits) and are stored in a structure that 
+154         * contains an array of two unsigned longs.  We now have to make 2 
+155         * checks in our if. 
+156         * 
+157         * Ori Pomerantz: 
+158         * 
+159         * Nobody promised me they'll never use more than 64 bits, or that this 
+160         * book won't be used for a version of Linux with a word size of 16 
+161         * bits.  This code would work in any case. 
+162         */ 
+163        for (i = 0; i < _NSIG_WORDS && !is_sig; i++) 
+164            is_sig = current->pending.signal.sig[i] & ~current->blocked.sig[i]; 
+165 
+166        if (is_sig) { 
+167            /* 
+168             * It's important to put module_put(THIS_MODULE) here, 
+169             * because for processes where the open is interrupted 
+170             * there will never be a corresponding close. If we 
+171             * don't decrement the usage count here, we will be 
+172             * left with a positive usage count which we'll have no 
+173             * way to bring down to zero, giving us an immortal 
+174             * module, which can only be killed by rebooting 
+175             * the machine. 
+176             */ 
+177            module_put(THIS_MODULE); 
+178            return -EINTR; 
+179        } 
+180    } 
+181 
+182    /* 
+183     * If we got here, Already_Open must be zero 
+184     */ 
+185 
+186    /* 
+187     * Open the file 
+188     */ 
+189    Already_Open = 1; 
+190    return 0; /* Allow the access */ 
+191} 
+192 
+193/* 
+194 * Called when the /proc file is closed 
+195 */ 
+196int module_close(struct inode *inode, struct file *file) 
+197{ 
+198    /* 
+199     * Set Already_Open to zero, so one of the processes in the WaitQ will 
+200     * be able to set Already_Open back to one and to open the file. All 
+201     * the other processes will be called when Already_Open is back to one, 
+202     * so they'll go back to sleep. 
+203     */ 
+204    Already_Open = 0; 
+205 
+206    /* 
+207     * Wake up all the processes in WaitQ, so if anybody is waiting for the 
+208     * file, they can have it. 
+209     */ 
+210    wake_up(&WaitQ); 
+211 
+212    module_put(THIS_MODULE); 
+213 
+214    return 0; /* success */ 
+215} 
+216 
+217/* 
+218 * Structures to register as the /proc file, with pointers to all the relevant 
+219 * functions. 
+220 */ 
+221 
+222/* 
+223 * File operations for our proc file. This is where we place pointers to all 
+224 * the functions called when somebody tries to do something to our file. NULL 
+225 * means we don't want to deal with something. 
+226 */ 
+227#ifdef HAVE_PROC_OPS 
+228static const struct proc_ops File_Ops_4_Our_Proc_File = { 
+229    .proc_read = module_output,   /* "read" from the file */ 
+230    .proc_write = module_input,   /* "write" to the file */ 
+231    .proc_open = module_open,     /* called when the /proc file is opened */ 
+232    .proc_release = module_close, /* called when it's closed */ 
+233}; 
+234#else 
+235static const struct file_operations File_Ops_4_Our_Proc_File = { 
+236    .read = module_output, 
+237    .write = module_input, 
+238    .open = module_open, 
+239    .release = module_close, 
+240}; 
+241#endif 
+242 
+243/* 
+244 * Module initialization and cleanup 
+245 */ 
+246 
+247/* 
+248 * Initialize the module - register the proc file 
+249 */ 
+250 
+251int init_module() 
+252{ 
+253    Our_Proc_File = 
+254        proc_create(PROC_ENTRY_FILENAME, 0644, NULL, &File_Ops_4_Our_Proc_File); 
+255    if (Our_Proc_File == NULL) { 
+256        remove_proc_entry(PROC_ENTRY_FILENAME, NULL); 
+257        pr_debug("Error: Could not initialize /proc/%s\n", PROC_ENTRY_FILENAME); 
+258        return -ENOMEM; 
+259    } 
+260    proc_set_size(Our_Proc_File, 80); 
+261    proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); 
+262 
+263    pr_info("/proc/test created\n"); 
+264 
+265    return 0; 
+266} 
+267 
+268/* 
+269 * Cleanup - unregister our file from /proc.  This could get dangerous if 
+270 * there are still processes waiting in WaitQ, because they are inside our 
+271 * open function, which will get unloaded. I'll explain how to avoid removal 
+272 * of a kernel module in such a case in chapter 10. 
+273 */ 
+274void cleanup_module() 
+275{ 
+276    remove_proc_entry(PROC_ENTRY_FILENAME, NULL); 
+277    pr_debug("/proc/%s removed\n", PROC_ENTRY_FILENAME); 
+278} 
+279 
+280MODULE_LICENSE("GPL");
+ +

+

+
1/* 
+2 *  cat_noblock.c - open a file and display its contents, but exit rather than 
+3 *  wait for input. 
+4 */ 
+5#include <errno.h>  /* for errno */ 
+6#include <fcntl.h>  /* for open */ 
+7#include <stdio.h>  /* standard I/O */ 
+8#include <stdlib.h> /* for exit */ 
+9#include <unistd.h> /* for read */ 
+10 
+11#define MAX_BYTES 1024 * 4 
+12 
+13int main(int argc, char *argv[]) 
+14{ 
+15    int fd;                 /* The file descriptor for the file to read */ 
+16    size_t bytes;           /* The number of bytes read */ 
+17    char buffer[MAX_BYTES]; /* The buffer for the bytes */ 
+18 
+19 
+20    /* Usage */ 
+21    if (argc != 2) { 
+22        printf("Usage: %s <filename>\n", argv[0]); 
+23        puts("Reads the content of a file, but doesn't wait for input"); 
+24        exit(-1); 
+25    } 
+26 
+27    /* Open the file for reading in non blocking mode */ 
+28    fd = open(argv[1], O_RDONLY | O_NONBLOCK); 
+29 
+30    /* If open failed */ 
+31    if (fd == -1) { 
+32        if (errno = EAGAIN) 
+33            puts("Open would block"); 
+34        else 
+35            puts("Open failed"); 
+36        exit(-1); 
+37    } 
+38 
+39    /* Read the file and output its contents */ 
+40    do { 
+41        int i; 
+42 
+43        /* Read characters from the file */ 
+44        bytes = read(fd, buffer, MAX_BYTES); 
+45 
+46        /* If there's an error, report it and die */ 
+47        if (bytes == -1) { 
+48            if (errno = EAGAIN) 
+49                puts("Normally I'd block, but you told me not to"); 
+50            else 
+51                puts("Another read error"); 
+52            exit(-1); 
+53        } 
+54 
+55        /* Print the characters */ 
+56        if (bytes > 0) { 
+57            for (i = 0; i < bytes; i++) 
+58                putchar(buffer[i]); 
+59        } 
+60 
+61        /* While there are no errors and the file isn't over */ 
+62    } while (bytes > 0); 
+63    return 0; 
+64}
+

+

+

0.11.2 Completions

+

Sometimes one thing should happen before another within a module having multiple +threads. Rather than using /proc/sleep commands the kernel has another way to +do this which allows timeouts or interrupts to also happen. +

In the following example two threads are started, but one needs to start before +another. +

+ + + +

+
1/* 
+2 *  completions.c 
+3 */ 
+4#include <linux/completion.h> 
+5#include <linux/init.h> 
+6#include <linux/kernel.h> 
+7#include <linux/kthread.h> 
+8#include <linux/module.h> 
+9 
+10static struct { 
+11    struct completion crank_comp; 
+12    struct completion flywheel_comp; 
+13} machine; 
+14 
+15static int machine_crank_thread(void *arg) 
+16{ 
+17    pr_info("Turn the crank\n"); 
+18 
+19    complete_all(&machine.crank_comp); 
+20    complete_and_exit(&machine.crank_comp, 0); 
+21} 
+22 
+23static int machine_flywheel_spinup_thread(void *arg) 
+24{ 
+25    wait_for_completion(&machine.crank_comp); 
+26 
+27    pr_info("Flywheel spins up\n"); 
+28 
+29    complete_all(&machine.flywheel_comp); 
+30    complete_and_exit(&machine.flywheel_comp, 0); 
+31} 
+32 
+33static int completions_init(void) 
+34{ 
+35    struct task_struct *crank_thread; 
+36    struct task_struct *flywheel_thread; 
+37 
+38    pr_info("completions example\n"); 
+39 
+40    init_completion(&machine.crank_comp); 
+41    init_completion(&machine.flywheel_comp); 
+42 
+43    crank_thread = kthread_create(machine_crank_thread, NULL, "KThread Crank"); 
+44    if (IS_ERR(crank_thread)) 
+45        goto ERROR_THREAD_1; 
+46 
+47    flywheel_thread = kthread_create(machine_flywheel_spinup_thread, NULL, 
+48                                     "KThread Flywheel"); 
+49    if (IS_ERR(flywheel_thread)) 
+50        goto ERROR_THREAD_2; 
+51 
+52    wake_up_process(flywheel_thread); 
+53    wake_up_process(crank_thread); 
+54 
+55    return 0; 
+56 
+57ERROR_THREAD_2: 
+58    kthread_stop(crank_thread); 
+59ERROR_THREAD_1: 
+60 
+61    return -1; 
+62} 
+63 
+64void completions_exit(void) 
+65{ 
+66    wait_for_completion(&machine.crank_comp); 
+67    wait_for_completion(&machine.flywheel_comp); 
+68 
+69    pr_info("completions exit\n"); 
+70} 
+71 
+72module_init(completions_init); 
+73module_exit(completions_exit); 
+74 
+75MODULE_DESCRIPTION("Completions example"); 
+76MODULE_LICENSE("GPL");
+

The machine structure stores the completion states for the two threads. At the +exit point of each thread the respective completion state is updated, and +wait_for_completion is used by the flywheel thread to ensure that it doesn’t begin +prematurely. +

So even though flywheel_thread is started first you should notice if you load this +module and run dmesg that turning the crank always happens first because the +flywheel thread waits for it to complete. +

There are other variations upon the wait_for_completion function, which include +timeouts or being interrupted, but this basic mechanism is enough for many common +situations without adding a lot of complexity. +

+

+

0.12 Avoiding Collisions and Deadlocks

+

If processes running on different CPUs or in different threads try to access the same +memory then it’s possible that strange things can happen or your system can lock +up. To avoid this various types of mutual exclusion kernel functions are available. +These indicate if a section of code is "locked" or "unlocked" so that simultaneous +attempts to run it can’t happen. +

+

0.12.1 Mutex

+

You can use kernel mutexes (mutual exclusions) in much the same manner that you +might deploy them in userland. This may be all that’s needed to avoid collisions in +most cases. +

+

+
1/* 
+2 *  example_mutex.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7#include <linux/mutex.h> 
+8 
+9DEFINE_MUTEX(mymutex); 
+10 
+11static int example_mutex_init(void) 
+12{ 
+13    int ret; 
+14 
+15    pr_info("example_mutex init\n"); 
+16 
+17    ret = mutex_trylock(&mymutex); 
+18    if (ret != 0) { 
+19        pr_info("mutex is locked\n"); 
+20 
+21        if (mutex_is_locked(&mymutex) == 0) 
+22            pr_info("The mutex failed to lock!\n"); 
+23 
+24        mutex_unlock(&mymutex); 
+25        pr_info("mutex is unlocked\n"); 
+26    } else 
+27        pr_info("Failed to lock\n"); 
+28 
+29    return 0; 
+30} 
+31 
+32static void example_mutex_exit(void) 
+33{ 
+34    pr_info("example_mutex exit\n"); 
+35} 
+36 
+37module_init(example_mutex_init); 
+38module_exit(example_mutex_exit); 
+39 
+40MODULE_DESCRIPTION("Mutex example"); 
+41MODULE_LICENSE("GPL");
+

+

+

0.12.2 Spinlocks

+

As the name suggests, spinlocks lock up the CPU that the code is running on, +taking 100% of its resources. Because of this you should only use the spinlock +mechanism around code which is likely to take no more than a few milliseconds to +run and so won’t noticably slow anything down from the user’s point of +view. + + + +

The example here is "irq safe" in that if interrupts happen during the lock then +they won’t be forgotten and will activate when the unlock happens, using the flags +variable to retain their state. +

+

+
1/* 
+2 *  example_spinlock.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/interrupt.h> 
+6#include <linux/kernel.h> 
+7#include <linux/module.h> 
+8#include <linux/spinlock.h> 
+9 
+10DEFINE_SPINLOCK(sl_static); 
+11spinlock_t sl_dynamic; 
+12 
+13static void example_spinlock_static(void) 
+14{ 
+15    unsigned long flags; 
+16 
+17    spin_lock_irqsave(&sl_static, flags); 
+18    pr_info("Locked static spinlock\n"); 
+19 
+20    /* Do something or other safely. 
+21       Because this uses 100% CPU time this 
+22       code should take no more than a few 
+23       milliseconds to run */ 
+24 
+25    spin_unlock_irqrestore(&sl_static, flags); 
+26    pr_info("Unlocked static spinlock\n"); 
+27} 
+28 
+29static void example_spinlock_dynamic(void) 
+30{ 
+31    unsigned long flags; 
+32 
+33    spin_lock_init(&sl_dynamic); 
+34    spin_lock_irqsave(&sl_dynamic, flags); 
+35    pr_info("Locked dynamic spinlock\n"); 
+36 
+37    /* Do something or other safely. 
+38       Because this uses 100% CPU time this 
+39       code should take no more than a few 
+40       milliseconds to run */ 
+41 
+42    spin_unlock_irqrestore(&sl_dynamic, flags); 
+43    pr_info("Unlocked dynamic spinlock\n"); 
+44} 
+45 
+46static int example_spinlock_init(void) 
+47{ 
+48    pr_info("example spinlock started\n"); 
+49 
+50    example_spinlock_static(); 
+51    example_spinlock_dynamic(); 
+52 
+53    return 0; 
+54} 
+55 
+56static void example_spinlock_exit(void) 
+57{ 
+58    pr_info("example spinlock exit\n"); 
+59} 
+60 
+61module_init(example_spinlock_init); 
+62module_exit(example_spinlock_exit); 
+63 
+64MODULE_DESCRIPTION("Spinlock example"); 
+65MODULE_LICENSE("GPL");
+

+

+

0.12.3 Read and write locks

+

Read and write locks are specialised kinds of spinlocks so that you can exclusively +read from something or write to something. Like the earlier spinlocks example the +one below shows an "irq safe" situation in which if other functions were triggered +from irqs which might also read and write to whatever you are concerned +with then they wouldn’t disrupt the logic. As before it’s a good idea to keep +anything done within the lock as short as possible so that it doesn’t hang up +the system and cause users to start revolting against the tyranny of your +module. +

+

+
1/* 
+2 *  example_rwlock.c 
+3 */ 
+4#include <linux/interrupt.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7 
+8DEFINE_RWLOCK(myrwlock); 
+9 
+10static void example_read_lock(void) 
+11{ 
+12    unsigned long flags; 
+13 
+14    read_lock_irqsave(&myrwlock, flags); 
+15    pr_info("Read Locked\n"); 
+16 
+17    /* Read from something */ 
+18 
+19    read_unlock_irqrestore(&myrwlock, flags); 
+20    pr_info("Read Unlocked\n"); 
+21} 
+22 
+23static void example_write_lock(void) 
+24{ 
+25    unsigned long flags; 
+26 
+27    write_lock_irqsave(&myrwlock, flags); 
+28    pr_info("Write Locked\n"); 
+29 
+30    /* Write to something */ 
+31 
+32    write_unlock_irqrestore(&myrwlock, flags); 
+33    pr_info("Write Unlocked\n"); 
+34} 
+35 
+36static int example_rwlock_init(void) 
+37{ 
+38    pr_info("example_rwlock started\n"); 
+39 
+40    example_read_lock(); 
+41    example_write_lock(); 
+42 
+43    return 0; 
+44} 
+45 
+46static void example_rwlock_exit(void) 
+47{ 
+48    pr_info("example_rwlock exit\n"); 
+49} 
+50 
+51module_init(example_rwlock_init); 
+52module_exit(example_rwlock_exit); 
+53 
+54MODULE_DESCRIPTION("Read/Write locks example"); 
+55MODULE_LICENSE("GPL");
+

Of course if you know for sure that there are no functions triggered by irqs +which could possibly interfere with your logic then you can use the simpler +read_lock(&myrwlock) and read_unlock(&myrwlock) or the corresponding write +functions. +

+

0.12.4 Atomic operations

+

If you’re doing simple arithmetic: adding, subtracting or bitwise operations then +there’s another way in the multi-CPU and multi-hyperthreaded world to stop other +parts of the system from messing with your mojo. By using atomic operations you +can be confident that your addition, subtraction or bit flip did actually happen +and wasn’t overwritten by some other shenanigans. An example is shown +below. +

+

+
1/* 
+2 *  example_atomic.c 
+3 */ 
+4#include <linux/interrupt.h> 
+5#include <linux/kernel.h> 
+6#include <linux/module.h> 
+7 
+8#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c" 
+9#define BYTE_TO_BINARY(byte)                                  \ 
+10    (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'),     \ 
+11        (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), \ 
+12        (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), \ 
+13        (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0') 
+14 
+15static void atomic_add_subtract(void) 
+16{ 
+17    atomic_t debbie; 
+18    atomic_t chris = ATOMIC_INIT(50); 
+19 
+20    atomic_set(&debbie, 45); 
+21 
+22    /* subtract one */ 
+23    atomic_dec(&debbie); 
+24 
+25    atomic_add(7, &debbie); 
+26 
+27    /* add one */ 
+28    atomic_inc(&debbie); 
+29 
+30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
+31            atomic_read(&debbie)); 
+32} 
+33 
+34static void atomic_bitwise(void) 
+35{ 
+36    unsigned long word = 0; 
+37 
+38    pr_info("Bits 0: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+39    set_bit(3, &word); 
+40    set_bit(5, &word); 
+41    pr_info("Bits 1: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+42    clear_bit(5, &word); 
+43    pr_info("Bits 2: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+44    change_bit(3, &word); 
+45 
+46    pr_info("Bits 3: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+47    if (test_and_set_bit(3, &word)) 
+48        pr_info("wrong\n"); 
+49    pr_info("Bits 4: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+50 
+51    word = 255; 
+52    pr_info("Bits 5: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+53} 
+54 
+55static int example_atomic_init(void) 
+56{ 
+57    pr_info("example_atomic started\n"); 
+58 
+59    atomic_add_subtract(); 
+60    atomic_bitwise(); 
+61 
+62    return 0; 
+63} 
+64 
+65static void example_atomic_exit(void) 
+66{ 
+67    pr_info("example_atomic exit\n"); 
+68} 
+69 
+70module_init(example_atomic_init); 
+71module_exit(example_atomic_exit); 
+72 
+73MODULE_DESCRIPTION("Atomic operations example"); 
+74MODULE_LICENSE("GPL");
+ + + +

+

+

0.13 Replacing Print Macros

+

+

+

0.13.1 Replacement

+

In Section 1.2.1.2, I said that X and kernel module programming don’t mix. That’s +true for developing kernel modules, but in actual use, you want to be able +to send messages to whichever tty the command to load the module came +from. +

"tty" is an abbreviation of teletype: originally a combination keyboard-printer +used to communicate with a Unix system, and today an abstraction for the text +stream used for a Unix program, whether it’s a physical terminal, an xterm on an X +display, a network connection used with ssh, etc. +

The way this is done is by using current, a pointer to the currently running task, +to get the current task’s tty structure. Then, we look inside that tty structure to find +a pointer to a string write function, which we use to write a string to the +tty. +

+

+
1/* 
+2 *  print_string.c - Send output to the tty we're running on, regardless if it's 
+3 *  through X11, telnet, etc.  We do this by printing the string to the tty 
+4 *  associated with the current task. 
+5 */ 
+6#include <linux/init.h> 
+7#include <linux/kernel.h> 
+8#include <linux/module.h> 
+9#include <linux/sched.h> /* For current */ 
+10#include <linux/tty.h>   /* For the tty declarations */ 
+11 
+12MODULE_LICENSE("GPL"); 
+13 
+14static void print_string(char *str) 
+15{ 
+16    struct tty_struct *my_tty; 
+17    const struct tty_operations *ttyops; 
+18 
+19    /* 
+20     * The tty for the current task, for 2.6.6+ kernels 
+21     */ 
+22    my_tty = get_current_tty(); 
+23    ttyops = my_tty->driver->ops; 
+24 
+25    /* 
+26     * If my_tty is NULL, the current task has no tty you can print to 
+27     * (ie, if it's a daemon).  If so, there's nothing we can do. 
+28     */ 
+29    if (my_tty != NULL) { 
+30        /* 
+31         * my_tty->driver is a struct which holds the tty's functions, 
+32         * one of which (write) is used to write strings to the tty. 
+33         * It can be used to take a string either from the user's or 
+34         * kernel's memory segment. 
+35         * 
+36         * The function's 1st parameter is the tty to write to, 
+37         * because the same function would normally be used for all 
+38         * tty's of a certain type. 
+39         * The 2nd parameter is a pointer to a string. 
+40         * The 3rd parameter is the length of the string. 
+41         * 
+42         * As you will see below, sometimes it's necessary to use 
+43         * preprocessor stuff to create code that works for different 
+44         * kernel versions. The (naive) approach we've taken here 
+45         * does not scale well. The right way to deal with this 
+46         * is described in section 2 of 
+47         * linux/Documentation/SubmittingPatches 
+48         */ 
+49        (ttyops->write)(my_tty,       /* The tty itself */ 
+50                        str,          /* String                 */ 
+51                        strlen(str)); /* Length */ 
+52 
+53        /* 
+54         * ttys were originally hardware devices, which (usually) 
+55         * strictly followed the ASCII standard.  In ASCII, to move to 
+56         * a new line you need two characters, a carriage return and a 
+57         * line feed.  On Unix, the ASCII line feed is used for both 
+58         * purposes - so we can't just use \n, because it wouldn't have 
+59         * a carriage return and the next line will start at the 
+60         * column right after the line feed. 
+61         * 
+62         * This is why text files are different between Unix and 
+63         * MS Windows.  In CP/M and derivatives, like MS-DOS and 
+64         * MS Windows, the ASCII standard was strictly adhered to, 
+65         * and therefore a newline requirs both a LF and a CR. 
+66         */ 
+67        (ttyops->write)(my_tty, "\015\012", 2); 
+68    } 
+69} 
+70 
+71static int __init print_string_init(void) 
+72{ 
+73    print_string("The module has been inserted.  Hello world!"); 
+74    return 0; 
+75} 
+76 
+77static void __exit print_string_exit(void) 
+78{ 
+79    print_string("The module has been removed.  Farewell world!"); 
+80} 
+81 
+82module_init(print_string_init); 
+83module_exit(print_string_exit);
+

+

+

0.13.2 Flashing keyboard LEDs

+

In certain conditions, you may desire a simpler and more direct way to communicate +to the external world. Flashing keyboard LEDs can be such a solution: It is an +immediate way to attract attention or to display a status condition. Keyboard LEDs +are present on every hardware, they are always visible, they do not need any setup, +and their use is rather simple and non-intrusive, compared to writing to a tty or a +file. +

The following source code illustrates a minimal kernel module which, when +loaded, starts blinking the keyboard LEDs until it is unloaded. +

+

+
1/* 
+2 *  kbleds.c - Blink keyboard leds until the module is unloaded. 
+3 */ 
+4 
+5#include <linux/init.h> 
+6#include <linux/kd.h> /* For KDSETLED */ 
+7#include <linux/module.h> 
+8#include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */ 
+9#include <linux/vt.h> 
+10#include <linux/vt_kern.h> /* for fg_console */ 
+11 
+12#include <linux/console_struct.h> /* For vc_cons */ 
+13 
+14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
+15MODULE_LICENSE("GPL"); 
+16 
+17struct timer_list my_timer; 
+18struct tty_driver *my_driver; 
+19char kbledstatus = 0; 
+20 
+21#define BLINK_DELAY HZ / 5 
+22#define ALL_LEDS_ON 0x07 
+23#define RESTORE_LEDS 0xFF 
+24 
+25/* 
+26 * Function my_timer_func blinks the keyboard LEDs periodically by invoking 
+27 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
+28 * terminal ioctl operations, please see file: 
+29 *     /usr/src/linux/drivers/char/vt_ioctl.c, function vt_ioctl(). 
+30 * 
+31 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
+32 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
+33 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
+34 * the LEDs reflect the actual keyboard status).  To learn more on this, 
+35 * please see file: 
+36 *     /usr/src/linux/drivers/char/keyboard.c, function setledstate(). 
+37 * 
+38 */ 
+39 
+40static void my_timer_func(unsigned long ptr) 
+41{ 
+42    unsigned long *pstatus = (unsigned long *) ptr; 
+43    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
+44 
+45    if (*pstatus == ALL_LEDS_ON) 
+46        *pstatus = RESTORE_LEDS; 
+47    else 
+48        *pstatus = ALL_LEDS_ON; 
+49 
+50    (my_driver->ops->ioctl)(t, KDSETLED, *pstatus); 
+51 
+52    my_timer.expires = jiffies + BLINK_DELAY; 
+53    add_timer(&my_timer); 
+54} 
+55 
+56static int __init kbleds_init(void) 
+57{ 
+58    int i; 
+59 
+60    pr_info("kbleds: loading\n"); 
+61    pr_info("kbleds: fgconsole is %x\n", fg_console); 
+62    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
+63        if (!vc_cons[i].d) 
+64            break; 
+65        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
+66                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
+67    } 
+68    pr_info("kbleds: finished scanning consoles\n"); 
+69 
+70    my_driver = vc_cons[fg_console].d->port.tty->driver; 
+71    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
+72 
+73    /* 
+74     * Set up the LED blink timer the first time 
+75     */ 
+76    timer_setup(&my_timer, (void *) &my_timer_func, 
+77                (unsigned long) &kbledstatus); 
+78    my_timer.expires = jiffies + BLINK_DELAY; 
+79    add_timer(&my_timer); 
+80 
+81    return 0; 
+82} 
+83 
+84static void __exit kbleds_cleanup(void) 
+85{ 
+86    pr_info("kbleds: unloading...\n"); 
+87    del_timer(&my_timer); 
+88    (my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, 
+89                            RESTORE_LEDS); 
+90} 
+91 
+92module_init(kbleds_init); 
+93module_exit(kbleds_cleanup);
+

If none of the examples in this chapter fit your debugging needs there might yet +be some other tricks to try. Ever wondered what CONFIG_LL_DEBUG in +make menuconfig is good for? If you activate that you get low level access +to the serial port. While this might not sound very powerful by itself, you + + + +can patch kernel/printk.c or any other essential syscall to use printascii, +thus makeing it possible to trace virtually everything what your code does +over a serial line. If you find yourself porting the kernel to some new and +former unsupported architecture this is usually amongst the first things that +should be implemented. Logging over a netconsole might also be worth a +try. +

While you have seen lots of stuff that can be used to aid debugging here, there are +some things to be aware of. Debugging is almost always intrusive. Adding debug code +can change the situation enough to make the bug seem to dissappear. Thus you +should try to keep debug code to a minimum and make sure it does not show up in +production code. +

+

+

0.14 Scheduling Tasks

+

There are two main ways of running tasks: tasklets and work queues. Tasklets are a +quick and easy way of scheduling a single function to be run, for example when +triggered from an interrupt, whereas work queues are more complicated but also +better suited to running multiple things in a sequence. +

+

+

0.14.1 Tasklets

+

Here’s an example tasklet module. The tasklet_fn function runs for a few seconds +and in the mean time execution of the example_tasklet_init function continues to +the exit point. +

+

+
1/* 
+2 *  example_tasklet.c 
+3 */ 
+4#include <linux/delay.h> 
+5#include <linux/interrupt.h> 
+6#include <linux/kernel.h> 
+7#include <linux/module.h> 
+8 
+9static void tasklet_fn(unsigned long data) 
+10{ 
+11    pr_info("Example tasklet starts\n"); 
+12    mdelay(5000); 
+13    pr_info("Example tasklet ends\n"); 
+14} 
+15 
+16DECLARE_TASKLET(mytask, tasklet_fn, 0L); 
+17 
+18static int example_tasklet_init(void) 
+19{ 
+20    pr_info("tasklet example init\n"); 
+21    tasklet_schedule(&mytask); 
+22    mdelay(200); 
+23    pr_info("Example tasklet init continues...\n"); 
+24    return 0; 
+25} 
+26 
+27static void example_tasklet_exit(void) 
+28{ 
+29    pr_info("tasklet example exit\n"); 
+30    tasklet_kill(&mytask); 
+31} 
+32 
+33module_init(example_tasklet_init); 
+34module_exit(example_tasklet_exit); 
+35 
+36MODULE_DESCRIPTION("Tasklet example"); 
+37MODULE_LICENSE("GPL");
+

So with this example loaded dmesg should show: + + + +

+
+tasklet example init
+Example tasklet starts
+Example tasklet init continues...
+Example tasklet ends
+
+

+

+

+

0.14.2 Work queues

+

To add a task to the scheduler we can use a workqueue. The kernel then uses the +Completely Fair Scheduler (CFS) to execute work within the queue. +

+

+
1/* 
+2 *  sched.c 
+3 */ 
+4#include <linux/init.h> 
+5#include <linux/module.h> 
+6#include <linux/workqueue.h> 
+7 
+8static struct workqueue_struct *queue = NULL; 
+9static struct work_struct work; 
+10 
+11static void work_handler(struct work_struct *data) 
+12{ 
+13    pr_info("work handler function.\n"); 
+14} 
+15 
+16int init_module() 
+17{ 
+18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
+19    INIT_WORK(&work, work_handler); 
+20    schedule_work(&work); 
+21 
+22    return 0; 
+23} 
+24 
+25void cleanup_module() 
+26{ 
+27    destroy_workqueue(queue); 
+28} 
+29 
+30MODULE_LICENSE("GPL"); 
+31MODULE_DESCRIPTION("Workqueue example");
+

+

+

0.15 Interrupt Handlers

+

+

+

0.15.1 Interrupt Handlers

+

Except for the last chapter, everything we did in the kernel so far we’ve done as a +response to a process asking for it, either by dealing with a special file, sending an +ioctl(), or issuing a system call. But the job of the kernel isn’t just to respond to +process requests. Another job, which is every bit as important, is to speak to the +hardware connected to the machine. +

There are two types of interaction between the CPU and the rest of the +computer’s hardware. The first type is when the CPU gives orders to the hardware, +the other is when the hardware needs to tell the CPU something. The second, called +interrupts, is much harder to implement because it has to be dealt with when +convenient for the hardware, not the CPU. Hardware devices typically have a very +small amount of RAM, and if you don’t read their information when available, it is +lost. + + + +

Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There +are two types of IRQ’s, short and long. A short IRQ is one which is expected to take +a very short period of time, during which the rest of the machine will be blocked and +no other interrupts will be handled. A long IRQ is one which can take longer, and +during which other interrupts may occur (but not interrupts from the same +device). If at all possible, it’s better to declare an interrupt handler to be +long. +

When the CPU receives an interrupt, it stops whatever it’s doing (unless it’s +processing a more important interrupt, in which case it will deal with this one +only when the more important one is done), saves certain parameters on +the stack and calls the interrupt handler. This means that certain things +are not allowed in the interrupt handler itself, because the system is in an +unknown state. The solution to this problem is for the interrupt handler to +do what needs to be done immediately, usually read something from the +hardware or send something to the hardware, and then schedule the handling of +the new information at a later time (this is called the "bottom half") and +return. The kernel is then guaranteed to call the bottom half as soon as +possible – and when it does, everything allowed in kernel modules will be +allowed. +

The way to implement this is to call request_irq() to get your interrupt handler +called when the relevant IRQ is received. +

In practice IRQ handling can be a bit more complex. Hardware is often +designed in a way that chains two interrupt controllers, so that all the IRQs +from interrupt controller B are cascaded to a certain IRQ from interrupt +controller A. Of course that requires that the kernel finds out which IRQ it +really was afterwards and that adds overhead. Other architectures offer some +special, very low overhead, so called "fast IRQ" or FIQs. To take advantage of +them requires handlers to be written in assembler, so they do not really fit +into the kernel. They can be made to work similar to the others, but after +that procedure, they’re no longer any faster than "common" IRQs. SMP +enabled kernels running on systems with more than one processor need to solve +another truckload of problems. It’s not enough to know if a certain IRQs +has happend, it’s also important for what CPU(s) it was for. People still +interested in more details, might want to do a web search for "APIC" now +;) +

This function receives the IRQ number, the name of the function, flags, a name +for /proc/interrupts and a parameter to pass to the interrupt handler. Usually +there is a certain number of IRQs available. How many IRQs there are is +hardware-dependent. The flags can include SA_SHIRQ to indicate you’re willing to +share the IRQ with other interrupt handlers (usually because a number of hardware +devices sit on the same IRQ) and SA_INTERRUPT to indicate this is a fast +interrupt. This function will only succeed if there isn’t already a handler on this IRQ, +or if you’re both willing to share. + + + +

+

+

0.15.2 Detecting button presses

+

Many popular single board computers, such as Raspberry Pis or Beagleboards, have +a bunch of GPIO pins. Attaching buttons to those and then having a button press do +something is a classic case in which you might need to use interrupts so that instead +of having the CPU waste time and battery power polling for a change in input state +it’s better for the input to trigger the CPU to then run a particular handling +function. +

Here’s an example where buttons are connected to GPIO numbers 17 and 18 and +an LED is connected to GPIO 4. You can change those numbers to whatever is +appropriate for your board. +

+

+
1/* 
+2 *  intrpt.c - Handling GPIO with interrupts 
+3 * 
+4 *  Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de) 
+5 *  from: 
+6 *    https://github.com/wendlers/rpi-kmod-samples 
+7 * 
+8 *  Press one button to turn on a LED and another to turn it off 
+9 */ 
+10 
+11#include <linux/gpio.h> 
+12#include <linux/interrupt.h> 
+13#include <linux/kernel.h> 
+14#include <linux/module.h> 
+15 
+16static int button_irqs[] = {-1, -1}; 
+17 
+18/* Define GPIOs for LEDs. 
+19   Change the numbers for the GPIO on your board. */ 
+20static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+21 
+22/* Define GPIOs for BUTTONS 
+23   Change the numbers for the GPIO on your board. */ 
+24static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+25                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+26 
+27/* 
+28 * interrupt function triggered when a button is pressed 
+29 */ 
+30static irqreturn_t button_isr(int irq, void *data) 
+31{ 
+32    /* first button */ 
+33    if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio)) 
+34        gpio_set_value(leds[0].gpio, 1); 
+35    /* second button */ 
+36    else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio)) 
+37        gpio_set_value(leds[0].gpio, 0); 
+38 
+39    return IRQ_HANDLED; 
+40} 
+41 
+42int init_module() 
+43{ 
+44    int ret = 0; 
+45 
+46    pr_info("%s\n", __func__); 
+47 
+48    /* register LED gpios */ 
+49    ret = gpio_request_array(leds, ARRAY_SIZE(leds)); 
+50 
+51    if (ret) { 
+52        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+53        return ret; 
+54    } 
+55 
+56    /* register BUTTON gpios */ 
+57    ret = gpio_request_array(buttons, ARRAY_SIZE(buttons)); 
+58 
+59    if (ret) { 
+60        pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret); 
+61        goto fail1; 
+62    } 
+63 
+64    pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio)); 
+65 
+66    ret = gpio_to_irq(buttons[0].gpio); 
+67 
+68    if (ret < 0) { 
+69        pr_err("Unable to request IRQ: %d\n", ret); 
+70        goto fail2; 
+71    } 
+72 
+73    button_irqs[0] = ret; 
+74 
+75    pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]); 
+76 
+77    ret = request_irq(button_irqs[0], button_isr, 
+78                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+79                      "gpiomod#button1", NULL); 
+80 
+81    if (ret) { 
+82        pr_err("Unable to request IRQ: %d\n", ret); 
+83        goto fail2; 
+84    } 
+85 
+86 
+87    ret = gpio_to_irq(buttons[1].gpio); 
+88 
+89    if (ret < 0) { 
+90        pr_err("Unable to request IRQ: %d\n", ret); 
+91        goto fail2; 
+92    } 
+93 
+94    button_irqs[1] = ret; 
+95 
+96    pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]); 
+97 
+98    ret = request_irq(button_irqs[1], button_isr, 
+99                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+100                      "gpiomod#button2", NULL); 
+101 
+102    if (ret) { 
+103        pr_err("Unable to request IRQ: %d\n", ret); 
+104        goto fail3; 
+105    } 
+106 
+107    return 0; 
+108 
+109/* cleanup what has been setup so far */ 
+110fail3: 
+111    free_irq(button_irqs[0], NULL); 
+112 
+113fail2: 
+114    gpio_free_array(buttons, ARRAY_SIZE(leds)); 
+115 
+116fail1: 
+117    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+118 
+119    return ret; 
+120} 
+121 
+122void cleanup_module() 
+123{ 
+124    int i; 
+125 
+126    pr_info("%s\n", __func__); 
+127 
+128    /* free irqs */ 
+129    free_irq(button_irqs[0], NULL); 
+130    free_irq(button_irqs[1], NULL); 
+131 
+132    /* turn all LEDs off */ 
+133    for (i = 0; i < ARRAY_SIZE(leds); i++) 
+134        gpio_set_value(leds[i].gpio, 0); 
+135 
+136    /* unregister */ 
+137    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+138    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
+139} 
+140 
+141MODULE_LICENSE("GPL"); 
+142MODULE_DESCRIPTION("Handle some GPIO interrupts");
+

+

+

0.15.3 Bottom Half

+

Suppose you want to do a bunch of stuff inside of an interrupt routine. A common +way to do that without rendering the interrupt unavailable for a significant duration +is to combine it with a tasklet. This pushes the bulk of the work off into the +scheduler. +

The example below modifies the previous example to also run an additional task +when an interrupt is triggered. +

+

+
1/* 
+2 * bottomhalf.c - Top and bottom half interrupt handling 
+3 * 
+4 * Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de) 
+5 * from: 
+6 *    https://github.com/wendlers/rpi-kmod-samples 
+7 * 
+8 *  Press one button to turn on a LED and another to turn it off 
+9 */ 
+10 
+11#include <linux/delay.h> 
+12#include <linux/gpio.h> 
+13#include <linux/interrupt.h> 
+14#include <linux/kernel.h> 
+15#include <linux/module.h> 
+16 
+17static int button_irqs[] = {-1, -1}; 
+18 
+19/* Define GPIOs for LEDs. 
+20   Change the numbers for the GPIO on your board. */ 
+21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+22 
+23/* Define GPIOs for BUTTONS 
+24   Change the numbers for the GPIO on your board. */ 
+25static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+26                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+27 
+28/* Tasklet containing some non-trivial amount of processing */ 
+29static void bottomhalf_tasklet_fn(unsigned long data) 
+30{ 
+31    pr_info("Bottom half tasklet starts\n"); 
+32    /* do something which takes a while */ 
+33    mdelay(500); 
+34    pr_info("Bottom half tasklet ends\n"); 
+35} 
+36 
+37DECLARE_TASKLET(buttontask, bottomhalf_tasklet_fn, 0L); 
+38 
+39/* 
+40 * interrupt function triggered when a button is pressed 
+41 */ 
+42static irqreturn_t button_isr(int irq, void *data) 
+43{ 
+44    /* Do something quickly right now */ 
+45    if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio)) 
+46        gpio_set_value(leds[0].gpio, 1); 
+47    else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio)) 
+48        gpio_set_value(leds[0].gpio, 0); 
+49 
+50    /* Do the rest at leisure via the scheduler */ 
+51    tasklet_schedule(&buttontask); 
+52 
+53    return IRQ_HANDLED; 
+54} 
+55 
+56int init_module() 
+57{ 
+58    int ret = 0; 
+59 
+60    pr_info("%s\n", __func__); 
+61 
+62    /* register LED gpios */ 
+63    ret = gpio_request_array(leds, ARRAY_SIZE(leds)); 
+64 
+65    if (ret) { 
+66        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+67        return ret; 
+68    } 
+69 
+70    /* register BUTTON gpios */ 
+71    ret = gpio_request_array(buttons, ARRAY_SIZE(buttons)); 
+72 
+73    if (ret) { 
+74        pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret); 
+75        goto fail1; 
+76    } 
+77 
+78    pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio)); 
+79 
+80    ret = gpio_to_irq(buttons[0].gpio); 
+81 
+82    if (ret < 0) { 
+83        pr_err("Unable to request IRQ: %d\n", ret); 
+84        goto fail2; 
+85    } 
+86 
+87    button_irqs[0] = ret; 
+88 
+89    pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]); 
+90 
+91    ret = request_irq(button_irqs[0], button_isr, 
+92                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+93                      "gpiomod#button1", NULL); 
+94 
+95    if (ret) { 
+96        pr_err("Unable to request IRQ: %d\n", ret); 
+97        goto fail2; 
+98    } 
+99 
+100 
+101    ret = gpio_to_irq(buttons[1].gpio); 
+102 
+103    if (ret < 0) { 
+104        pr_err("Unable to request IRQ: %d\n", ret); 
+105        goto fail2; 
+106    } 
+107 
+108    button_irqs[1] = ret; 
+109 
+110    pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]); 
+111 
+112    ret = request_irq(button_irqs[1], button_isr, 
+113                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
+114                      "gpiomod#button2", NULL); 
+115 
+116    if (ret) { 
+117        pr_err("Unable to request IRQ: %d\n", ret); 
+118        goto fail3; 
+119    } 
+120 
+121    return 0; 
+122 
+123/* cleanup what has been setup so far */ 
+124fail3: 
+125    free_irq(button_irqs[0], NULL); 
+126 
+127fail2: 
+128    gpio_free_array(buttons, ARRAY_SIZE(leds)); 
+129 
+130fail1: 
+131    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+132 
+133    return ret; 
+134} 
+135 
+136void cleanup_module() 
+137{ 
+138    int i; 
+139 
+140    pr_info("%s\n", __func__); 
+141 
+142    /* free irqs */ 
+143    free_irq(button_irqs[0], NULL); 
+144    free_irq(button_irqs[1], NULL); 
+145 
+146    /* turn all LEDs off */ 
+147    for (i = 0; i < ARRAY_SIZE(leds); i++) 
+148        gpio_set_value(leds[i].gpio, 0); 
+149 
+150    /* unregister */ 
+151    gpio_free_array(leds, ARRAY_SIZE(leds)); 
+152    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
+153} 
+154 
+155MODULE_LICENSE("GPL"); 
+156MODULE_DESCRIPTION("Interrupt with top and bottom half");
+

+

+

0.16 Crypto

+

At the dawn of the internet everybody trusted everybody completely…but that didn’t +work out so well. When this guide was originally written it was a more innocent era +in which almost nobody actually gave a damn about crypto - least of all kernel +developers. That’s certainly no longer the case now. To handle crypto stuff the kernel +has its own API enabling common methods of encryption, decryption and your +favourite hash functions. + + + +

+

+

0.16.1 Hash functions

+

Calculating and checking the hashes of things is a common operation. Here is a +demonstration of how to calculate a sha256 hash within a kernel module. +

+

+
1/* 
+2 *  cryptosha256.c 
+3 */ 
+4#include <crypto/internal/hash.h> 
+5#include <linux/module.h> 
+6 
+7#define SHA256_LENGTH 32 
+8 
+9static void show_hash_result(char *plaintext, char *hash_sha256) 
+10{ 
+11    int i; 
+12    char str[SHA256_LENGTH * 2 + 1]; 
+13 
+14    pr_info("sha256 test for string: \"%s\"\n", plaintext); 
+15    for (i = 0; i < SHA256_LENGTH; i++) 
+16        sprintf(&str[i * 2], "%02x", (unsigned char) hash_sha256[i]); 
+17    str[i * 2] = 0; 
+18    pr_info("%s\n", str); 
+19} 
+20 
+21int cryptosha256_init(void) 
+22{ 
+23    char *plaintext = "This is a test"; 
+24    char hash_sha256[SHA256_LENGTH]; 
+25    struct crypto_shash *sha256; 
+26    struct shash_desc *shash; 
+27 
+28    sha256 = crypto_alloc_shash("sha256", 0, 0); 
+29    if (IS_ERR(sha256)) 
+30        return -1; 
+31 
+32    shash = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(sha256), 
+33                    GFP_KERNEL); 
+34    if (!shash) 
+35        return -ENOMEM; 
+36 
+37    shash->tfm = sha256; 
+38 
+39    if (crypto_shash_init(shash)) 
+40        return -1; 
+41 
+42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
+43        return -1; 
+44 
+45    if (crypto_shash_final(shash, hash_sha256)) 
+46        return -1; 
+47 
+48    kfree(shash); 
+49    crypto_free_shash(sha256); 
+50 
+51    show_hash_result(plaintext, hash_sha256); 
+52 
+53    return 0; 
+54} 
+55 
+56void cryptosha256_exit(void) {} 
+57 
+58module_init(cryptosha256_init); 
+59module_exit(cryptosha256_exit); 
+60 
+61MODULE_DESCRIPTION("sha256 hash test"); 
+62MODULE_LICENSE("GPL");
+

Make and install the module: +

+

+
1make 
+2sudo insmod cryptosha256.ko 
+3dmesg
+

And you should see that the hash was calculated for the test string. +

Finally, remove the test module: +

+

+
1sudo rmmod cryptosha256
+

+

+

0.16.2 Symmetric key encryption

+

Here is an example of symmetrically encrypting a string using the AES algorithm +and a password. +

+

+
1/* 
+2 *  cryptosk.c 
+3 */ 
+4#include <crypto/internal/skcipher.h> 
+5#include <linux/crypto.h> 
+6#include <linux/module.h> 
+7 
+8#define SYMMETRIC_KEY_LENGTH 32 
+9#define CIPHER_BLOCK_SIZE 16 
+10 
+11struct tcrypt_result { 
+12    struct completion completion; 
+13    int err; 
+14}; 
+15 
+16struct skcipher_def { 
+17    struct scatterlist sg; 
+18    struct crypto_skcipher *tfm; 
+19    struct skcipher_request *req; 
+20    struct tcrypt_result result; 
+21    char *scratchpad; 
+22    char *ciphertext; 
+23    char *ivdata; 
+24}; 
+25 
+26static struct skcipher_def sk; 
+27 
+28static void test_skcipher_finish(struct skcipher_def *sk) 
+29{ 
+30    if (sk->tfm) 
+31        crypto_free_skcipher(sk->tfm); 
+32    if (sk->req) 
+33        skcipher_request_free(sk->req); 
+34    if (sk->ivdata) 
+35        kfree(sk->ivdata); 
+36    if (sk->scratchpad) 
+37        kfree(sk->scratchpad); 
+38    if (sk->ciphertext) 
+39        kfree(sk->ciphertext); 
+40} 
+41 
+42static int test_skcipher_result(struct skcipher_def *sk, int rc) 
+43{ 
+44    switch (rc) { 
+45    case 0: 
+46        break; 
+47    case -EINPROGRESS || -EBUSY: 
+48        rc = wait_for_completion_interruptible(&sk->result.completion); 
+49        if (!rc && !sk->result.err) { 
+50            reinit_completion(&sk->result.completion); 
+51            break; 
+52        } 
+53        pr_info("skcipher encrypt returned with %d result %d\n", rc, 
+54                sk->result.err); 
+55        break; 
+56    default: 
+57        pr_info("skcipher encrypt returned with %d result %d\n", rc, 
+58                sk->result.err); 
+59        break; 
+60    } 
+61 
+62    init_completion(&sk->result.completion); 
+63 
+64    return rc; 
+65} 
+66 
+67static void test_skcipher_callback(struct crypto_async_request *req, int error) 
+68{ 
+69    struct tcrypt_result *result = req->data; 
+70    /* int ret; */ 
+71 
+72    if (error == -EINPROGRESS) 
+73        return; 
+74 
+75    result->err = error; 
+76    complete(&result->completion); 
+77    pr_info("Encryption finished successfully\n"); 
+78 
+79    /* decrypt data */ 
+80    /* 
+81    memset((void*)sk.scratchpad, '-', CIPHER_BLOCK_SIZE); 
+82    ret = crypto_skcipher_decrypt(sk.req); 
+83    ret = test_skcipher_result(&sk, ret); 
+84    if (ret) 
+85        return; 
+86 
+87    sg_copy_from_buffer(&sk.sg, 1, sk.scratchpad, CIPHER_BLOCK_SIZE); 
+88    sk.scratchpad[CIPHER_BLOCK_SIZE-1] = 0; 
+89 
+90    pr_info("Decryption request successful\n"); 
+91    pr_info("Decrypted: %s\n", sk.scratchpad); 
+92    */ 
+93} 
+94 
+95static int test_skcipher_encrypt(char *plaintext, 
+96                                 char *password, 
+97                                 struct skcipher_def *sk) 
+98{ 
+99    int ret = -EFAULT; 
+100    unsigned char key[SYMMETRIC_KEY_LENGTH]; 
+101 
+102    if (!sk->tfm) { 
+103        sk->tfm = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0); 
+104        if (IS_ERR(sk->tfm)) { 
+105            pr_info("could not allocate skcipher handle\n"); 
+106            return PTR_ERR(sk->tfm); 
+107        } 
+108    } 
+109 
+110    if (!sk->req) { 
+111        sk->req = skcipher_request_alloc(sk->tfm, GFP_KERNEL); 
+112        if (!sk->req) { 
+113            pr_info("could not allocate skcipher request\n"); 
+114            ret = -ENOMEM; 
+115            goto out; 
+116        } 
+117    } 
+118 
+119    skcipher_request_set_callback(sk->req, CRYPTO_TFM_REQ_MAY_BACKLOG, 
+120                                  test_skcipher_callback, &sk->result); 
+121 
+122    /* clear the key */ 
+123    memset((void *) key, '\0', SYMMETRIC_KEY_LENGTH); 
+124 
+125    /* Use the world's favourite password */ 
+126    sprintf((char *) key, "%s", password); 
+127 
+128    /* AES 256 with given symmetric key */ 
+129    if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) { 
+130        pr_info("key could not be set\n"); 
+131        ret = -EAGAIN; 
+132        goto out; 
+133    } 
+134    pr_info("Symmetric key: %s\n", key); 
+135    pr_info("Plaintext: %s\n", plaintext); 
+136 
+137    if (!sk->ivdata) { 
+138        /* see https://en.wikipedia.org/wiki/Initialization_vector */ 
+139        sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL); 
+140        if (!sk->ivdata) { 
+141            pr_info("could not allocate ivdata\n"); 
+142            goto out; 
+143        } 
+144        get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE); 
+145    } 
+146 
+147    if (!sk->scratchpad) { 
+148        /* The text to be encrypted */ 
+149        sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL); 
+150        if (!sk->scratchpad) { 
+151            pr_info("could not allocate scratchpad\n"); 
+152            goto out; 
+153        } 
+154    } 
+155    sprintf((char *) sk->scratchpad, "%s", plaintext); 
+156 
+157    sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE); 
+158    skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg, CIPHER_BLOCK_SIZE, 
+159                               sk->ivdata); 
+160    init_completion(&sk->result.completion); 
+161 
+162    /* encrypt data */ 
+163    ret = crypto_skcipher_encrypt(sk->req); 
+164    ret = test_skcipher_result(sk, ret); 
+165    if (ret) 
+166        goto out; 
+167 
+168    pr_info("Encryption request successful\n"); 
+169 
+170out: 
+171    return ret; 
+172} 
+173 
+174int cryptoapi_init(void) 
+175{ 
+176    /* The world's favorite password */ 
+177    char *password = "password123"; 
+178 
+179    sk.tfm = NULL; 
+180    sk.req = NULL; 
+181    sk.scratchpad = NULL; 
+182    sk.ciphertext = NULL; 
+183    sk.ivdata = NULL; 
+184 
+185    test_skcipher_encrypt("Testing", password, &sk); 
+186    return 0; 
+187} 
+188 
+189void cryptoapi_exit(void) 
+190{ 
+191    test_skcipher_finish(&sk); 
+192} 
+193 
+194module_init(cryptoapi_init); 
+195module_exit(cryptoapi_exit); 
+196 
+197MODULE_DESCRIPTION("Symmetric key encryption example"); 
+198MODULE_LICENSE("GPL");
+

+

+

0.17 Standardising the interfaces: The Device Model

+

Up to this point we’ve seen all kinds of modules doing all kinds of things, but there +was no consistency in their interfaces with the rest of the kernel. To impose some +consistency such that there is at minimum a standardised way to start, suspend and +resume a device a device model was added. An example is show below, and you can +use this as a template to add your own suspend, resume or other interface +functions. +

+

+
1/* 
+2 *  devicemodel.c 
+3 */ 
+4#include <linux/kernel.h> 
+5#include <linux/module.h> 
+6#include <linux/platform_device.h> 
+7 
+8struct devicemodel_data { 
+9    char *greeting; 
+10    int number; 
+11}; 
+12 
+13static int devicemodel_probe(struct platform_device *dev) 
+14{ 
+15    struct devicemodel_data *pd = 
+16        (struct devicemodel_data *) (dev->dev.platform_data); 
+17 
+18    pr_info("devicemodel probe\n"); 
+19    pr_info("devicemodel greeting: %s; %d\n", pd->greeting, pd->number); 
+20 
+21    /* Your device initialisation code */ 
+22 
+23    return 0; 
+24} 
+25 
+26static int devicemodel_remove(struct platform_device *dev) 
+27{ 
+28    pr_info("devicemodel example removed\n"); 
+29 
+30    /* Your device removal code */ 
+31 
+32    return 0; 
+33} 
+34 
+35static int devicemodel_suspend(struct device *dev) 
+36{ 
+37    pr_info("devicemodel example suspend\n"); 
+38 
+39    /* Your device suspend code */ 
+40 
+41    return 0; 
+42} 
+43 
+44static int devicemodel_resume(struct device *dev) 
+45{ 
+46    pr_info("devicemodel example resume\n"); 
+47 
+48    /* Your device resume code */ 
+49 
+50    return 0; 
+51} 
+52 
+53static const struct dev_pm_ops devicemodel_pm_ops = { 
+54    .suspend = devicemodel_suspend, 
+55    .resume = devicemodel_resume, 
+56    .poweroff = devicemodel_suspend, 
+57    .freeze = devicemodel_suspend, 
+58    .thaw = devicemodel_resume, 
+59    .restore = devicemodel_resume, 
+60}; 
+61 
+62static struct platform_driver devicemodel_driver = { 
+63    .driver = 
+64        { 
+65            .name = "devicemodel_example", 
+66            .owner = THIS_MODULE, 
+67            .pm = &devicemodel_pm_ops, 
+68        }, 
+69    .probe = devicemodel_probe, 
+70    .remove = devicemodel_remove, 
+71}; 
+72 
+73static int devicemodel_init(void) 
+74{ 
+75    int ret; 
+76 
+77    pr_info("devicemodel init\n"); 
+78 
+79    ret = platform_driver_register(&devicemodel_driver); 
+80 
+81    if (ret) { 
+82        pr_err("Unable to register driver\n"); 
+83        return ret; 
+84    } 
+85 
+86    return 0; 
+87} 
+88 
+89static void devicemodel_exit(void) 
+90{ 
+91    pr_info("devicemodel exit\n"); 
+92    platform_driver_unregister(&devicemodel_driver); 
+93} 
+94 
+95MODULE_LICENSE("GPL"); 
+96MODULE_DESCRIPTION("Linux Device Model example"); 
+97 
+98module_init(devicemodel_init); 
+99module_exit(devicemodel_exit);
+ + + +

+

+

0.18 Optimizations

+

+

+

0.18.1 Likely and Unlikely conditions

+

Sometimes you might want your code to run as quickly as possible, especially if +it’s handling an interrupt or doing something which might cause noticible +latency. If your code contains boolean conditions and if you know that the +conditions are almost always likely to evaluate as either true or false, then +you can allow the compiler to optimise for this using the likely and unlikely +macros. +

For example, when allocating memory you’re almost always expecting this to +succeed. +

+

+
1bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx); 
+2if (unlikely(!bvl)) { 
+3  mempool_free(bio, bio_pool); 
+4  bio = NULL; 
+5  goto out; 
+6}
+

When the unlikely macro is used the compiler alters its machine instruction +output so that it continues along the false branch and only jumps if the condition is +true. That avoids flushing the processor pipeline. The opposite happens if you use the +likely macro. +

+

0.19 Common Pitfalls

+

Before I send you on your way to go out into the world and write kernel modules, +there are a few things I need to warn you about. If I fail to warn you and something +bad happens, please report the problem to me for a full refund of the amount I was +paid for your copy of the book. +

+

+

0.19.1 Using standard libraries

+

You can’t do that. In a kernel module you can only use kernel functions, which are +the functions you can see in /proc/kallsyms. +

+

+ + + +

0.19.2 Disabling interrupts

+

You might need to do this for a short time and that is OK, but if you don’t +enable them afterwards, your system will be stuck and you’ll have to power it +off. +

+

+

0.19.3 Sticking your head inside a large carnivore

+

I probably don’t have to warn you about this, but I figured I will anyway, just in +case. +

+

+

0.20 Where To Go From Here?

+

I could easily have squeezed a few more chapters into this book. I could have added a +chapter about creating new file systems, or about adding new protocol stacks (as if +there’s a need for that – you’d have to dig underground to find a protocol stack +not supported by Linux). I could have added explanations of the kernel +mechanisms we haven’t touched upon, such as bootstrapping or the disk +interface. +

However, I chose not to. My purpose in writing this book was to provide initiation +into the mysteries of kernel module programming and to teach the common +techniques for that purpose. For people seriously interested in kernel programming, I +recommend kernelnewbies.org and the Documentation subdirectory within the kernel +source code which isn’t always easy to understand but can be a starting point for +further investigation. Also, as Linus said, the best way to learn the kernel is to read +the source code yourself. +

If you’re interested in more examples of short kernel modules then searching on +sites such as Github and Gitlab is a good way to start, although there is a lot of +duplication of older LKMPG examples which may not compile with newer kernel +versions. You will also be able to find examples of the use of kernel modules to attack +or compromise systems or exfiltrate data and those can be useful for thinking about +how to defend systems and learning about existing security mechanisms within the +kernel. +

I hope I have helped you in your quest to become a better programmer, or at +least to have fun through technology. And, if you do write useful kernel modules, I +hope you publish them under the GPL, so I can use them too. +

If you’d like to contribute to this guide or notice anything glaringly wrong, please +create an issue at https://github.com/sysprog21/lkmpg. +

Happy hacking. +

+ + + \ No newline at end of file diff --git a/lkmpg0x.svg b/lkmpg0x.svg new file mode 100644 index 0000000..bb0fa58 --- /dev/null +++ b/lkmpg0x.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lkmpg1x.svg b/lkmpg1x.svg new file mode 100644 index 0000000..0075f94 --- /dev/null +++ b/lkmpg1x.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file