diff --git a/index.html b/index.html index c09a05c..5f0ed00 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,7 @@

The Linux Kernel Module Programming Guide

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

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

0.11 Blocking Processes and threads

@@ -3221,286 +3230,286 @@ $

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

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

@@ -3516,82 +3525,82 @@ 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> 
+   
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; 
+10static struct { 
+11    struct completion crank_comp; 
+12    struct completion flywheel_comp; 
 13} machine; 
 14 
-15static int machine_crank_thread(void *arg) 
+15static int machine_crank_thread(void *arg) 
 16{ 
-17    pr_info("Turn the crank\n"); 
+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) 
+23static int machine_flywheel_spinup_thread(void *arg) 
 24{ 
 25    wait_for_completion(&machine.crank_comp); 
 26 
-27    pr_info("Flywheel spins up\n"); 
+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) 
+33static int completions_init(void) 
 34{ 
-35    struct task_struct *crank_thread; 
-36    struct task_struct *flywheel_thread; 
+35    struct task_struct *crank_thread; 
+36    struct task_struct *flywheel_thread; 
 37 
-38    pr_info("completions example\n"); 
+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; 
+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; 
+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; 
+55    return 0; 
 56 
 57ERROR_THREAD_2: 
 58    kthread_stop(crank_thread); 
 59ERROR_THREAD_1: 
 60 
-61    return -1; 
+61    return -1; 
 62} 
 63 
-64void completions_exit(void) 
+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"); 
+69    pr_info("completions exit\n"); 
 70} 
 71 
 72module_init(completions_init); 
 73module_exit(completions_exit); 
 74 
-75MODULE_DESCRIPTION("Completions example"); 
-76MODULE_LICENSE("GPL");
+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 @@ -3621,47 +3630,47 @@ might deploy them in userland. This may be all that is needed to avoid collision 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> 
+   
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) 
+11static int example_mutex_init(void) 
 12{ 
-13    int ret; 
+13    int ret; 
 14 
-15    pr_info("example_mutex init\n"); 
+15    pr_info("example_mutex init\n"); 
 16 
 17    ret = mutex_trylock(&mymutex); 
-18    if (ret != 0) { 
-19        pr_info("mutex is locked\n"); 
+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"); 
+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"); 
+25        pr_info("mutex is unlocked\n"); 
+26    } else 
+27        pr_info("Failed to lock\n"); 
 28 
-29    return 0; 
+29    return 0; 
 30} 
 31 
-32static void example_mutex_exit(void) 
+32static void example_mutex_exit(void) 
 33{ 
-34    pr_info("example_mutex exit\n"); 
+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");
+40MODULE_DESCRIPTION("Mutex example"); +41MODULE_LICENSE("GPL");

0.12.2 Spinlocks

@@ -3679,69 +3688,69 @@ they will not be forgotten and will activate when the unlock happens, using the 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> 
+   
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) 
+13static void example_spinlock_static(void) 
 14{ 
-15    unsigned long flags; 
+15    unsigned long flags; 
 16 
 17    spin_lock_irqsave(&sl_static, flags); 
-18    pr_info("Locked static spinlock\n"); 
+18    pr_info("Locked static spinlock\n"); 
 19 
-20    /* Do something or other safely. Because this uses 100% CPU time, this 
-21     * code should take no more than a few milliseconds to run. 
-22     */ 
+20    /* Do something or other safely. Because this uses 100% CPU time, this 
+21     * code should take no more than a few milliseconds to run. 
+22     */ 
 23 
 24    spin_unlock_irqrestore(&sl_static, flags); 
-25    pr_info("Unlocked static spinlock\n"); 
+25    pr_info("Unlocked static spinlock\n"); 
 26} 
 27 
-28static void example_spinlock_dynamic(void) 
+28static void example_spinlock_dynamic(void) 
 29{ 
-30    unsigned long flags; 
+30    unsigned long flags; 
 31 
 32    spin_lock_init(&sl_dynamic); 
 33    spin_lock_irqsave(&sl_dynamic, flags); 
-34    pr_info("Locked dynamic spinlock\n"); 
+34    pr_info("Locked dynamic spinlock\n"); 
 35 
-36    /* Do something or other safely. Because this uses 100% CPU time, this 
-37     * code should take no more than a few milliseconds to run. 
-38     */ 
+36    /* Do something or other safely. Because this uses 100% CPU time, this 
+37     * code should take no more than a few milliseconds to run. 
+38     */ 
 39 
 40    spin_unlock_irqrestore(&sl_dynamic, flags); 
-41    pr_info("Unlocked dynamic spinlock\n"); 
+41    pr_info("Unlocked dynamic spinlock\n"); 
 42} 
 43 
-44static int example_spinlock_init(void) 
+44static int example_spinlock_init(void) 
 45{ 
-46    pr_info("example spinlock started\n"); 
+46    pr_info("example spinlock started\n"); 
 47 
 48    example_spinlock_static(); 
 49    example_spinlock_dynamic(); 
 50 
-51    return 0; 
+51    return 0; 
 52} 
 53 
-54static void example_spinlock_exit(void) 
+54static void example_spinlock_exit(void) 
 55{ 
-56    pr_info("example spinlock exit\n"); 
+56    pr_info("example spinlock exit\n"); 
 57} 
 58 
 59module_init(example_spinlock_init); 
 60module_exit(example_spinlock_exit); 
 61 
-62MODULE_DESCRIPTION("Spinlock example"); 
-63MODULE_LICENSE("GPL");
+62MODULE_DESCRIPTION("Spinlock example"); +63MODULE_LICENSE("GPL");

0.12.3 Read and write locks

@@ -3755,61 +3764,61 @@ 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> 
+   
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) 
+10static void example_read_lock(void) 
 11{ 
-12    unsigned long flags; 
+12    unsigned long flags; 
 13 
 14    read_lock_irqsave(&myrwlock, flags); 
-15    pr_info("Read Locked\n"); 
+15    pr_info("Read Locked\n"); 
 16 
-17    /* Read from something */ 
+17    /* Read from something */ 
 18 
 19    read_unlock_irqrestore(&myrwlock, flags); 
-20    pr_info("Read Unlocked\n"); 
+20    pr_info("Read Unlocked\n"); 
 21} 
 22 
-23static void example_write_lock(void) 
+23static void example_write_lock(void) 
 24{ 
-25    unsigned long flags; 
+25    unsigned long flags; 
 26 
 27    write_lock_irqsave(&myrwlock, flags); 
-28    pr_info("Write Locked\n"); 
+28    pr_info("Write Locked\n"); 
 29 
-30    /* Write to something */ 
+30    /* Write to something */ 
 31 
 32    write_unlock_irqrestore(&myrwlock, flags); 
-33    pr_info("Write Unlocked\n"); 
+33    pr_info("Write Unlocked\n"); 
 34} 
 35 
-36static int example_rwlock_init(void) 
+36static int example_rwlock_init(void) 
 37{ 
-38    pr_info("example_rwlock started\n"); 
+38    pr_info("example_rwlock started\n"); 
 39 
 40    example_read_lock(); 
 41    example_write_lock(); 
 42 
-43    return 0; 
+43    return 0; 
 44} 
 45 
-46static void example_rwlock_exit(void) 
+46static void example_rwlock_exit(void) 
 47{ 
-48    pr_info("example_rwlock exit\n"); 
+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");
+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) @@ -3825,80 +3834,80 @@ and was not 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> 
+   
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') 
+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) 
+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 */ 
+22    /* subtract one */ 
 23    atomic_dec(&debbie); 
 24 
 25    atomic_add(7, &debbie); 
 26 
-27    /* add one */ 
+27    /* add one */ 
 28    atomic_inc(&debbie); 
 29 
-30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
+30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
 31            atomic_read(&debbie)); 
 32} 
 33 
-34static void atomic_bitwise(void) 
+34static void atomic_bitwise(void) 
 35{ 
-36    unsigned long word = 0; 
+36    unsigned long word = 0; 
 37 
-38    pr_info("Bits 0: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+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)); 
+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)); 
+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)); 
+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)); 
+52    pr_info("Bits 5: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
 53} 
 54 
-55static int example_atomic_init(void) 
+55static int example_atomic_init(void) 
 56{ 
-57    pr_info("example_atomic started\n"); 
+57    pr_info("example_atomic started\n"); 
 58 
 59    atomic_add_subtract(); 
 60    atomic_bitwise(); 
 61 
-62    return 0; 
+62    return 0; 
 63} 
 64 
-65static void example_atomic_exit(void) 
+65static void example_atomic_exit(void) 
 66{ 
-67    pr_info("example_atomic exit\n"); 
+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");
+73MODULE_DESCRIPTION("Atomic operations example"); +74MODULE_LICENSE("GPL");
@@ -3922,83 +3931,83 @@ 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 
-3 * it is through X11, telnet, etc.  We do this by printing the string to the 
-4 * tty 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 */ 
+   
1/* 
+2 * print_string.c - Send output to the tty we're running on, regardless if 
+3 * it is through X11, telnet, etc.  We do this by printing the string to the 
+4 * tty 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 
-12static void print_string(char *str) 
+12static void print_string(char *str) 
 13{ 
-14    struct tty_struct *my_tty; 
-15    const struct tty_operations *ttyops; 
+14    struct tty_struct *my_tty; 
+15    const struct tty_operations *ttyops; 
 16 
-17    /* The tty for the current task, for 2.6.6+ kernels */ 
+17    /* The tty for the current task, for 2.6.6+ kernels */ 
 18    my_tty = get_current_tty(); 
 19    ttyops = my_tty->driver->ops; 
 20 
-21    /* If my_tty is NULL, the current task has no tty you can print to (i.e., 
-22     * if it is a daemon). If so, there is nothing we can do. 
-23     */ 
-24    if (my_tty) { 
-25        /* my_tty->driver is a struct which holds the tty's functions, 
-26         * one of which (write) is used to write strings to the tty. 
-27         * It can be used to take a string either from the user's or 
-28         * kernel's memory segment. 
-29         * 
-30         * The function's 1st parameter is the tty to write to, because the 
-31         * same function would normally be used for all tty's of a certain 
-32         * type. 
-33         * The 2nd parameter is a pointer to a string. 
-34         * The 3rd parameter is the length of the string. 
-35         * 
-36         * As you will see below, sometimes it's necessary to use 
-37         * preprocessor stuff to create code that works for different 
-38         * kernel versions. The (naive) approach we've taken here does not 
-39         * scale well. The right way to deal with this is described in 
-40         * section 2 of 
-41         * linux/Documentation/SubmittingPatches 
-42         */ 
-43        (ttyops->write)(my_tty,       /* The tty itself */ 
-44                        str,          /* String                 */ 
-45                        strlen(str)); /* Length */ 
+21    /* If my_tty is NULL, the current task has no tty you can print to (i.e., 
+22     * if it is a daemon). If so, there is nothing we can do. 
+23     */ 
+24    if (my_tty) { 
+25        /* my_tty->driver is a struct which holds the tty's functions, 
+26         * one of which (write) is used to write strings to the tty. 
+27         * It can be used to take a string either from the user's or 
+28         * kernel's memory segment. 
+29         * 
+30         * The function's 1st parameter is the tty to write to, because the 
+31         * same function would normally be used for all tty's of a certain 
+32         * type. 
+33         * The 2nd parameter is a pointer to a string. 
+34         * The 3rd parameter is the length of the string. 
+35         * 
+36         * As you will see below, sometimes it's necessary to use 
+37         * preprocessor stuff to create code that works for different 
+38         * kernel versions. The (naive) approach we've taken here does not 
+39         * scale well. The right way to deal with this is described in 
+40         * section 2 of 
+41         * linux/Documentation/SubmittingPatches 
+42         */ 
+43        (ttyops->write)(my_tty,       /* The tty itself */ 
+44                        str,          /* String                 */ 
+45                        strlen(str)); /* Length */ 
 46 
-47        /* ttys were originally hardware devices, which (usually) strictly 
-48         * followed the ASCII standard. In ASCII, to move to a new line you 
-49         * need two characters, a carriage return and a line feed. On Unix, 
-50         * the ASCII line feed is used for both purposes - so we can not 
-51         * just use \n, because it would not have a carriage return and the 
-52         * next line will start at the column right after the line feed. 
-53         * 
-54         * This is why text files are different between Unix and MS Windows. 
-55         * In CP/M and derivatives, like MS-DOS and MS Windows, the ASCII 
-56         * standard was strictly adhered to, and therefore a newline requirs 
-57         * both a LF and a CR. 
-58         */ 
-59        (ttyops->write)(my_tty, "\015\012", 2); 
+47        /* ttys were originally hardware devices, which (usually) strictly 
+48         * followed the ASCII standard. In ASCII, to move to a new line you 
+49         * need two characters, a carriage return and a line feed. On Unix, 
+50         * the ASCII line feed is used for both purposes - so we can not 
+51         * just use \n, because it would not have a carriage return and the 
+52         * next line will start at the column right after the line feed. 
+53         * 
+54         * This is why text files are different between Unix and MS Windows. 
+55         * In CP/M and derivatives, like MS-DOS and MS Windows, the ASCII 
+56         * standard was strictly adhered to, and therefore a newline requirs 
+57         * both a LF and a CR. 
+58         */ 
+59        (ttyops->write)(my_tty, "\015\012", 2); 
 60    } 
 61} 
 62 
-63static int __init print_string_init(void) 
+63static int __init print_string_init(void) 
 64{ 
-65    print_string("The module has been inserted.  Hello world!"); 
-66    return 0; 
+65    print_string("The module has been inserted.  Hello world!"); 
+66    return 0; 
 67} 
 68 
-69static void __exit print_string_exit(void) 
+69static void __exit print_string_exit(void) 
 70{ 
-71    print_string("The module has been removed.  Farewell world!"); 
+71    print_string("The module has been removed.  Farewell world!"); 
 72} 
 73 
 74module_init(print_string_init); 
 75module_exit(print_string_exit); 
 76 
-77MODULE_LICENSE("GPL");
+77MODULE_LICENSE("GPL");

0.13.2 Flashing keyboard LEDs

@@ -4012,49 +4021,49 @@ file. loaded, starts blinking the keyboard LEDs until it is unloaded.

-
1/* 
-2 * kbleds.c - Blink keyboard leds until the module is unloaded. 
-3 */ 
+   
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 */ 
+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 */ 
+12#include <linux/console_struct.h> /* For vc_cons */ 
 13 
-14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
+14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
 15 
-16struct timer_list my_timer; 
-17struct tty_driver *my_driver; 
-18char kbledstatus = 0; 
+16struct timer_list my_timer; 
+17struct tty_driver *my_driver; 
+18char kbledstatus = 0; 
 19 
-20#define BLINK_DELAY HZ / 5 
-21#define ALL_LEDS_ON 0x07 
-22#define RESTORE_LEDS 0xFF 
+20#define BLINK_DELAY HZ / 5 
+21#define ALL_LEDS_ON 0x07 
+22#define RESTORE_LEDS 0xFF 
 23 
-24/* Function my_timer_func blinks the keyboard LEDs periodically by invoking 
-25 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
-26 * terminal ioctl operations, please see file: 
-27 *   drivers/tty/vt/vt_ioctl.c, function vt_ioctl(). 
-28 * 
-29 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
-30 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
-31 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
-32 * the LEDs reflect the actual keyboard status).  To learn more on this, 
-33 * please see file: drivers/tty/vt/keyboard.c, function setledstate(). 
-34 */ 
+24/* Function my_timer_func blinks the keyboard LEDs periodically by invoking 
+25 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
+26 * terminal ioctl operations, please see file: 
+27 *   drivers/tty/vt/vt_ioctl.c, function vt_ioctl(). 
+28 * 
+29 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
+30 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
+31 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
+32 * the LEDs reflect the actual keyboard status).  To learn more on this, 
+33 * please see file: drivers/tty/vt/keyboard.c, function setledstate(). 
+34 */ 
 35 
-36static void my_timer_func(unsigned long ptr) 
+36static void my_timer_func(unsigned long ptr) 
 37{ 
-38    unsigned long *pstatus = (unsigned long *) ptr; 
-39    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
+38    unsigned long *pstatus = (unsigned long *) ptr; 
+39    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
 40 
-41    if (*pstatus == ALL_LEDS_ON) 
+41    if (*pstatus == ALL_LEDS_ON) 
 42        *pstatus = RESTORE_LEDS; 
-43    else 
+43    else 
 44        *pstatus = ALL_LEDS_ON; 
 45 
 46    (my_driver->ops->ioctl)(t, KDSETLED, *pstatus); 
@@ -4063,35 +4072,35 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
 49    add_timer(&my_timer); 
 50} 
 51 
-52static int __init kbleds_init(void) 
+52static int __init kbleds_init(void) 
 53{ 
-54    int i; 
+54    int i; 
 55 
-56    pr_info("kbleds: loading\n"); 
-57    pr_info("kbleds: fgconsole is %x\n", fg_console); 
-58    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
-59        if (!vc_cons[i].d) 
-60            break; 
-61        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
-62                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
+56    pr_info("kbleds: loading\n"); 
+57    pr_info("kbleds: fgconsole is %x\n", fg_console); 
+58    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
+59        if (!vc_cons[i].d) 
+60            break; 
+61        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
+62                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
 63    } 
-64    pr_info("kbleds: finished scanning consoles\n"); 
+64    pr_info("kbleds: finished scanning consoles\n"); 
 65 
 66    my_driver = vc_cons[fg_console].d->port.tty->driver; 
-67    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
+67    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
 68 
-69    /* Set up the LED blink timer the first time. */ 
-70    timer_setup(&my_timer, (void *) &my_timer_func, 
-71                (unsigned long) &kbledstatus); 
+69    /* Set up the LED blink timer the first time. */ 
+70    timer_setup(&my_timer, (void *) &my_timer_func, 
+71                (unsigned long) &kbledstatus); 
 72    my_timer.expires = jiffies + BLINK_DELAY; 
 73    add_timer(&my_timer); 
 74 
-75    return 0; 
+75    return 0; 
 76} 
 77 
-78static void __exit kbleds_cleanup(void) 
+78static void __exit kbleds_cleanup(void) 
 79{ 
-80    pr_info("kbleds: unloading...\n"); 
+80    pr_info("kbleds: unloading...\n"); 
 81    del_timer(&my_timer); 
 82    (my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, 
 83                            RESTORE_LEDS); 
@@ -4100,7 +4109,7 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
 86module_init(kbleds_init); 
 87module_exit(kbleds_cleanup); 
 88 
-89MODULE_LICENSE("GPL");
+89MODULE_LICENSE("GPL");
@@ -4137,43 +4146,50 @@ better suited to running multiple things in a sequence.
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> 
+   
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} 
+9/* Macro DECLARE_TASKLET_OLD exists for compatibiity. 
+10 * See https://lwn.net/Articles/830964/ 
+11 */ 
+12#ifndef DECLARE_TASKLET_OLD 
+13#define DECLARE_TASKLET_OLD(arg1, arg2) DECLARE_TASKLET(arg1, arg2, 0L) 
+14#endif 
 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");
+16static void tasklet_fn(unsigned long data) +17{ +18    pr_info("Example tasklet starts\n"); +19    mdelay(5000); +20    pr_info("Example tasklet ends\n"); +21} +22 +23DECLARE_TASKLET_OLD(mytask, tasklet_fn); +24 +25static int example_tasklet_init(void) +26{ +27    pr_info("tasklet example init\n"); +28    tasklet_schedule(&mytask); +29    mdelay(200); +30    pr_info("Example tasklet init continues...\n"); +31    return 0; +32} +33 +34static void example_tasklet_exit(void) +35{ +36    pr_info("tasklet example exit\n"); +37    tasklet_kill(&mytask); +38} +39 +40module_init(example_tasklet_init); +41module_exit(example_tasklet_exit); +42 +43MODULE_DESCRIPTION("Tasklet example"); +44MODULE_LICENSE("GPL");

So with this example loaded dmesg should show: @@ -4186,39 +4202,51 @@ Example tasklet starts Example tasklet init continues... Example tasklet ends

-

-

+

Although tasklet is easy to use, it comes with several defators, and developers are +discussing about getting rid of tasklet in linux kernel. The tasklet callback +runs in atomic context, inside a software interrupt, meaning that it cannot +sleep or access user-space data, so not all work can be done in a tasklet +handler. Also, the kernel only allows one instance of any given tasklet to be +running at any given time; multiple different tasklet callbacks can run in +parallel. +

In recent kernels, tasklets can be replaced by workqueues, timers, or threaded +interrupts.1 +While the removal of tasklets remains a longer-term goal, the current kernel contains more +than a hundred uses of tasklets. Now developers are proceeding with the API changes and +the macro DECLARE_TASKLET_OLD + exists for compatibiity. For further information, see https://lwn.net/Articles/830964/. +

0.14.2 Work queues

-

To add a task to the scheduler we can use a workqueue. The kernel then uses the +

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> 
+   
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; 
+8static struct workqueue_struct *queue = NULL; 
+9static struct work_struct work; 
 10 
-11static void work_handler(struct work_struct *data) 
+11static void work_handler(struct work_struct *data) 
 12{ 
-13    pr_info("work handler function.\n"); 
+13    pr_info("work handler function.\n"); 
 14} 
 15 
-16static int __init sched_init(void) 
+16static int __init sched_init(void) 
 17{ 
-18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
+18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
 19    INIT_WORK(&work, work_handler); 
 20    schedule_work(&work); 
 21 
-22    return 0; 
+22    return 0; 
 23} 
 24 
-25static void __exit sched_exit(void) 
+25static void __exit sched_exit(void) 
 26{ 
 27    destroy_workqueue(queue); 
 28} 
@@ -4226,38 +4254,38 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
 30module_init(sched_init); 
 31module_exit(sched_exit); 
 32 
-33MODULE_LICENSE("GPL"); 
-34MODULE_DESCRIPTION("Workqueue example");
-

+33MODULE_LICENSE("GPL"); +34MODULE_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 have done as a +

Except for the last chapter, everything we did in the kernel so far we have 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 is not 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 +

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 order 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 do not read their information when available, it is lost. - - - -

Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There +

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 is better to declare an interrupt handler to be long. -

When the CPU receives an interrupt, it stops whatever it is doing (unless it is +

When the CPU receives an interrupt, it stops whatever it is doing (unless it is 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 @@ -4269,10 +4297,10 @@ 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 +

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 +

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 @@ -4282,11 +4310,14 @@ 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 are 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 is not enough to know if a certain IRQs has happened, it’s also important to know what CPU(s) it was for. People still interested in more details, might want to refer to "APIC" now. -

This function receives the IRQ number, the name of the function, +

This function receives the IRQ number, the name of the function, flags, a name for /proc/interrupts and a parameter to be passed 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 @@ -4296,132 +4327,129 @@ How many IRQs there are is hardware-dependent. The flags can include SA_INTERRUPT to indicate this is a fast interrupt. This function will only succeed if there is not already a handler on this IRQ, or if you are both willing to share. - - - -

+

0.15.2 Detecting button presses

-

Many popular single board computers, such as Raspberry Pi or Beagleboards, have a +

Many popular single board computers, such as Raspberry Pi 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 is better for the input to trigger the CPU to then run a particular handling function. -

Here is an example where buttons are connected to GPIO numbers 17 and 18 and +

Here is 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 */ 
+   
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> 
+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}; 
+16static int button_irqs[] = {-1, -1}; 
 17 
-18/* Define GPIOs for LEDs. 
-19 * TODO: Change the numbers for the GPIO on your board. 
-20 */ 
-21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+18/* Define GPIOs for LEDs. 
+19 * TODO: Change the numbers for the GPIO on your board. 
+20 */ 
+21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
 22 
-23/* Define GPIOs for BUTTONS 
-24 * TODO: Change the numbers for the GPIO on your board. 
-25 */ 
-26static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
-27                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+23/* Define GPIOs for BUTTONS 
+24 * TODO: Change the numbers for the GPIO on your board. 
+25 */ 
+26static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+27                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
 28 
-29/* interrupt function triggered when a button is pressed. */ 
-30static irqreturn_t button_isr(int irq, void *data) 
+29/* interrupt function triggered when a button is pressed. */ 
+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)) 
+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)) 
+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; 
+39    return IRQ_HANDLED; 
 40} 
 41 
-42static int __init intrpt_init(void) 
+42static int __init intrpt_init(void) 
 43{ 
-44    int ret = 0; 
+44    int ret = 0; 
 45 
-46    pr_info("%s\n", __func__); 
+46    pr_info("%s\n", __func__); 
 47 
-48    /* register LED gpios */ 
+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; 
+51    if (ret) { 
+52        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+53        return ret; 
 54    } 
 55 
-56    /* register BUTTON gpios */ 
+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; 
+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)); 
+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; 
+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]); 
+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); 
+79                      "gpiomod#button1", NULL); 
 80 
-81    if (ret) { 
-82        pr_err("Unable to request IRQ: %d\n", ret); 
-83        goto fail2; 
+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; 
+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]); 
+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); 
+100                      "gpiomod#button2", NULL); 
 101 
-102    if (ret) { 
-103        pr_err("Unable to request IRQ: %d\n", ret); 
-104        goto fail3; 
+102    if (ret) { 
+103        pr_err("Unable to request IRQ: %d\n", ret); 
+104        goto fail3; 
 105    } 
 106 
-107    return 0; 
+107    return 0; 
 108 
-109/* cleanup what has been setup so far */ 
+109/* cleanup what has been setup so far */ 
 110fail3: 
 111    free_irq(button_irqs[0], NULL); 
 112 
@@ -4431,24 +4459,24 @@ appropriate for your board.
 116fail1: 
 117    gpio_free_array(leds, ARRAY_SIZE(leds)); 
 118 
-119    return ret; 
+119    return ret; 
 120} 
 121 
-122static void __exit intrpt_exit(void) 
+122static void __exit intrpt_exit(void) 
 123{ 
-124    int i; 
+124    int i; 
 125 
-126    pr_info("%s\n", __func__); 
+126    pr_info("%s\n", __func__); 
 127 
-128    /* free irqs */ 
+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++) 
+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 */ 
+136    /* unregister */ 
 137    gpio_free_array(leds, ARRAY_SIZE(leds)); 
 138    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
 139} 
@@ -4456,480 +4484,492 @@ appropriate for your board.
 141module_init(intrpt_init); 
 142module_exit(intrpt_exit); 
 143 
-144MODULE_LICENSE("GPL"); 
-145MODULE_DESCRIPTION("Handle some GPIO interrupts");
-

+144MODULE_LICENSE("GPL"); +145MODULE_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 +

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 +

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

+142    return ret; +143} +144 +145static void __exit bottomhalf_exit(void) +146{ +147    int i; +148 +149    pr_info("%s\n", __func__); +150 +151    /* free irqs */ +152    free_irq(button_irqs[0], NULL); +153    free_irq(button_irqs[1], NULL); +154 +155    /* turn all LEDs off */ +156    for (i = 0; i < ARRAY_SIZE(leds); i++) +157        gpio_set_value(leds[i].gpio, 0); +158 +159    /* unregister */ +160    gpio_free_array(leds, ARRAY_SIZE(leds)); +161    gpio_free_array(buttons, ARRAY_SIZE(buttons)); +162} +163 +164module_init(bottomhalf_init); +165module_exit(bottomhalf_exit); +166 +167MODULE_LICENSE("GPL"); +168MODULE_DESCRIPTION("Interrupt with top and bottom half");

+

0.16 Crypto

-

At the dawn of the internet, everybody trusted everybody completely…but that did +

At the dawn of the internet, everybody trusted everybody completely…but that did not 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 is 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 +

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> 
+   
1/* 
+2 * cryptosha256.c 
+3 */ 
+4#include <crypto/internal/hash.h> 
+5#include <linux/module.h> 
 6 
-7#define SHA256_LENGTH 32 
+7#define SHA256_LENGTH 32 
 8 
-9static void show_hash_result(char *plaintext, char *hash_sha256) 
+9static void show_hash_result(char *plaintext, char *hash_sha256) 
 10{ 
-11    int i; 
-12    char str[SHA256_LENGTH * 2 + 1]; 
+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]); 
+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); 
+18    pr_info("%s\n", str); 
 19} 
 20 
-21int cryptosha256_init(void) 
+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; 
+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; 
+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), 
+32    shash = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(sha256), 
 33                    GFP_KERNEL); 
-34    if (!shash) 
-35        return -ENOMEM; 
+34    if (!shash) 
+35        return -ENOMEM; 
 36 
 37    shash->tfm = sha256; 
 38 
-39    if (crypto_shash_init(shash)) 
-40        return -1; 
+39    if (crypto_shash_init(shash)) 
+40        return -1; 
 41 
-42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
-43        return -1; 
+42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
+43        return -1; 
 44 
-45    if (crypto_shash_final(shash, hash_sha256)) 
-46        return -1; 
+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; 
+53    return 0; 
 54} 
 55 
-56void cryptosha256_exit(void) {} 
+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: +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: +

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 +

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

+169    pr_info("Encryption request successful\n"); +170 +171out: +172    return ret; +173} +174 +175int cryptoapi_init(void) +176{ +177    /* The world's favorite password */ +178    char *password = "password123"; +179 +180    sk.tfm = NULL; +181    sk.req = NULL; +182    sk.scratchpad = NULL; +183    sk.ciphertext = NULL; +184    sk.ivdata = NULL; +185 +186    test_skcipher_encrypt("Testing", password, &sk); +187    return 0; +188} +189 +190void cryptoapi_exit(void) +191{ +192    test_skcipher_finish(&sk); +193} +194 +195module_init(cryptoapi_init); +196module_exit(cryptoapi_exit); +197 +198MODULE_DESCRIPTION("Symmetric key encryption example"); +199MODULE_LICENSE("GPL");

+

0.17 Standardizing the interfaces: The Device Model

-

Up to this point we have seen all kinds of modules doing all kinds of things, but there +

Up to this point we have 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 standardized way to start, suspend and resume a device a device model was added. An example is shown below, and you can @@ -4937,59 +4977,59 @@ 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> 
+   
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; 
+8struct devicemodel_data { 
+9    char *greeting; 
+10    int number; 
 11}; 
 12 
-13static int devicemodel_probe(struct platform_device *dev) 
+13static int devicemodel_probe(struct platform_device *dev) 
 14{ 
-15    struct devicemodel_data *pd = 
-16        (struct devicemodel_data *) (dev->dev.platform_data); 
+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); 
+18    pr_info("devicemodel probe\n"); 
+19    pr_info("devicemodel greeting: %s; %d\n", pd->greeting, pd->number); 
 20 
-21    /* Your device initialization code */ 
+21    /* Your device initialization code */ 
 22 
-23    return 0; 
+23    return 0; 
 24} 
 25 
-26static int devicemodel_remove(struct platform_device *dev) 
+26static int devicemodel_remove(struct platform_device *dev) 
 27{ 
-28    pr_info("devicemodel example removed\n"); 
+28    pr_info("devicemodel example removed\n"); 
 29 
-30    /* Your device removal code */ 
+30    /* Your device removal code */ 
 31 
-32    return 0; 
+32    return 0; 
 33} 
 34 
-35static int devicemodel_suspend(struct device *dev) 
+35static int devicemodel_suspend(struct device *dev) 
 36{ 
-37    pr_info("devicemodel example suspend\n"); 
+37    pr_info("devicemodel example suspend\n"); 
 38 
-39    /* Your device suspend code */ 
+39    /* Your device suspend code */ 
 40 
-41    return 0; 
+41    return 0; 
 42} 
 43 
-44static int devicemodel_resume(struct device *dev) 
+44static int devicemodel_resume(struct device *dev) 
 45{ 
-46    pr_info("devicemodel example resume\n"); 
+46    pr_info("devicemodel example resume\n"); 
 47 
-48    /* Your device resume code */ 
+48    /* Your device resume code */ 
 49 
-50    return 0; 
+50    return 0; 
 51} 
 52 
-53static const struct dev_pm_ops devicemodel_pm_ops = { 
+53static const struct dev_pm_ops devicemodel_pm_ops = { 
 54    .suspend = devicemodel_suspend, 
 55    .resume = devicemodel_resume, 
 56    .poweroff = devicemodel_suspend, 
@@ -4998,10 +5038,10 @@ functions.
 59    .restore = devicemodel_resume, 
 60}; 
 61 
-62static struct platform_driver devicemodel_driver = { 
+62static struct platform_driver devicemodel_driver = { 
 63    .driver = 
 64        { 
-65            .name = "devicemodel_example", 
+65            .name = "devicemodel_example", 
 66            .owner = THIS_MODULE, 
 67            .pm = &devicemodel_pm_ops, 
 68        }, 
@@ -5009,43 +5049,40 @@ functions.
 70    .remove = devicemodel_remove, 
 71}; 
 72 
-73static int devicemodel_init(void) 
+73static int devicemodel_init(void) 
 74{ 
-75    int ret; 
+75    int ret; 
 76 
-77    pr_info("devicemodel init\n"); 
+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; 
+81    if (ret) { 
+82        pr_err("Unable to register driver\n"); 
+83        return ret; 
 84    } 
 85 
-86    return 0; 
+86    return 0; 
 87} 
 88 
-89static void devicemodel_exit(void) 
+89static void devicemodel_exit(void) 
 90{ 
-91    pr_info("devicemodel exit\n"); 
+91    pr_info("devicemodel exit\n"); 
 92    platform_driver_unregister(&devicemodel_driver); 
 93} 
 94 
 95module_init(devicemodel_init); 
 96module_exit(devicemodel_exit); 
 97 
-98MODULE_LICENSE("GPL"); 
-99MODULE_DESCRIPTION("Linux Device Model example");
- - - -

+98MODULE_LICENSE("GPL"); +99MODULE_DESCRIPTION("Linux Device Model example");

+

0.18 Optimizations

-

+

0.18.1 Likely and Unlikely conditions

-

Sometimes you might want your code to run as quickly as possible, +

Sometimes you might want your code to run as quickly as possible, especially if it is handling an interrupt or doing something which might cause noticeable latency. If your code contains boolean conditions and if you know that the conditions are almost always likely to evaluate as either @@ -5059,56 +5096,63 @@ to succeed.

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

When the unlikely + + + +

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

-

+

0.19.1 Using standard libraries

-

You can not do that. In a kernel module, you can only use kernel functions which are +

You can not 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 do not enable +

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

+

0.20 Where To Go From Here?

-

For people seriously interested in kernel programming, I recommend kernelnewbies.org +

For people seriously interested in kernel programming, I recommend kernelnewbies.org and the Documentation subdirectory within the kernel source code which is not always easy to understand but can be a starting point for further investigation. Also, as Linus Torvalds said, the best way to learn the kernel is to read the source code yourself. -

If you are interested in more examples of short kernel modules then searching on +

If you are 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 + + + +

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 would like to contribute to this guide or notice anything glaringly wrong, +

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

Happy hacking! +

Happy hacking!

- +

1The goal of threaded interrupts is to push more of the work to separate threads, so that the +minimum needed for acknowledging an interrupt is reduced, and therefore the time spent handling +the interrupt (where it can’t handle any other interrupts at the same time) is reduced. See +https://lwn.net/Articles/302043/

+ \ No newline at end of file diff --git a/lkmpg-for-ht.css b/lkmpg-for-ht.css index e7c4bf1..955b0e9 100644 --- a/lkmpg-for-ht.css +++ b/lkmpg-for-ht.css @@ -12,6 +12,8 @@ .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;} .ecrm-0500{font-size:50%;} .tctt-1000{font-family: monospace,monospace;} .tctt-1000{font-family: monospace,monospace;} @@ -23,6 +25,8 @@ .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;} .ectt-0800{font-size:80%; font-family: monospace,monospace;} .ectt-0800{ font-family: monospace,monospace;} .ectt-0800{ font-family: monospace,monospace;} @@ -31,6 +35,9 @@ .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;} +.ecrm-0800{font-size:80%;} .tctt-0800{font-size:80%;font-family: monospace,monospace;} .tctt-0800{font-family: monospace,monospace;} .ecbx-1000{ font-weight: bold;} @@ -41,6 +48,9 @@ .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;} +.ecrm-0900{font-size:90%;} p{margin-top:0;margin-bottom:0} p.indent{text-indent:0;} p + p{margin-top:1em;} @@ -90,6 +100,8 @@ div.flushleft {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.footnotes{border-top:solid 1px black; border-bottom:solid 1px black; padding-bottom:1ex; padding-top:0.5ex; margin-right:15%; margin-top:2ex; font-style:italic; font-size:85%;} +div.footnotes p{margin-top:0; margin-bottom:0; text-indent:0;} 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;} @@ -148,7 +160,6 @@ 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;} @@ -1821,110 +1832,120 @@ span#textcolor1364{color:rgb(0,0,255)} span#textcolor1365{color:rgb(0,127,0)} span#textcolor1366{color:rgb(0,0,255)} span#textcolor1367{color:rgb(0,127,0)} -span#textcolor1368{color:rgb(43,145,175)} -span#textcolor1369{color:rgb(43,145,175)} -span#textcolor1370{color:rgb(43,145,175)} -span#textcolor1371{color:rgb(43,145,175)} +span#textcolor1368{color:rgb(0,127,0)} +span#textcolor1369{color:rgb(0,127,0)} +span#textcolor1370{color:rgb(0,0,255)} +span#textcolor1371{color:rgb(0,0,255)} span#textcolor1372{color:rgb(0,127,0)} span#textcolor1373{color:rgb(0,0,255)} -span#textcolor1374{color:rgb(43,145,175)} -span#textcolor1375{color:rgb(43,145,175)} +span#textcolor1374{color:rgb(0,0,255)} +span#textcolor1375{color:rgb(0,0,255)} span#textcolor1376{color:rgb(0,127,0)} -span#textcolor1377{color:rgb(0,127,0)} -span#textcolor1378{color:rgb(0,127,0)} -span#textcolor1379{color:rgb(0,127,0)} -span#textcolor1380{color:rgb(0,127,0)} -span#textcolor1381{color:rgb(0,127,0)} +span#textcolor1377{color:rgb(0,0,255)} +span#textcolor1378{color:rgb(43,145,175)} +span#textcolor1379{color:rgb(43,145,175)} +span#textcolor1380{color:rgb(43,145,175)} +span#textcolor1381{color:rgb(43,145,175)} 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(43,145,175)} -span#textcolor1389{color:rgb(43,145,175)} +span#textcolor1383{color:rgb(0,0,255)} +span#textcolor1384{color:rgb(43,145,175)} +span#textcolor1385{color:rgb(43,145,175)} +span#textcolor1386{color:rgb(0,127,0)} +span#textcolor1387{color:rgb(0,127,0)} +span#textcolor1388{color:rgb(0,127,0)} +span#textcolor1389{color:rgb(0,127,0)} span#textcolor1390{color:rgb(0,127,0)} span#textcolor1391{color:rgb(0,127,0)} span#textcolor1392{color:rgb(0,127,0)} span#textcolor1393{color:rgb(0,127,0)} span#textcolor1394{color:rgb(0,127,0)} 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,127,0)} -span#textcolor1400{color:rgb(43,145,175)} -span#textcolor1401{color:rgb(0,0,255)} -span#textcolor1402{color:rgb(43,145,175)} -span#textcolor1403{color:rgb(43,145,175)} -span#textcolor1404{color:rgb(43,145,175)} -span#textcolor1405{color:rgb(43,145,175)} -span#textcolor1406{color:rgb(43,145,175)} +span#textcolor1396{color:rgb(0,0,255)} +span#textcolor1397{color:rgb(43,145,175)} +span#textcolor1398{color:rgb(43,145,175)} +span#textcolor1399{color:rgb(43,145,175)} +span#textcolor1400{color:rgb(0,127,0)} +span#textcolor1401{color:rgb(0,127,0)} +span#textcolor1402{color:rgb(0,127,0)} +span#textcolor1403{color:rgb(0,127,0)} +span#textcolor1404{color:rgb(0,127,0)} +span#textcolor1405{color:rgb(0,127,0)} +span#textcolor1406{color:rgb(0,127,0)} span#textcolor1407{color:rgb(0,127,0)} -span#textcolor1408{color:rgb(163,20,20)} -span#textcolor1409{color:rgb(0,0,255)} -span#textcolor1410{color:rgb(163,20,20)} +span#textcolor1408{color:rgb(0,127,0)} +span#textcolor1409{color:rgb(0,127,0)} +span#textcolor1410{color:rgb(43,145,175)} span#textcolor1411{color:rgb(0,0,255)} -span#textcolor1412{color:rgb(163,20,20)} -span#textcolor1413{color:rgb(163,20,20)} -span#textcolor1414{color:rgb(163,20,20)} -span#textcolor1415{color:rgb(0,127,0)} -span#textcolor1416{color:rgb(0,127,0)} +span#textcolor1412{color:rgb(43,145,175)} +span#textcolor1413{color:rgb(43,145,175)} +span#textcolor1414{color:rgb(43,145,175)} +span#textcolor1415{color:rgb(43,145,175)} +span#textcolor1416{color:rgb(43,145,175)} span#textcolor1417{color:rgb(0,127,0)} -span#textcolor1418{color:rgb(0,0,255)} +span#textcolor1418{color:rgb(163,20,20)} span#textcolor1419{color:rgb(0,0,255)} -span#textcolor1420{color:rgb(43,145,175)} -span#textcolor1421{color:rgb(43,145,175)} -span#textcolor1422{color:rgb(43,145,175)} -span#textcolor1423{color:rgb(43,145,175)} -span#textcolor1424{color:rgb(43,145,175)} -span#textcolor1425{color:rgb(43,145,175)} -span#textcolor1426{color:rgb(43,145,175)} -span#textcolor1427{color:rgb(43,145,175)} +span#textcolor1420{color:rgb(163,20,20)} +span#textcolor1421{color:rgb(0,0,255)} +span#textcolor1422{color:rgb(163,20,20)} +span#textcolor1423{color:rgb(163,20,20)} +span#textcolor1424{color:rgb(163,20,20)} +span#textcolor1425{color:rgb(0,127,0)} +span#textcolor1426{color:rgb(0,127,0)} +span#textcolor1427{color:rgb(0,127,0)} span#textcolor1428{color:rgb(0,0,255)} -span#textcolor1429{color:rgb(43,145,175)} +span#textcolor1429{color:rgb(0,0,255)} span#textcolor1430{color:rgb(43,145,175)} -span#textcolor1431{color:rgb(0,0,255)} +span#textcolor1431{color:rgb(43,145,175)} span#textcolor1432{color:rgb(43,145,175)} span#textcolor1433{color:rgb(43,145,175)} -span#textcolor1434{color:rgb(0,0,255)} -span#textcolor1435{color:rgb(0,0,255)} +span#textcolor1434{color:rgb(43,145,175)} +span#textcolor1435{color:rgb(43,145,175)} span#textcolor1436{color:rgb(43,145,175)} -span#textcolor1437{color:rgb(0,0,255)} +span#textcolor1437{color:rgb(43,145,175)} 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(0,0,255)} -span#textcolor1442{color:rgb(0,0,255)} -span#textcolor1443{color:rgb(0,127,0)} -span#textcolor1444{color:rgb(43,145,175)} -span#textcolor1445{color:rgb(0,127,0)} +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(43,145,175)} -span#textcolor1447{color:rgb(43,145,175)} -span#textcolor1448{color:rgb(163,20,20)} -span#textcolor1449{color:rgb(163,20,20)} -span#textcolor1450{color:rgb(163,20,20)} +span#textcolor1447{color:rgb(0,0,255)} +span#textcolor1448{color:rgb(0,0,255)} +span#textcolor1449{color:rgb(43,145,175)} +span#textcolor1450{color:rgb(43,145,175)} span#textcolor1451{color:rgb(0,0,255)} span#textcolor1452{color:rgb(0,0,255)} -span#textcolor1453{color:rgb(43,145,175)} +span#textcolor1453{color:rgb(0,127,0)} span#textcolor1454{color:rgb(43,145,175)} -span#textcolor1455{color:rgb(0,0,255)} -span#textcolor1456{color:rgb(0,0,255)} -span#textcolor1457{color:rgb(0,127,0)} -span#textcolor1458{color:rgb(0,0,255)} -span#textcolor1459{color:rgb(43,145,175)} -span#textcolor1460{color:rgb(43,145,175)} -span#textcolor1461{color:rgb(163,20,20)} -span#textcolor1462{color:rgb(163,20,20)} -span#textcolor1463{color:rgb(163,20,20)} -span#textcolor1464{color:rgb(163,20,20)} -span#textcolor1465{color:rgb(163,20,20)} -span#textcolor1466{color:rgb(163,20,20)} -span#textcolor1467{color:rgb(163,20,20)} -span#textcolor1468{color:rgb(163,20,20)} +span#textcolor1455{color:rgb(0,127,0)} +span#textcolor1456{color:rgb(43,145,175)} +span#textcolor1457{color:rgb(43,145,175)} +span#textcolor1458{color:rgb(163,20,20)} +span#textcolor1459{color:rgb(163,20,20)} +span#textcolor1460{color:rgb(163,20,20)} +span#textcolor1461{color:rgb(0,0,255)} +span#textcolor1462{color:rgb(0,0,255)} +span#textcolor1463{color:rgb(43,145,175)} +span#textcolor1464{color:rgb(43,145,175)} +span#textcolor1465{color:rgb(0,0,255)} +span#textcolor1466{color:rgb(0,0,255)} +span#textcolor1467{color:rgb(0,127,0)} +span#textcolor1468{color:rgb(0,0,255)} span#textcolor1469{color:rgb(43,145,175)} span#textcolor1470{color:rgb(43,145,175)} span#textcolor1471{color:rgb(163,20,20)} +span#textcolor1472{color:rgb(163,20,20)} +span#textcolor1473{color:rgb(163,20,20)} +span#textcolor1474{color:rgb(163,20,20)} +span#textcolor1475{color:rgb(163,20,20)} +span#textcolor1476{color:rgb(163,20,20)} +span#textcolor1477{color:rgb(163,20,20)} +span#textcolor1478{color:rgb(163,20,20)} +span#textcolor1479{color:rgb(43,145,175)} +span#textcolor1480{color:rgb(43,145,175)} +span#textcolor1481{color:rgb(163,20,20)} pre#fancyvrb53{padding:5.69054pt;} pre#fancyvrb53{ border-top: solid 0.4pt; } pre#fancyvrb53{ border-left: solid 0.4pt; } @@ -1935,123 +1956,113 @@ 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#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,127,0)} -span#textcolor1476{color:rgb(0,0,255)} -span#textcolor1477{color:rgb(0,127,0)} -span#textcolor1478{color:rgb(0,0,255)} -span#textcolor1479{color:rgb(0,127,0)} -span#textcolor1480{color:rgb(0,0,255)} -span#textcolor1481{color:rgb(0,127,0)} -span#textcolor1482{color:rgb(0,0,255)} +span#textcolor1482{color:rgb(0,127,0)} span#textcolor1483{color:rgb(0,127,0)} -#colorbox1484{border: solid 1px rgb(255,0,0);} -#colorbox1484{background-color: rgb(255,255,255);} -span#textcolor1485{color:rgb(0,0,255)} -span#textcolor1486{color:rgb(0,127,0)} -span#textcolor1487{color:rgb(0,0,255)} -span#textcolor1488{color:rgb(0,127,0)} -span#textcolor1489{color:rgb(0,0,255)} +span#textcolor1484{color:rgb(0,127,0)} +span#textcolor1485{color:rgb(0,127,0)} +span#textcolor1486{color:rgb(0,0,255)} +span#textcolor1487{color:rgb(0,127,0)} +span#textcolor1488{color:rgb(0,0,255)} +span#textcolor1489{color:rgb(0,127,0)} span#textcolor1490{color:rgb(0,0,255)} -span#textcolor1491{color:rgb(0,0,255)} -span#textcolor1492{color:rgb(0,127,0)} +span#textcolor1491{color:rgb(0,127,0)} +span#textcolor1492{color:rgb(0,0,255)} span#textcolor1493{color:rgb(0,127,0)} -span#textcolor1494{color:rgb(0,127,0)} +#colorbox1494{border: solid 1px rgb(255,0,0);} +#colorbox1494{background-color: rgb(255,255,255);} span#textcolor1495{color:rgb(0,0,255)} -span#textcolor1496{color:rgb(0,0,255)} -span#textcolor1497{color:rgb(43,145,175)} -span#textcolor1498{color:rgb(0,0,255)} +span#textcolor1496{color:rgb(0,127,0)} +span#textcolor1497{color:rgb(0,0,255)} +span#textcolor1498{color:rgb(0,127,0)} span#textcolor1499{color:rgb(0,0,255)} span#textcolor1500{color:rgb(0,0,255)} -span#textcolor1501{color:rgb(0,127,0)} +span#textcolor1501{color:rgb(0,0,255)} span#textcolor1502{color:rgb(0,127,0)} span#textcolor1503{color:rgb(0,127,0)} span#textcolor1504{color:rgb(0,127,0)} span#textcolor1505{color:rgb(0,0,255)} -span#textcolor1506{color:rgb(43,145,175)} -span#textcolor1507{color:rgb(0,0,255)} -span#textcolor1508{color:rgb(0,127,0)} -span#textcolor1509{color:rgb(43,145,175)} -span#textcolor1510{color:rgb(0,127,0)} +span#textcolor1506{color:rgb(0,0,255)} +span#textcolor1507{color:rgb(43,145,175)} +span#textcolor1508{color:rgb(0,0,255)} +span#textcolor1509{color:rgb(0,0,255)} +span#textcolor1510{color:rgb(0,0,255)} span#textcolor1511{color:rgb(0,127,0)} -#colorbox1512{border: solid 1px rgb(255,0,0);} -#colorbox1512{background-color: rgb(255,255,255);} -span#textcolor1513{color:rgb(43,145,175)} +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,0,255)} span#textcolor1516{color:rgb(43,145,175)} -span#textcolor1517{color:rgb(43,145,175)} -span#textcolor1518{color:rgb(43,145,175)} -span#textcolor1519{color:rgb(0,127,0)} +span#textcolor1517{color:rgb(0,0,255)} +span#textcolor1518{color:rgb(0,127,0)} +span#textcolor1519{color:rgb(43,145,175)} span#textcolor1520{color:rgb(0,127,0)} span#textcolor1521{color:rgb(0,127,0)} -span#textcolor1522{color:rgb(0,0,255)} -span#textcolor1523{color:rgb(0,0,255)} -span#textcolor1524{color:rgb(163,20,20)} -span#textcolor1525{color:rgb(163,20,20)} -span#textcolor1526{color:rgb(163,20,20)} -span#textcolor1527{color:rgb(0,0,255)} -span#textcolor1528{color:rgb(0,0,255)} +#colorbox1522{border: solid 1px rgb(255,0,0);} +#colorbox1522{background-color: rgb(255,255,255);} +span#textcolor1523{color:rgb(43,145,175)} +span#textcolor1524{color:rgb(0,127,0)} +span#textcolor1525{color:rgb(0,0,255)} +span#textcolor1526{color:rgb(43,145,175)} +span#textcolor1527{color:rgb(43,145,175)} +span#textcolor1528{color:rgb(43,145,175)} 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#textcolor1532{color:rgb(0,0,255)} span#textcolor1533{color:rgb(0,0,255)} -span#textcolor1534{color:rgb(43,145,175)} -span#textcolor1535{color:rgb(0,0,255)} -span#textcolor1536{color:rgb(0,127,0)} +span#textcolor1534{color:rgb(163,20,20)} +span#textcolor1535{color:rgb(163,20,20)} +span#textcolor1536{color:rgb(163,20,20)} span#textcolor1537{color:rgb(0,0,255)} -span#textcolor1538{color:rgb(43,145,175)} +span#textcolor1538{color:rgb(0,0,255)} span#textcolor1539{color:rgb(0,127,0)} -span#textcolor1540{color:rgb(43,145,175)} +span#textcolor1540{color:rgb(0,127,0)} span#textcolor1541{color:rgb(0,127,0)} span#textcolor1542{color:rgb(0,127,0)} -span#textcolor1543{color:rgb(43,145,175)} -span#textcolor1544{color:rgb(0,127,0)} -span#textcolor1545{color:rgb(0,127,0)} +span#textcolor1543{color:rgb(0,0,255)} +span#textcolor1544{color:rgb(43,145,175)} +span#textcolor1545{color:rgb(0,0,255)} span#textcolor1546{color:rgb(0,127,0)} span#textcolor1547{color:rgb(0,0,255)} -span#textcolor1548{color:rgb(0,127,0)} -span#textcolor1549{color:rgb(163,20,20)} -span#textcolor1550{color:rgb(0,127,0)} -span#textcolor1551{color:rgb(0,0,255)} +span#textcolor1548{color:rgb(43,145,175)} +span#textcolor1549{color:rgb(0,127,0)} +span#textcolor1550{color:rgb(43,145,175)} +span#textcolor1551{color:rgb(0,127,0)} span#textcolor1552{color:rgb(0,127,0)} span#textcolor1553{color:rgb(43,145,175)} span#textcolor1554{color:rgb(0,127,0)} span#textcolor1555{color:rgb(0,127,0)} -span#textcolor1556{color:rgb(0,0,255)} -span#textcolor1557{color:rgb(43,145,175)} -span#textcolor1558{color:rgb(0,0,255)} -span#textcolor1559{color:rgb(0,0,255)} +span#textcolor1556{color:rgb(0,127,0)} +span#textcolor1557{color:rgb(0,0,255)} +span#textcolor1558{color:rgb(0,127,0)} +span#textcolor1559{color:rgb(163,20,20)} span#textcolor1560{color:rgb(0,127,0)} -span#textcolor1561{color:rgb(0,127,0)} +span#textcolor1561{color:rgb(0,0,255)} span#textcolor1562{color:rgb(0,127,0)} -span#textcolor1563{color:rgb(0,127,0)} +span#textcolor1563{color:rgb(43,145,175)} span#textcolor1564{color:rgb(0,127,0)} -span#textcolor1565{color:rgb(0,0,255)} +span#textcolor1565{color:rgb(0,127,0)} span#textcolor1566{color:rgb(0,0,255)} -span#textcolor1567{color:rgb(0,127,0)} -span#textcolor1568{color:rgb(0,127,0)} -span#textcolor1569{color:rgb(0,127,0)} +span#textcolor1567{color:rgb(43,145,175)} +span#textcolor1568{color:rgb(0,0,255)} +span#textcolor1569{color:rgb(0,0,255)} span#textcolor1570{color:rgb(0,127,0)} span#textcolor1571{color:rgb(0,127,0)} -span#textcolor1572{color:rgb(0,0,255)} -span#textcolor1573{color:rgb(43,145,175)} +span#textcolor1572{color:rgb(0,127,0)} +span#textcolor1573{color:rgb(0,127,0)} span#textcolor1574{color:rgb(0,127,0)} -span#textcolor1575{color:rgb(0,127,0)} -span#textcolor1576{color:rgb(0,127,0)} +span#textcolor1575{color:rgb(0,0,255)} +span#textcolor1576{color:rgb(0,0,255)} span#textcolor1577{color:rgb(0,127,0)} span#textcolor1578{color:rgb(0,127,0)} span#textcolor1579{color:rgb(0,127,0)} span#textcolor1580{color:rgb(0,127,0)} span#textcolor1581{color:rgb(0,127,0)} -span#textcolor1582{color:rgb(0,127,0)} -span#textcolor1583{color:rgb(0,127,0)} +span#textcolor1582{color:rgb(0,0,255)} +span#textcolor1583{color:rgb(43,145,175)} span#textcolor1584{color:rgb(0,127,0)} -span#textcolor1585{color:rgb(0,0,255)} -span#textcolor1586{color:rgb(0,0,255)} +span#textcolor1585{color:rgb(0,127,0)} +span#textcolor1586{color:rgb(0,127,0)} span#textcolor1587{color:rgb(0,127,0)} span#textcolor1588{color:rgb(0,127,0)} span#textcolor1589{color:rgb(0,127,0)} @@ -2061,24 +2072,24 @@ span#textcolor1592{color:rgb(0,127,0)} span#textcolor1593{color:rgb(0,127,0)} span#textcolor1594{color:rgb(0,127,0)} span#textcolor1595{color:rgb(0,0,255)} -span#textcolor1596{color:rgb(0,127,0)} +span#textcolor1596{color:rgb(0,0,255)} span#textcolor1597{color:rgb(0,127,0)} -span#textcolor1598{color:rgb(0,0,255)} +span#textcolor1598{color:rgb(0,127,0)} span#textcolor1599{color:rgb(0,127,0)} span#textcolor1600{color:rgb(0,127,0)} -span#textcolor1601{color:rgb(43,145,175)} -span#textcolor1602{color:rgb(0,0,255)} -span#textcolor1603{color:rgb(0,0,255)} +span#textcolor1601{color:rgb(0,127,0)} +span#textcolor1602{color:rgb(0,127,0)} +span#textcolor1603{color:rgb(0,127,0)} span#textcolor1604{color:rgb(0,127,0)} -span#textcolor1605{color:rgb(0,127,0)} +span#textcolor1605{color:rgb(0,0,255)} span#textcolor1606{color:rgb(0,127,0)} span#textcolor1607{color:rgb(0,127,0)} -span#textcolor1608{color:rgb(0,127,0)} +span#textcolor1608{color:rgb(0,0,255)} span#textcolor1609{color:rgb(0,127,0)} span#textcolor1610{color:rgb(0,127,0)} -span#textcolor1611{color:rgb(0,127,0)} +span#textcolor1611{color:rgb(43,145,175)} span#textcolor1612{color:rgb(0,0,255)} -span#textcolor1613{color:rgb(0,127,0)} +span#textcolor1613{color:rgb(0,0,255)} span#textcolor1614{color:rgb(0,127,0)} span#textcolor1615{color:rgb(0,127,0)} span#textcolor1616{color:rgb(0,127,0)} @@ -2086,417 +2097,417 @@ span#textcolor1617{color:rgb(0,127,0)} span#textcolor1618{color:rgb(0,127,0)} span#textcolor1619{color:rgb(0,127,0)} span#textcolor1620{color:rgb(0,127,0)} -span#textcolor1621{color:rgb(0,0,255)} +span#textcolor1621{color:rgb(0,127,0)} span#textcolor1622{color:rgb(0,0,255)} -span#textcolor1623{color:rgb(0,0,255)} -span#textcolor1624{color:rgb(0,0,255)} +span#textcolor1623{color:rgb(0,127,0)} +span#textcolor1624{color:rgb(0,127,0)} span#textcolor1625{color:rgb(0,127,0)} span#textcolor1626{color:rgb(0,127,0)} span#textcolor1627{color:rgb(0,127,0)} span#textcolor1628{color:rgb(0,127,0)} -span#textcolor1629{color:rgb(0,0,255)} -span#textcolor1630{color:rgb(0,0,255)} +span#textcolor1629{color:rgb(0,127,0)} +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,0,255)} -span#textcolor1636{color:rgb(43,145,175)} -span#textcolor1637{color:rgb(43,145,175)} -span#textcolor1638{color:rgb(0,0,255)} -span#textcolor1639{color:rgb(163,20,20)} -span#textcolor1640{color:rgb(163,20,20)} -span#textcolor1641{color:rgb(163,20,20)} +span#textcolor1634{color:rgb(0,0,255)} +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,0,255)} +span#textcolor1640{color:rgb(0,0,255)} +span#textcolor1641{color:rgb(0,0,255)} span#textcolor1642{color:rgb(0,0,255)} -span#textcolor1643{color:rgb(163,20,20)} -span#textcolor1644{color:rgb(163,20,20)} -span#textcolor1645{color:rgb(163,20,20)} -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#textcolor1643{color:rgb(0,0,255)} +span#textcolor1644{color:rgb(0,127,0)} +span#textcolor1645{color:rgb(0,0,255)} +span#textcolor1646{color:rgb(43,145,175)} +span#textcolor1647{color:rgb(43,145,175)} +span#textcolor1648{color:rgb(0,0,255)} +span#textcolor1649{color:rgb(163,20,20)} +span#textcolor1650{color:rgb(163,20,20)} +span#textcolor1651{color:rgb(163,20,20)} span#textcolor1652{color:rgb(0,0,255)} -span#textcolor1653{color:rgb(43,145,175)} -span#textcolor1654{color:rgb(43,145,175)} +span#textcolor1653{color:rgb(163,20,20)} +span#textcolor1654{color:rgb(163,20,20)} span#textcolor1655{color:rgb(163,20,20)} -span#textcolor1656{color:rgb(163,20,20)} -span#textcolor1657{color:rgb(163,20,20)} -span#textcolor1658{color:rgb(163,20,20)} +span#textcolor1656{color:rgb(0,0,255)} +span#textcolor1657{color:rgb(0,127,0)} +span#textcolor1658{color:rgb(0,127,0)} +span#textcolor1659{color:rgb(0,127,0)} +span#textcolor1660{color:rgb(0,127,0)} +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(163,20,20)} +span#textcolor1666{color:rgb(163,20,20)} +span#textcolor1667{color:rgb(163,20,20)} +span#textcolor1668{color:rgb(163,20,20)} 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#textcolor1659{color:rgb(0,127,0)} -span#textcolor1660{color:rgb(0,127,0)} -span#textcolor1661{color:rgb(0,127,0)} -span#textcolor1662{color:rgb(0,127,0)} -span#textcolor1663{color:rgb(0,0,255)} -span#textcolor1664{color:rgb(0,127,0)} -span#textcolor1665{color:rgb(0,0,255)} -span#textcolor1666{color:rgb(0,127,0)} -span#textcolor1667{color:rgb(0,0,255)} -span#textcolor1668{color:rgb(0,127,0)} -span#textcolor1669{color:rgb(0,0,255)} +span#textcolor1669{color:rgb(0,127,0)} span#textcolor1670{color:rgb(0,127,0)} -span#textcolor1671{color:rgb(0,0,255)} +span#textcolor1671{color:rgb(0,127,0)} span#textcolor1672{color:rgb(0,127,0)} span#textcolor1673{color:rgb(0,0,255)} -span#textcolor1674{color:rgb(43,145,175)} -span#textcolor1675{color:rgb(43,145,175)} -span#textcolor1676{color:rgb(43,145,175)} -span#textcolor1677{color:rgb(43,145,175)} +span#textcolor1674{color:rgb(0,127,0)} +span#textcolor1675{color:rgb(0,0,255)} +span#textcolor1676{color:rgb(0,127,0)} +span#textcolor1677{color:rgb(0,0,255)} span#textcolor1678{color:rgb(0,127,0)} -span#textcolor1679{color:rgb(43,145,175)} +span#textcolor1679{color:rgb(0,0,255)} span#textcolor1680{color:rgb(0,127,0)} -span#textcolor1681{color:rgb(43,145,175)} +span#textcolor1681{color:rgb(0,0,255)} span#textcolor1682{color:rgb(0,127,0)} -span#textcolor1683{color:rgb(0,127,0)} -span#textcolor1684{color:rgb(0,0,255)} -span#textcolor1685{color:rgb(163,20,20)} -span#textcolor1686{color:rgb(163,20,20)} -span#textcolor1687{color:rgb(163,20,20)} -span#textcolor1688{color:rgb(163,20,20)} -span#textcolor1689{color:rgb(0,127,0)} +span#textcolor1683{color:rgb(0,0,255)} +span#textcolor1684{color:rgb(43,145,175)} +span#textcolor1685{color:rgb(43,145,175)} +span#textcolor1686{color:rgb(43,145,175)} +span#textcolor1687{color:rgb(43,145,175)} +span#textcolor1688{color:rgb(0,127,0)} +span#textcolor1689{color:rgb(43,145,175)} span#textcolor1690{color:rgb(0,127,0)} -span#textcolor1691{color:rgb(0,0,255)} -span#textcolor1692{color:rgb(163,20,20)} -span#textcolor1693{color:rgb(163,20,20)} -span#textcolor1694{color:rgb(0,127,0)} -span#textcolor1695{color:rgb(0,0,255)} -span#textcolor1696{color:rgb(0,127,0)} -span#textcolor1697{color:rgb(0,127,0)} -span#textcolor1698{color:rgb(0,0,255)} -span#textcolor1699{color:rgb(0,0,255)} -span#textcolor1700{color:rgb(163,20,20)} +span#textcolor1691{color:rgb(43,145,175)} +span#textcolor1692{color:rgb(0,127,0)} +span#textcolor1693{color:rgb(0,127,0)} +span#textcolor1694{color:rgb(0,0,255)} +span#textcolor1695{color:rgb(163,20,20)} +span#textcolor1696{color:rgb(163,20,20)} +span#textcolor1697{color:rgb(163,20,20)} +span#textcolor1698{color:rgb(163,20,20)} +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(163,20,20)} -span#textcolor1703{color:rgb(0,127,0)} -span#textcolor1704{color:rgb(0,0,255)} +span#textcolor1703{color:rgb(163,20,20)} +span#textcolor1704{color:rgb(0,127,0)} span#textcolor1705{color:rgb(0,0,255)} -span#textcolor1706{color:rgb(43,145,175)} +span#textcolor1706{color:rgb(0,127,0)} span#textcolor1707{color:rgb(0,127,0)} span#textcolor1708{color:rgb(0,0,255)} span#textcolor1709{color:rgb(0,0,255)} +span#textcolor1710{color:rgb(163,20,20)} +span#textcolor1711{color:rgb(0,0,255)} +span#textcolor1712{color:rgb(163,20,20)} +span#textcolor1713{color:rgb(0,127,0)} +span#textcolor1714{color:rgb(0,0,255)} +span#textcolor1715{color:rgb(0,0,255)} +span#textcolor1716{color:rgb(43,145,175)} +span#textcolor1717{color:rgb(0,127,0)} +span#textcolor1718{color:rgb(0,0,255)} +span#textcolor1719{color:rgb(0,0,255)} 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#textcolor1710{color:rgb(0,127,0)} -span#textcolor1711{color:rgb(0,127,0)} -span#textcolor1712{color:rgb(0,127,0)} -span#textcolor1713{color:rgb(0,0,255)} -span#textcolor1714{color:rgb(0,127,0)} -span#textcolor1715{color:rgb(0,0,255)} -span#textcolor1716{color:rgb(0,127,0)} -span#textcolor1717{color:rgb(0,0,255)} -span#textcolor1718{color:rgb(0,127,0)} -span#textcolor1719{color:rgb(0,0,255)} span#textcolor1720{color:rgb(0,127,0)} -span#textcolor1721{color:rgb(0,0,255)} +span#textcolor1721{color:rgb(0,127,0)} span#textcolor1722{color:rgb(0,127,0)} span#textcolor1723{color:rgb(0,0,255)} -span#textcolor1724{color:rgb(0,0,255)} +span#textcolor1724{color:rgb(0,127,0)} span#textcolor1725{color:rgb(0,0,255)} -span#textcolor1726{color:rgb(0,0,255)} +span#textcolor1726{color:rgb(0,127,0)} span#textcolor1727{color:rgb(0,0,255)} -span#textcolor1728{color:rgb(43,145,175)} -span#textcolor1729{color:rgb(43,145,175)} -span#textcolor1730{color:rgb(163,20,20)} -span#textcolor1731{color:rgb(163,20,20)} -span#textcolor1732{color:rgb(163,20,20)} +span#textcolor1728{color:rgb(0,127,0)} +span#textcolor1729{color:rgb(0,0,255)} +span#textcolor1730{color:rgb(0,127,0)} +span#textcolor1731{color:rgb(0,0,255)} +span#textcolor1732{color:rgb(0,127,0)} span#textcolor1733{color:rgb(0,0,255)} -span#textcolor1734{color:rgb(43,145,175)} -span#textcolor1735{color:rgb(43,145,175)} -span#textcolor1736{color:rgb(163,20,20)} -span#textcolor1737{color:rgb(163,20,20)} -span#textcolor1738{color:rgb(163,20,20)} -span#textcolor1739{color:rgb(0,0,255)} -span#textcolor1740{color:rgb(43,145,175)} -span#textcolor1741{color:rgb(43,145,175)} -span#textcolor1742{color:rgb(0,0,255)} +span#textcolor1734{color:rgb(0,0,255)} +span#textcolor1735{color:rgb(0,0,255)} +span#textcolor1736{color:rgb(0,0,255)} +span#textcolor1737{color:rgb(0,0,255)} +span#textcolor1738{color:rgb(43,145,175)} +span#textcolor1739{color:rgb(43,145,175)} +span#textcolor1740{color:rgb(163,20,20)} +span#textcolor1741{color:rgb(163,20,20)} +span#textcolor1742{color:rgb(163,20,20)} span#textcolor1743{color:rgb(0,0,255)} -span#textcolor1744{color:rgb(163,20,20)} -span#textcolor1745{color:rgb(163,20,20)} +span#textcolor1744{color:rgb(43,145,175)} +span#textcolor1745{color:rgb(43,145,175)} span#textcolor1746{color:rgb(163,20,20)} span#textcolor1747{color:rgb(163,20,20)} -span#textcolor1748{color:rgb(0,0,255)} +span#textcolor1748{color:rgb(163,20,20)} span#textcolor1749{color:rgb(0,0,255)} -span#textcolor1750{color:rgb(163,20,20)} -span#textcolor1751{color:rgb(0,0,255)} +span#textcolor1750{color:rgb(43,145,175)} +span#textcolor1751{color:rgb(43,145,175)} span#textcolor1752{color:rgb(0,0,255)} span#textcolor1753{color:rgb(0,0,255)} -span#textcolor1754{color:rgb(0,0,255)} -span#textcolor1755{color:rgb(43,145,175)} -span#textcolor1756{color:rgb(43,145,175)} +span#textcolor1754{color:rgb(163,20,20)} +span#textcolor1755{color:rgb(163,20,20)} +span#textcolor1756{color:rgb(163,20,20)} span#textcolor1757{color:rgb(163,20,20)} -span#textcolor1758{color:rgb(163,20,20)} -span#textcolor1759{color:rgb(163,20,20)} +span#textcolor1758{color:rgb(0,0,255)} +span#textcolor1759{color:rgb(0,0,255)} span#textcolor1760{color:rgb(163,20,20)} -span#textcolor1761{color:rgb(163,20,20)} +span#textcolor1761{color:rgb(0,0,255)} +span#textcolor1762{color:rgb(0,0,255)} +span#textcolor1763{color:rgb(0,0,255)} +span#textcolor1764{color:rgb(0,0,255)} +span#textcolor1765{color:rgb(43,145,175)} +span#textcolor1766{color:rgb(43,145,175)} +span#textcolor1767{color:rgb(163,20,20)} +span#textcolor1768{color:rgb(163,20,20)} +span#textcolor1769{color:rgb(163,20,20)} +span#textcolor1770{color:rgb(163,20,20)} +span#textcolor1771{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#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,0,255)} -span#textcolor1766{color:rgb(0,127,0)} -span#textcolor1767{color:rgb(0,0,255)} -span#textcolor1768{color:rgb(0,127,0)} -span#textcolor1769{color:rgb(0,0,255)} -span#textcolor1770{color:rgb(0,127,0)} -span#textcolor1771{color:rgb(0,0,255)} span#textcolor1772{color:rgb(0,127,0)} -span#textcolor1773{color:rgb(0,0,255)} -span#textcolor1774{color:rgb(43,145,175)} -span#textcolor1775{color:rgb(43,145,175)} -span#textcolor1776{color:rgb(43,145,175)} -span#textcolor1777{color:rgb(163,20,20)} -span#textcolor1778{color:rgb(163,20,20)} -span#textcolor1779{color:rgb(163,20,20)} -span#textcolor1780{color:rgb(0,0,255)} -span#textcolor1781{color:rgb(163,20,20)} -span#textcolor1782{color:rgb(163,20,20)} -span#textcolor1783{color:rgb(163,20,20)} -span#textcolor1784{color:rgb(0,0,255)} -span#textcolor1785{color:rgb(163,20,20)} -span#textcolor1786{color:rgb(163,20,20)} +span#textcolor1773{color:rgb(0,127,0)} +span#textcolor1774{color:rgb(0,127,0)} +span#textcolor1775{color:rgb(0,0,255)} +span#textcolor1776{color:rgb(0,127,0)} +span#textcolor1777{color:rgb(0,0,255)} +span#textcolor1778{color:rgb(0,127,0)} +span#textcolor1779{color:rgb(0,0,255)} +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,0,255)} +span#textcolor1784{color:rgb(43,145,175)} +span#textcolor1785{color:rgb(43,145,175)} +span#textcolor1786{color:rgb(43,145,175)} span#textcolor1787{color:rgb(163,20,20)} span#textcolor1788{color:rgb(163,20,20)} span#textcolor1789{color:rgb(163,20,20)} -span#textcolor1790{color:rgb(163,20,20)} -span#textcolor1791{color:rgb(0,0,255)} +span#textcolor1790{color:rgb(0,0,255)} +span#textcolor1791{color:rgb(163,20,20)} span#textcolor1792{color:rgb(163,20,20)} span#textcolor1793{color:rgb(163,20,20)} -span#textcolor1794{color:rgb(163,20,20)} -span#textcolor1795{color:rgb(0,0,255)} -span#textcolor1796{color:rgb(0,0,255)} -span#textcolor1797{color:rgb(43,145,175)} -span#textcolor1798{color:rgb(43,145,175)} +span#textcolor1794{color:rgb(0,0,255)} +span#textcolor1795{color:rgb(163,20,20)} +span#textcolor1796{color:rgb(163,20,20)} +span#textcolor1797{color:rgb(163,20,20)} +span#textcolor1798{color:rgb(163,20,20)} span#textcolor1799{color:rgb(163,20,20)} span#textcolor1800{color:rgb(163,20,20)} -span#textcolor1801{color:rgb(163,20,20)} +span#textcolor1801{color:rgb(0,0,255)} span#textcolor1802{color:rgb(163,20,20)} span#textcolor1803{color:rgb(163,20,20)} +span#textcolor1804{color:rgb(163,20,20)} +span#textcolor1805{color:rgb(0,0,255)} +span#textcolor1806{color:rgb(0,0,255)} +span#textcolor1807{color:rgb(43,145,175)} +span#textcolor1808{color:rgb(43,145,175)} +span#textcolor1809{color:rgb(163,20,20)} +span#textcolor1810{color:rgb(163,20,20)} +span#textcolor1811{color:rgb(163,20,20)} +span#textcolor1812{color:rgb(163,20,20)} +span#textcolor1813{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#textcolor1804{color:rgb(0,127,0)} -span#textcolor1805{color:rgb(0,127,0)} -span#textcolor1806{color:rgb(0,127,0)} -span#textcolor1807{color:rgb(0,0,255)} -span#textcolor1808{color:rgb(0,127,0)} -span#textcolor1809{color:rgb(0,0,255)} -span#textcolor1810{color:rgb(0,127,0)} -span#textcolor1811{color:rgb(0,0,255)} -span#textcolor1812{color:rgb(0,127,0)} -span#textcolor1813{color:rgb(0,0,255)} span#textcolor1814{color:rgb(0,127,0)} -span#textcolor1815{color:rgb(0,0,255)} +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(43,145,175)} -span#textcolor1819{color:rgb(43,145,175)} -span#textcolor1820{color:rgb(43,145,175)} -span#textcolor1821{color:rgb(43,145,175)} -span#textcolor1822{color:rgb(163,20,20)} -span#textcolor1823{color:rgb(163,20,20)} -span#textcolor1824{color:rgb(163,20,20)} -span#textcolor1825{color:rgb(0,127,0)} +span#textcolor1818{color:rgb(0,127,0)} +span#textcolor1819{color:rgb(0,0,255)} +span#textcolor1820{color:rgb(0,127,0)} +span#textcolor1821{color:rgb(0,0,255)} +span#textcolor1822{color:rgb(0,127,0)} +span#textcolor1823{color:rgb(0,0,255)} +span#textcolor1824{color:rgb(0,127,0)} +span#textcolor1825{color:rgb(0,0,255)} span#textcolor1826{color:rgb(0,127,0)} -span#textcolor1827{color:rgb(0,127,0)} -span#textcolor1828{color:rgb(163,20,20)} -span#textcolor1829{color:rgb(163,20,20)} -span#textcolor1830{color:rgb(163,20,20)} -span#textcolor1831{color:rgb(0,0,255)} -span#textcolor1832{color:rgb(43,145,175)} -span#textcolor1833{color:rgb(43,145,175)} -span#textcolor1834{color:rgb(43,145,175)} -span#textcolor1835{color:rgb(43,145,175)} -span#textcolor1836{color:rgb(163,20,20)} -span#textcolor1837{color:rgb(163,20,20)} +span#textcolor1827{color:rgb(0,0,255)} +span#textcolor1828{color:rgb(43,145,175)} +span#textcolor1829{color:rgb(43,145,175)} +span#textcolor1830{color:rgb(43,145,175)} +span#textcolor1831{color:rgb(43,145,175)} +span#textcolor1832{color:rgb(163,20,20)} +span#textcolor1833{color:rgb(163,20,20)} +span#textcolor1834{color:rgb(163,20,20)} +span#textcolor1835{color:rgb(0,127,0)} +span#textcolor1836{color:rgb(0,127,0)} +span#textcolor1837{color:rgb(0,127,0)} span#textcolor1838{color:rgb(163,20,20)} -span#textcolor1839{color:rgb(0,127,0)} -span#textcolor1840{color:rgb(0,127,0)} -span#textcolor1841{color:rgb(0,127,0)} -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(43,145,175)} -span#textcolor1847{color:rgb(43,145,175)} +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(43,145,175)} +span#textcolor1843{color:rgb(43,145,175)} +span#textcolor1844{color:rgb(43,145,175)} +span#textcolor1845{color:rgb(43,145,175)} +span#textcolor1846{color:rgb(163,20,20)} +span#textcolor1847{color:rgb(163,20,20)} span#textcolor1848{color:rgb(163,20,20)} -span#textcolor1849{color:rgb(163,20,20)} -span#textcolor1850{color:rgb(163,20,20)} -span#textcolor1851{color:rgb(0,0,255)} -span#textcolor1852{color:rgb(0,0,255)} -span#textcolor1853{color:rgb(43,145,175)} -span#textcolor1854{color:rgb(43,145,175)} -span#textcolor1855{color:rgb(163,20,20)} -span#textcolor1856{color:rgb(163,20,20)} -span#textcolor1857{color:rgb(163,20,20)} +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(163,20,20)} +span#textcolor1853{color:rgb(163,20,20)} +span#textcolor1854{color:rgb(163,20,20)} +span#textcolor1855{color:rgb(0,0,255)} +span#textcolor1856{color:rgb(43,145,175)} +span#textcolor1857{color:rgb(43,145,175)} span#textcolor1858{color:rgb(163,20,20)} span#textcolor1859{color:rgb(163,20,20)} +span#textcolor1860{color:rgb(163,20,20)} +span#textcolor1861{color:rgb(0,0,255)} +span#textcolor1862{color:rgb(0,0,255)} +span#textcolor1863{color:rgb(43,145,175)} +span#textcolor1864{color:rgb(43,145,175)} +span#textcolor1865{color:rgb(163,20,20)} +span#textcolor1866{color:rgb(163,20,20)} +span#textcolor1867{color:rgb(163,20,20)} +span#textcolor1868{color:rgb(163,20,20)} +span#textcolor1869{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#textcolor1860{color:rgb(0,127,0)} -span#textcolor1861{color:rgb(0,127,0)} -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(43,145,175)} -span#textcolor1871{color:rgb(43,145,175)} -span#textcolor1872{color:rgb(43,145,175)} -span#textcolor1873{color:rgb(43,145,175)} -span#textcolor1874{color:rgb(163,20,20)} -span#textcolor1875{color:rgb(163,20,20)} -span#textcolor1876{color:rgb(163,20,20)} -span#textcolor1877{color:rgb(0,127,0)} -span#textcolor1878{color:rgb(163,20,20)} -span#textcolor1879{color:rgb(163,20,20)} -span#textcolor1880{color:rgb(163,20,20)} -span#textcolor1881{color:rgb(0,0,255)} +span#textcolor1870{color:rgb(0,127,0)} +span#textcolor1871{color:rgb(0,127,0)} +span#textcolor1872{color:rgb(0,127,0)} +span#textcolor1873{color:rgb(0,0,255)} +span#textcolor1874{color:rgb(0,127,0)} +span#textcolor1875{color:rgb(0,0,255)} +span#textcolor1876{color:rgb(0,127,0)} +span#textcolor1877{color:rgb(0,0,255)} +span#textcolor1878{color:rgb(0,127,0)} +span#textcolor1879{color:rgb(0,0,255)} +span#textcolor1880{color:rgb(43,145,175)} +span#textcolor1881{color:rgb(43,145,175)} span#textcolor1882{color:rgb(43,145,175)} span#textcolor1883{color:rgb(43,145,175)} -span#textcolor1884{color:rgb(43,145,175)} -span#textcolor1885{color:rgb(43,145,175)} +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(163,20,20)} +span#textcolor1887{color:rgb(0,127,0)} span#textcolor1888{color:rgb(163,20,20)} -span#textcolor1889{color:rgb(0,127,0)} +span#textcolor1889{color:rgb(163,20,20)} span#textcolor1890{color:rgb(163,20,20)} -span#textcolor1891{color:rgb(163,20,20)} -span#textcolor1892{color:rgb(163,20,20)} -span#textcolor1893{color:rgb(0,0,255)} +span#textcolor1891{color:rgb(0,0,255)} +span#textcolor1892{color:rgb(43,145,175)} +span#textcolor1893{color:rgb(43,145,175)} span#textcolor1894{color:rgb(43,145,175)} span#textcolor1895{color:rgb(43,145,175)} span#textcolor1896{color:rgb(163,20,20)} span#textcolor1897{color:rgb(163,20,20)} span#textcolor1898{color:rgb(163,20,20)} -span#textcolor1899{color:rgb(0,0,255)} -span#textcolor1900{color:rgb(0,0,255)} -span#textcolor1901{color:rgb(43,145,175)} -span#textcolor1902{color:rgb(43,145,175)} -span#textcolor1903{color:rgb(163,20,20)} -span#textcolor1904{color:rgb(163,20,20)} -span#textcolor1905{color:rgb(163,20,20)} +span#textcolor1899{color:rgb(0,127,0)} +span#textcolor1900{color:rgb(163,20,20)} +span#textcolor1901{color:rgb(163,20,20)} +span#textcolor1902{color:rgb(163,20,20)} +span#textcolor1903{color:rgb(0,0,255)} +span#textcolor1904{color:rgb(43,145,175)} +span#textcolor1905{color:rgb(43,145,175)} span#textcolor1906{color:rgb(163,20,20)} span#textcolor1907{color:rgb(163,20,20)} +span#textcolor1908{color:rgb(163,20,20)} +span#textcolor1909{color:rgb(0,0,255)} +span#textcolor1910{color:rgb(0,0,255)} +span#textcolor1911{color:rgb(43,145,175)} +span#textcolor1912{color:rgb(43,145,175)} +span#textcolor1913{color:rgb(163,20,20)} +span#textcolor1914{color:rgb(163,20,20)} +span#textcolor1915{color:rgb(163,20,20)} +span#textcolor1916{color:rgb(163,20,20)} +span#textcolor1917{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#textcolor1908{color:rgb(0,127,0)} -span#textcolor1909{color:rgb(0,127,0)} -span#textcolor1910{color:rgb(0,127,0)} -span#textcolor1911{color:rgb(0,0,255)} -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,0,255)} -span#textcolor1919{color:rgb(0,0,255)} -span#textcolor1920{color:rgb(0,0,255)} +span#textcolor1918{color:rgb(0,127,0)} +span#textcolor1919{color:rgb(0,127,0)} +span#textcolor1920{color:rgb(0,127,0)} span#textcolor1921{color:rgb(0,0,255)} -span#textcolor1922{color:rgb(0,0,255)} +span#textcolor1922{color:rgb(0,127,0)} span#textcolor1923{color:rgb(0,0,255)} -span#textcolor1924{color:rgb(43,145,175)} -span#textcolor1925{color:rgb(43,145,175)} +span#textcolor1924{color:rgb(0,127,0)} +span#textcolor1925{color:rgb(0,0,255)} span#textcolor1926{color:rgb(0,127,0)} -span#textcolor1927{color:rgb(0,127,0)} -span#textcolor1928{color:rgb(163,20,20)} -span#textcolor1929{color:rgb(163,20,20)} -span#textcolor1930{color:rgb(163,20,20)} +span#textcolor1927{color:rgb(0,0,255)} +span#textcolor1928{color:rgb(0,0,255)} +span#textcolor1929{color:rgb(0,0,255)} +span#textcolor1930{color:rgb(0,0,255)} span#textcolor1931{color:rgb(0,0,255)} -span#textcolor1932{color:rgb(43,145,175)} -span#textcolor1933{color:rgb(43,145,175)} +span#textcolor1932{color:rgb(0,0,255)} +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#textcolor1936{color:rgb(0,127,0)} +span#textcolor1937{color:rgb(0,127,0)} span#textcolor1938{color:rgb(163,20,20)} span#textcolor1939{color:rgb(163,20,20)} -span#textcolor1940{color:rgb(0,0,255)} -span#textcolor1941{color:rgb(163,20,20)} -span#textcolor1942{color:rgb(163,20,20)} -span#textcolor1943{color:rgb(163,20,20)} -span#textcolor1944{color:rgb(163,20,20)} -span#textcolor1945{color:rgb(163,20,20)} -span#textcolor1946{color:rgb(0,0,255)} -span#textcolor1947{color:rgb(43,145,175)} -span#textcolor1948{color:rgb(43,145,175)} +span#textcolor1940{color:rgb(163,20,20)} +span#textcolor1941{color:rgb(0,0,255)} +span#textcolor1942{color:rgb(43,145,175)} +span#textcolor1943{color:rgb(43,145,175)} +span#textcolor1944{color:rgb(43,145,175)} +span#textcolor1945{color:rgb(43,145,175)} +span#textcolor1946{color:rgb(163,20,20)} +span#textcolor1947{color:rgb(163,20,20)} +span#textcolor1948{color:rgb(163,20,20)} span#textcolor1949{color:rgb(163,20,20)} -span#textcolor1950{color:rgb(163,20,20)} +span#textcolor1950{color:rgb(0,0,255)} span#textcolor1951{color:rgb(163,20,20)} -span#textcolor1952{color:rgb(0,0,255)} -span#textcolor1953{color:rgb(0,0,255)} -span#textcolor1954{color:rgb(43,145,175)} -span#textcolor1955{color:rgb(43,145,175)} -span#textcolor1956{color:rgb(163,20,20)} -span#textcolor1957{color:rgb(163,20,20)} -span#textcolor1958{color:rgb(163,20,20)} +span#textcolor1952{color:rgb(163,20,20)} +span#textcolor1953{color:rgb(163,20,20)} +span#textcolor1954{color:rgb(163,20,20)} +span#textcolor1955{color:rgb(163,20,20)} +span#textcolor1956{color:rgb(0,0,255)} +span#textcolor1957{color:rgb(43,145,175)} +span#textcolor1958{color:rgb(43,145,175)} span#textcolor1959{color:rgb(163,20,20)} span#textcolor1960{color:rgb(163,20,20)} +span#textcolor1961{color:rgb(163,20,20)} +span#textcolor1962{color:rgb(0,0,255)} +span#textcolor1963{color:rgb(0,0,255)} +span#textcolor1964{color:rgb(43,145,175)} +span#textcolor1965{color:rgb(43,145,175)} +span#textcolor1966{color:rgb(163,20,20)} +span#textcolor1967{color:rgb(163,20,20)} +span#textcolor1968{color:rgb(163,20,20)} +span#textcolor1969{color:rgb(163,20,20)} +span#textcolor1970{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#textcolor1961{color:rgb(0,127,0)} -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,127,0)} -span#textcolor1966{color:rgb(0,0,255)} -span#textcolor1967{color:rgb(0,127,0)} -span#textcolor1968{color:rgb(0,0,255)} -span#textcolor1969{color:rgb(0,127,0)} -span#textcolor1970{color:rgb(0,0,255)} span#textcolor1971{color:rgb(0,127,0)} -span#textcolor1972{color:rgb(0,0,255)} +span#textcolor1972{color:rgb(0,127,0)} span#textcolor1973{color:rgb(0,127,0)} -span#textcolor1974{color:rgb(0,0,255)} +span#textcolor1974{color:rgb(0,127,0)} span#textcolor1975{color:rgb(0,127,0)} span#textcolor1976{color:rgb(0,0,255)} -span#textcolor1977{color:rgb(43,145,175)} -span#textcolor1978{color:rgb(43,145,175)} -span#textcolor1979{color:rgb(0,0,255)} +span#textcolor1977{color:rgb(0,127,0)} +span#textcolor1978{color:rgb(0,0,255)} +span#textcolor1979{color:rgb(0,127,0)} span#textcolor1980{color:rgb(0,0,255)} -span#textcolor1981{color:rgb(0,0,255)} -span#textcolor1982{color:rgb(0,127,0)} +span#textcolor1981{color:rgb(0,127,0)} +span#textcolor1982{color:rgb(0,0,255)} span#textcolor1983{color:rgb(0,127,0)} -span#textcolor1984{color:rgb(0,127,0)} +span#textcolor1984{color:rgb(0,0,255)} span#textcolor1985{color:rgb(0,127,0)} span#textcolor1986{color:rgb(0,0,255)} -span#textcolor1987{color:rgb(0,127,0)} -span#textcolor1988{color:rgb(0,127,0)} -span#textcolor1989{color:rgb(0,127,0)} -span#textcolor1990{color:rgb(0,127,0)} -span#textcolor1991{color:rgb(0,127,0)} +span#textcolor1987{color:rgb(43,145,175)} +span#textcolor1988{color:rgb(43,145,175)} +span#textcolor1989{color:rgb(0,0,255)} +span#textcolor1990{color:rgb(0,0,255)} +span#textcolor1991{color:rgb(0,0,255)} span#textcolor1992{color:rgb(0,127,0)} span#textcolor1993{color:rgb(0,127,0)} span#textcolor1994{color:rgb(0,127,0)} span#textcolor1995{color:rgb(0,127,0)} -span#textcolor1996{color:rgb(0,127,0)} +span#textcolor1996{color:rgb(0,0,255)} span#textcolor1997{color:rgb(0,127,0)} span#textcolor1998{color:rgb(0,127,0)} span#textcolor1999{color:rgb(0,127,0)} @@ -2520,394 +2531,394 @@ span#textcolor2016{color:rgb(0,127,0)} span#textcolor2017{color:rgb(0,127,0)} span#textcolor2018{color:rgb(0,127,0)} span#textcolor2019{color:rgb(0,127,0)} -span#textcolor2020{color:rgb(163,20,20)} -span#textcolor2021{color:rgb(163,20,20)} -span#textcolor2022{color:rgb(163,20,20)} -span#textcolor2023{color:rgb(0,0,255)} -span#textcolor2024{color:rgb(43,145,175)} -span#textcolor2025{color:rgb(43,145,175)} -span#textcolor2026{color:rgb(163,20,20)} -span#textcolor2027{color:rgb(0,0,255)} -span#textcolor2028{color:rgb(0,0,255)} -span#textcolor2029{color:rgb(43,145,175)} -span#textcolor2030{color:rgb(43,145,175)} +span#textcolor2020{color:rgb(0,127,0)} +span#textcolor2021{color:rgb(0,127,0)} +span#textcolor2022{color:rgb(0,127,0)} +span#textcolor2023{color:rgb(0,127,0)} +span#textcolor2024{color:rgb(0,127,0)} +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(0,127,0)} +span#textcolor2030{color:rgb(163,20,20)} span#textcolor2031{color:rgb(163,20,20)} span#textcolor2032{color:rgb(163,20,20)} +span#textcolor2033{color:rgb(0,0,255)} +span#textcolor2034{color:rgb(43,145,175)} +span#textcolor2035{color:rgb(43,145,175)} +span#textcolor2036{color:rgb(163,20,20)} +span#textcolor2037{color:rgb(0,0,255)} +span#textcolor2038{color:rgb(0,0,255)} +span#textcolor2039{color:rgb(43,145,175)} +span#textcolor2040{color:rgb(43,145,175)} +span#textcolor2041{color:rgb(163,20,20)} +span#textcolor2042{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#textcolor2033{color:rgb(0,127,0)} -span#textcolor2034{color:rgb(0,127,0)} -span#textcolor2035{color:rgb(0,127,0)} -span#textcolor2036{color:rgb(0,0,255)} -span#textcolor2037{color:rgb(0,127,0)} -span#textcolor2038{color:rgb(0,0,255)} -span#textcolor2039{color:rgb(0,127,0)} -span#textcolor2040{color:rgb(0,0,255)} -span#textcolor2041{color:rgb(0,127,0)} -span#textcolor2042{color:rgb(0,0,255)} span#textcolor2043{color:rgb(0,127,0)} -span#textcolor2044{color:rgb(0,0,255)} +span#textcolor2044{color:rgb(0,127,0)} span#textcolor2045{color:rgb(0,127,0)} span#textcolor2046{color:rgb(0,0,255)} span#textcolor2047{color:rgb(0,127,0)} span#textcolor2048{color:rgb(0,0,255)} span#textcolor2049{color:rgb(0,127,0)} -span#textcolor2050{color:rgb(163,20,20)} -span#textcolor2051{color:rgb(0,0,255)} +span#textcolor2050{color:rgb(0,0,255)} +span#textcolor2051{color:rgb(0,127,0)} span#textcolor2052{color:rgb(0,0,255)} -span#textcolor2053{color:rgb(43,145,175)} +span#textcolor2053{color:rgb(0,127,0)} span#textcolor2054{color:rgb(0,0,255)} -span#textcolor2055{color:rgb(0,0,255)} +span#textcolor2055{color:rgb(0,127,0)} span#textcolor2056{color:rgb(0,0,255)} span#textcolor2057{color:rgb(0,127,0)} -span#textcolor2058{color:rgb(0,127,0)} +span#textcolor2058{color:rgb(0,0,255)} span#textcolor2059{color:rgb(0,127,0)} -span#textcolor2060{color:rgb(0,127,0)} -span#textcolor2061{color:rgb(0,127,0)} -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,127,0)} -span#textcolor2066{color:rgb(0,127,0)} +span#textcolor2060{color:rgb(163,20,20)} +span#textcolor2061{color:rgb(0,0,255)} +span#textcolor2062{color:rgb(0,0,255)} +span#textcolor2063{color:rgb(43,145,175)} +span#textcolor2064{color:rgb(0,0,255)} +span#textcolor2065{color:rgb(0,0,255)} +span#textcolor2066{color:rgb(0,0,255)} span#textcolor2067{color:rgb(0,127,0)} -span#textcolor2068{color:rgb(0,0,255)} -span#textcolor2069{color:rgb(43,145,175)} -span#textcolor2070{color:rgb(43,145,175)} -span#textcolor2071{color:rgb(43,145,175)} -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(0,0,255)} -span#textcolor2077{color:rgb(0,0,255)} +span#textcolor2068{color:rgb(0,127,0)} +span#textcolor2069{color:rgb(0,127,0)} +span#textcolor2070{color:rgb(0,127,0)} +span#textcolor2071{color:rgb(0,127,0)} +span#textcolor2072{color:rgb(0,127,0)} +span#textcolor2073{color:rgb(0,127,0)} +span#textcolor2074{color:rgb(0,127,0)} +span#textcolor2075{color:rgb(0,127,0)} +span#textcolor2076{color:rgb(0,127,0)} +span#textcolor2077{color:rgb(0,127,0)} span#textcolor2078{color:rgb(0,0,255)} -span#textcolor2079{color:rgb(0,0,255)} +span#textcolor2079{color:rgb(43,145,175)} span#textcolor2080{color:rgb(43,145,175)} span#textcolor2081{color:rgb(43,145,175)} span#textcolor2082{color:rgb(43,145,175)} -span#textcolor2083{color:rgb(163,20,20)} -span#textcolor2084{color:rgb(163,20,20)} -span#textcolor2085{color:rgb(163,20,20)} -span#textcolor2086{color:rgb(163,20,20)} -span#textcolor2087{color:rgb(163,20,20)} -span#textcolor2088{color:rgb(163,20,20)} +span#textcolor2083{color:rgb(43,145,175)} +span#textcolor2084{color:rgb(43,145,175)} +span#textcolor2085{color:rgb(43,145,175)} +span#textcolor2086{color:rgb(0,0,255)} +span#textcolor2087{color:rgb(0,0,255)} +span#textcolor2088{color:rgb(0,0,255)} span#textcolor2089{color:rgb(0,0,255)} -span#textcolor2090{color:rgb(0,0,255)} -span#textcolor2091{color:rgb(0,0,255)} -span#textcolor2092{color:rgb(163,20,20)} +span#textcolor2090{color:rgb(43,145,175)} +span#textcolor2091{color:rgb(43,145,175)} +span#textcolor2092{color:rgb(43,145,175)} span#textcolor2093{color:rgb(163,20,20)} span#textcolor2094{color:rgb(163,20,20)} -span#textcolor2095{color:rgb(43,145,175)} -span#textcolor2096{color:rgb(43,145,175)} +span#textcolor2095{color:rgb(163,20,20)} +span#textcolor2096{color:rgb(163,20,20)} span#textcolor2097{color:rgb(163,20,20)} 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(163,20,20)} +span#textcolor2099{color:rgb(0,0,255)} +span#textcolor2100{color:rgb(0,0,255)} +span#textcolor2101{color:rgb(0,0,255)} span#textcolor2102{color:rgb(163,20,20)} -span#textcolor2103{color:rgb(0,127,0)} -span#textcolor2104{color:rgb(43,145,175)} +span#textcolor2103{color:rgb(163,20,20)} +span#textcolor2104{color:rgb(163,20,20)} span#textcolor2105{color:rgb(43,145,175)} span#textcolor2106{color:rgb(43,145,175)} -span#textcolor2107{color:rgb(0,0,255)} -span#textcolor2108{color:rgb(0,0,255)} -span#textcolor2109{color:rgb(43,145,175)} -span#textcolor2110{color:rgb(43,145,175)} +span#textcolor2107{color:rgb(163,20,20)} +span#textcolor2108{color:rgb(163,20,20)} +span#textcolor2109{color:rgb(163,20,20)} +span#textcolor2110{color:rgb(163,20,20)} span#textcolor2111{color:rgb(163,20,20)} span#textcolor2112{color:rgb(163,20,20)} -span#textcolor2113{color:rgb(163,20,20)} -span#textcolor2114{color:rgb(163,20,20)} +span#textcolor2113{color:rgb(0,127,0)} +span#textcolor2114{color:rgb(43,145,175)} +span#textcolor2115{color:rgb(43,145,175)} +span#textcolor2116{color:rgb(43,145,175)} +span#textcolor2117{color:rgb(0,0,255)} +span#textcolor2118{color:rgb(0,0,255)} +span#textcolor2119{color:rgb(43,145,175)} +span#textcolor2120{color:rgb(43,145,175)} +span#textcolor2121{color:rgb(163,20,20)} +span#textcolor2122{color:rgb(163,20,20)} +span#textcolor2123{color:rgb(163,20,20)} +span#textcolor2124{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#textcolor2115{color:rgb(0,127,0)} -span#textcolor2116{color:rgb(0,127,0)} -span#textcolor2117{color:rgb(0,127,0)} -span#textcolor2118{color:rgb(0,0,255)} -span#textcolor2119{color:rgb(0,127,0)} -span#textcolor2120{color:rgb(0,0,255)} -span#textcolor2121{color:rgb(0,127,0)} -span#textcolor2122{color:rgb(0,0,255)} -span#textcolor2123{color:rgb(0,127,0)} -span#textcolor2124{color:rgb(0,0,255)} span#textcolor2125{color:rgb(0,127,0)} -span#textcolor2126{color:rgb(0,0,255)} -span#textcolor2127{color:rgb(43,145,175)} -span#textcolor2128{color:rgb(43,145,175)} -span#textcolor2129{color:rgb(43,145,175)} -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(163,20,20)} -span#textcolor2134{color:rgb(163,20,20)} -span#textcolor2135{color:rgb(163,20,20)} -span#textcolor2136{color:rgb(0,0,255)} -span#textcolor2137{color:rgb(43,145,175)} -span#textcolor2138{color:rgb(43,145,175)} -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(163,20,20)} -span#textcolor2143{color:rgb(163,20,20)} -span#textcolor2144{color:rgb(163,20,20)} -span#textcolor2145{color:rgb(0,0,255)} -span#textcolor2146{color:rgb(0,0,255)} -span#textcolor2147{color:rgb(43,145,175)} -span#textcolor2148{color:rgb(43,145,175)} +span#textcolor2126{color:rgb(0,127,0)} +span#textcolor2127{color:rgb(0,127,0)} +span#textcolor2128{color:rgb(0,0,255)} +span#textcolor2129{color:rgb(0,127,0)} +span#textcolor2130{color:rgb(0,0,255)} +span#textcolor2131{color:rgb(0,127,0)} +span#textcolor2132{color:rgb(0,0,255)} +span#textcolor2133{color:rgb(0,127,0)} +span#textcolor2134{color:rgb(0,0,255)} +span#textcolor2135{color:rgb(0,127,0)} +span#textcolor2136{color:rgb(0,127,0)} +span#textcolor2137{color:rgb(0,127,0)} +span#textcolor2138{color:rgb(0,127,0)} +span#textcolor2139{color:rgb(0,0,255)} +span#textcolor2140{color:rgb(0,0,255)} +span#textcolor2141{color:rgb(0,0,255)} +span#textcolor2142{color:rgb(0,0,255)} +span#textcolor2143{color:rgb(43,145,175)} +span#textcolor2144{color:rgb(43,145,175)} +span#textcolor2145{color:rgb(43,145,175)} +span#textcolor2146{color:rgb(163,20,20)} +span#textcolor2147{color:rgb(163,20,20)} +span#textcolor2148{color:rgb(163,20,20)} span#textcolor2149{color:rgb(163,20,20)} span#textcolor2150{color:rgb(163,20,20)} span#textcolor2151{color:rgb(163,20,20)} -span#textcolor2152{color:rgb(163,20,20)} -span#textcolor2153{color:rgb(163,20,20)} +span#textcolor2152{color:rgb(0,0,255)} +span#textcolor2153{color:rgb(43,145,175)} +span#textcolor2154{color:rgb(43,145,175)} +span#textcolor2155{color:rgb(163,20,20)} +span#textcolor2156{color:rgb(163,20,20)} +span#textcolor2157{color:rgb(163,20,20)} +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(0,0,255)} +span#textcolor2162{color:rgb(0,0,255)} +span#textcolor2163{color:rgb(43,145,175)} +span#textcolor2164{color:rgb(43,145,175)} +span#textcolor2165{color:rgb(163,20,20)} +span#textcolor2166{color:rgb(163,20,20)} +span#textcolor2167{color:rgb(163,20,20)} +span#textcolor2168{color:rgb(163,20,20)} +span#textcolor2169{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#textcolor2154{color:rgb(0,127,0)} -span#textcolor2155{color:rgb(0,127,0)} -span#textcolor2156{color:rgb(0,127,0)} -span#textcolor2157{color:rgb(0,0,255)} -span#textcolor2158{color:rgb(0,127,0)} -span#textcolor2159{color:rgb(0,0,255)} -span#textcolor2160{color:rgb(0,127,0)} -span#textcolor2161{color:rgb(0,0,255)} -span#textcolor2162{color:rgb(0,127,0)} -span#textcolor2163{color:rgb(0,0,255)} -span#textcolor2164{color:rgb(0,0,255)} -span#textcolor2165{color:rgb(0,0,255)} -span#textcolor2166{color:rgb(0,0,255)} -span#textcolor2167{color:rgb(0,0,255)} -span#textcolor2168{color:rgb(43,145,175)} -span#textcolor2169{color:rgb(0,0,255)} -span#textcolor2170{color:rgb(163,20,20)} -span#textcolor2171{color:rgb(163,20,20)} -span#textcolor2172{color:rgb(163,20,20)} +span#textcolor2170{color:rgb(0,127,0)} +span#textcolor2171{color:rgb(0,127,0)} +span#textcolor2172{color:rgb(0,127,0)} span#textcolor2173{color:rgb(0,0,255)} -span#textcolor2174{color:rgb(43,145,175)} -span#textcolor2175{color:rgb(43,145,175)} -span#textcolor2176{color:rgb(163,20,20)} +span#textcolor2174{color:rgb(0,127,0)} +span#textcolor2175{color:rgb(0,0,255)} +span#textcolor2176{color:rgb(0,127,0)} span#textcolor2177{color:rgb(0,0,255)} -span#textcolor2178{color:rgb(0,0,255)} -span#textcolor2179{color:rgb(43,145,175)} -span#textcolor2180{color:rgb(43,145,175)} -span#textcolor2181{color:rgb(163,20,20)} -span#textcolor2182{color:rgb(163,20,20)} +span#textcolor2178{color:rgb(0,127,0)} +span#textcolor2179{color:rgb(0,0,255)} +span#textcolor2180{color:rgb(0,0,255)} +span#textcolor2181{color:rgb(0,0,255)} +span#textcolor2182{color:rgb(0,0,255)} +span#textcolor2183{color:rgb(0,0,255)} +span#textcolor2184{color:rgb(43,145,175)} +span#textcolor2185{color:rgb(0,0,255)} +span#textcolor2186{color:rgb(163,20,20)} +span#textcolor2187{color:rgb(163,20,20)} +span#textcolor2188{color:rgb(163,20,20)} +span#textcolor2189{color:rgb(0,0,255)} +span#textcolor2190{color:rgb(43,145,175)} +span#textcolor2191{color:rgb(43,145,175)} +span#textcolor2192{color:rgb(163,20,20)} +span#textcolor2193{color:rgb(0,0,255)} +span#textcolor2194{color:rgb(0,0,255)} +span#textcolor2195{color:rgb(43,145,175)} +span#textcolor2196{color:rgb(43,145,175)} +span#textcolor2197{color:rgb(163,20,20)} +span#textcolor2198{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#textcolor2183{color:rgb(0,127,0)} -span#textcolor2184{color:rgb(0,127,0)} -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,0,255)} -span#textcolor2195{color:rgb(0,127,0)} -span#textcolor2196{color:rgb(0,0,255)} -span#textcolor2197{color:rgb(0,127,0)} -span#textcolor2198{color:rgb(0,0,255)} span#textcolor2199{color:rgb(0,127,0)} -span#textcolor2200{color:rgb(0,0,255)} -span#textcolor2201{color:rgb(43,145,175)} +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,0,255)} -span#textcolor2206{color:rgb(0,0,255)} -span#textcolor2207{color:rgb(163,20,20)} -span#textcolor2208{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,0,255)} span#textcolor2209{color:rgb(0,127,0)} -span#textcolor2210{color:rgb(0,127,0)} -span#textcolor2211{color:rgb(0,0,255)} +span#textcolor2210{color:rgb(0,0,255)} +span#textcolor2211{color:rgb(0,127,0)} span#textcolor2212{color:rgb(0,0,255)} -span#textcolor2213{color:rgb(163,20,20)} -span#textcolor2214{color:rgb(163,20,20)} +span#textcolor2213{color:rgb(0,127,0)} +span#textcolor2214{color:rgb(0,0,255)} span#textcolor2215{color:rgb(0,127,0)} span#textcolor2216{color:rgb(0,0,255)} span#textcolor2217{color:rgb(43,145,175)} -span#textcolor2218{color:rgb(43,145,175)} +span#textcolor2218{color:rgb(0,127,0)} span#textcolor2219{color:rgb(0,127,0)} -span#textcolor2220{color:rgb(0,0,255)} -span#textcolor2221{color:rgb(0,127,0)} +span#textcolor2220{color:rgb(0,127,0)} +span#textcolor2221{color:rgb(0,0,255)} span#textcolor2222{color:rgb(0,0,255)} -span#textcolor2223{color:rgb(0,0,255)} -span#textcolor2224{color:rgb(0,0,255)} -span#textcolor2225{color:rgb(0,0,255)} -span#textcolor2226{color:rgb(43,145,175)} -span#textcolor2227{color:rgb(43,145,175)} -span#textcolor2228{color:rgb(43,145,175)} +span#textcolor2223{color:rgb(163,20,20)} +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,0,255)} +span#textcolor2228{color:rgb(0,0,255)} 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,127,0)} -span#textcolor2233{color:rgb(0,0,255)} -span#textcolor2234{color:rgb(163,20,20)} -span#textcolor2235{color:rgb(163,20,20)} -span#textcolor2236{color:rgb(163,20,20)} -span#textcolor2237{color:rgb(0,0,255)} -span#textcolor2238{color:rgb(0,127,0)} +span#textcolor2231{color:rgb(0,127,0)} +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(0,127,0)} +span#textcolor2236{color:rgb(0,0,255)} +span#textcolor2237{color:rgb(0,127,0)} +span#textcolor2238{color:rgb(0,0,255)} span#textcolor2239{color:rgb(0,0,255)} -span#textcolor2240{color:rgb(163,20,20)} -span#textcolor2241{color:rgb(163,20,20)} -span#textcolor2242{color:rgb(163,20,20)} -span#textcolor2243{color:rgb(0,0,255)} -span#textcolor2244{color:rgb(163,20,20)} +span#textcolor2240{color:rgb(0,0,255)} +span#textcolor2241{color:rgb(0,0,255)} +span#textcolor2242{color:rgb(43,145,175)} +span#textcolor2243{color:rgb(43,145,175)} +span#textcolor2244{color:rgb(43,145,175)} span#textcolor2245{color:rgb(163,20,20)} span#textcolor2246{color:rgb(163,20,20)} -span#textcolor2247{color:rgb(0,0,255)} -span#textcolor2248{color:rgb(163,20,20)} -span#textcolor2249{color:rgb(163,20,20)} +span#textcolor2247{color:rgb(163,20,20)} +span#textcolor2248{color:rgb(0,127,0)} +span#textcolor2249{color:rgb(0,0,255)} span#textcolor2250{color:rgb(163,20,20)} -span#textcolor2251{color:rgb(0,0,255)} +span#textcolor2251{color:rgb(163,20,20)} span#textcolor2252{color:rgb(163,20,20)} -span#textcolor2253{color:rgb(163,20,20)} -span#textcolor2254{color:rgb(163,20,20)} -span#textcolor2255{color:rgb(163,20,20)} -span#textcolor2256{color:rgb(0,0,255)} +span#textcolor2253{color:rgb(0,0,255)} +span#textcolor2254{color:rgb(0,127,0)} +span#textcolor2255{color:rgb(0,0,255)} +span#textcolor2256{color:rgb(163,20,20)} span#textcolor2257{color:rgb(163,20,20)} 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#textcolor2259{color:rgb(0,0,255)} +span#textcolor2260{color:rgb(163,20,20)} +span#textcolor2261{color:rgb(163,20,20)} span#textcolor2262{color:rgb(163,20,20)} -span#textcolor2263{color:rgb(163,20,20)} +span#textcolor2263{color:rgb(0,0,255)} span#textcolor2264{color:rgb(163,20,20)} -span#textcolor2265{color:rgb(0,0,255)} +span#textcolor2265{color:rgb(163,20,20)} span#textcolor2266{color:rgb(163,20,20)} -span#textcolor2267{color:rgb(163,20,20)} +span#textcolor2267{color:rgb(0,0,255)} span#textcolor2268{color:rgb(163,20,20)} span#textcolor2269{color:rgb(163,20,20)} -span#textcolor2270{color:rgb(0,0,255)} +span#textcolor2270{color:rgb(163,20,20)} span#textcolor2271{color:rgb(163,20,20)} -span#textcolor2272{color:rgb(163,20,20)} +span#textcolor2272{color:rgb(0,0,255)} span#textcolor2273{color:rgb(163,20,20)} -span#textcolor2274{color:rgb(0,0,255)} -span#textcolor2275{color:rgb(0,0,255)} -span#textcolor2276{color:rgb(0,127,0)} +span#textcolor2274{color:rgb(163,20,20)} +span#textcolor2275{color:rgb(163,20,20)} +span#textcolor2276{color:rgb(0,0,255)} span#textcolor2277{color:rgb(0,0,255)} -span#textcolor2278{color:rgb(0,0,255)} -span#textcolor2279{color:rgb(43,145,175)} -span#textcolor2280{color:rgb(43,145,175)} -span#textcolor2281{color:rgb(43,145,175)} +span#textcolor2278{color:rgb(163,20,20)} +span#textcolor2279{color:rgb(163,20,20)} +span#textcolor2280{color:rgb(163,20,20)} +span#textcolor2281{color:rgb(0,0,255)} span#textcolor2282{color:rgb(163,20,20)} span#textcolor2283{color:rgb(163,20,20)} span#textcolor2284{color:rgb(163,20,20)} -span#textcolor2285{color:rgb(0,127,0)} -span#textcolor2286{color:rgb(0,127,0)} -span#textcolor2287{color:rgb(0,0,255)} -span#textcolor2288{color:rgb(0,127,0)} +span#textcolor2285{color:rgb(163,20,20)} +span#textcolor2286{color:rgb(0,0,255)} +span#textcolor2287{color:rgb(163,20,20)} +span#textcolor2288{color:rgb(163,20,20)} span#textcolor2289{color:rgb(163,20,20)} -span#textcolor2290{color:rgb(163,20,20)} +span#textcolor2290{color:rgb(0,0,255)} +span#textcolor2291{color:rgb(0,0,255)} +span#textcolor2292{color:rgb(0,127,0)} +span#textcolor2293{color:rgb(0,0,255)} +span#textcolor2294{color:rgb(0,0,255)} +span#textcolor2295{color:rgb(43,145,175)} +span#textcolor2296{color:rgb(43,145,175)} +span#textcolor2297{color:rgb(43,145,175)} +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,127,0)} +span#textcolor2302{color:rgb(0,127,0)} +span#textcolor2303{color:rgb(0,0,255)} +span#textcolor2304{color:rgb(0,127,0)} +span#textcolor2305{color:rgb(163,20,20)} +span#textcolor2306{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#textcolor2291{color:rgb(0,127,0)} -span#textcolor2292{color:rgb(0,127,0)} -span#textcolor2293{color:rgb(0,127,0)} -span#textcolor2294{color:rgb(0,127,0)} -span#textcolor2295{color:rgb(0,127,0)} -span#textcolor2296{color:rgb(0,127,0)} -span#textcolor2297{color:rgb(0,127,0)} -span#textcolor2298{color:rgb(0,127,0)} -span#textcolor2299{color:rgb(0,127,0)} -span#textcolor2300{color:rgb(0,0,255)} -span#textcolor2301{color:rgb(0,127,0)} -span#textcolor2302{color:rgb(0,0,255)} -span#textcolor2303{color:rgb(0,127,0)} -span#textcolor2304{color:rgb(0,0,255)} -span#textcolor2305{color:rgb(0,127,0)} -span#textcolor2306{color:rgb(0,0,255)} span#textcolor2307{color:rgb(0,127,0)} -span#textcolor2308{color:rgb(0,0,255)} +span#textcolor2308{color:rgb(0,127,0)} span#textcolor2309{color:rgb(0,127,0)} -span#textcolor2310{color:rgb(0,0,255)} -span#textcolor2311{color:rgb(43,145,175)} +span#textcolor2310{color:rgb(0,127,0)} +span#textcolor2311{color:rgb(0,127,0)} span#textcolor2312{color:rgb(0,127,0)} span#textcolor2313{color:rgb(0,127,0)} span#textcolor2314{color:rgb(0,127,0)} -span#textcolor2315{color:rgb(0,0,255)} +span#textcolor2315{color:rgb(0,127,0)} span#textcolor2316{color:rgb(0,0,255)} -span#textcolor2317{color:rgb(163,20,20)} -span#textcolor2318{color:rgb(0,127,0)} +span#textcolor2317{color:rgb(0,127,0)} +span#textcolor2318{color:rgb(0,0,255)} span#textcolor2319{color:rgb(0,127,0)} -span#textcolor2320{color:rgb(0,127,0)} -span#textcolor2321{color:rgb(0,0,255)} +span#textcolor2320{color:rgb(0,0,255)} +span#textcolor2321{color:rgb(0,127,0)} span#textcolor2322{color:rgb(0,0,255)} -span#textcolor2323{color:rgb(163,20,20)} -span#textcolor2324{color:rgb(163,20,20)} +span#textcolor2323{color:rgb(0,127,0)} +span#textcolor2324{color:rgb(0,0,255)} span#textcolor2325{color:rgb(0,127,0)} -span#textcolor2326{color:rgb(0,0,255)} -span#textcolor2327{color:rgb(43,145,175)} -span#textcolor2328{color:rgb(43,145,175)} -span#textcolor2329{color:rgb(43,145,175)} -span#textcolor2330{color:rgb(163,20,20)} -span#textcolor2331{color:rgb(163,20,20)} -span#textcolor2332{color:rgb(163,20,20)} -span#textcolor2333{color:rgb(0,127,0)} -span#textcolor2334{color:rgb(163,20,20)} -span#textcolor2335{color:rgb(163,20,20)} -span#textcolor2336{color:rgb(163,20,20)} -span#textcolor2337{color:rgb(0,127,0)} +span#textcolor2326{color:rgb(0,127,0)} +span#textcolor2327{color:rgb(0,127,0)} +span#textcolor2328{color:rgb(0,127,0)} +span#textcolor2329{color:rgb(0,0,255)} +span#textcolor2330{color:rgb(0,0,255)} +span#textcolor2331{color:rgb(0,0,255)} +span#textcolor2332{color:rgb(0,0,255)} +span#textcolor2333{color:rgb(43,145,175)} +span#textcolor2334{color:rgb(0,127,0)} +span#textcolor2335{color:rgb(0,127,0)} +span#textcolor2336{color:rgb(0,127,0)} +span#textcolor2337{color:rgb(0,0,255)} span#textcolor2338{color:rgb(0,0,255)} -span#textcolor2339{color:rgb(43,145,175)} -span#textcolor2340{color:rgb(43,145,175)} +span#textcolor2339{color:rgb(163,20,20)} +span#textcolor2340{color:rgb(0,127,0)} span#textcolor2341{color:rgb(0,127,0)} -span#textcolor2342{color:rgb(0,0,255)} +span#textcolor2342{color:rgb(0,127,0)} span#textcolor2343{color:rgb(0,0,255)} span#textcolor2344{color:rgb(0,0,255)} -span#textcolor2345{color:rgb(0,127,0)} -span#textcolor2346{color:rgb(0,0,255)} -span#textcolor2347{color:rgb(0,0,255)} -span#textcolor2348{color:rgb(43,145,175)} +span#textcolor2345{color:rgb(163,20,20)} +span#textcolor2346{color:rgb(163,20,20)} +span#textcolor2347{color:rgb(0,127,0)} +span#textcolor2348{color:rgb(0,0,255)} span#textcolor2349{color:rgb(43,145,175)} span#textcolor2350{color:rgb(43,145,175)} -span#textcolor2351{color:rgb(163,20,20)} +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(0,127,0)} -span#textcolor2355{color:rgb(0,0,255)} +span#textcolor2354{color:rgb(163,20,20)} +span#textcolor2355{color:rgb(0,127,0)} span#textcolor2356{color:rgb(163,20,20)} span#textcolor2357{color:rgb(163,20,20)} span#textcolor2358{color:rgb(163,20,20)} -span#textcolor2359{color:rgb(0,0,255)} -span#textcolor2360{color:rgb(0,127,0)} -span#textcolor2361{color:rgb(0,0,255)} -span#textcolor2362{color:rgb(163,20,20)} -span#textcolor2363{color:rgb(163,20,20)} -span#textcolor2364{color:rgb(163,20,20)} +span#textcolor2359{color:rgb(0,127,0)} +span#textcolor2360{color:rgb(0,0,255)} +span#textcolor2361{color:rgb(43,145,175)} +span#textcolor2362{color:rgb(43,145,175)} +span#textcolor2363{color:rgb(0,127,0)} +span#textcolor2364{color:rgb(0,0,255)} span#textcolor2365{color:rgb(0,0,255)} -span#textcolor2366{color:rgb(163,20,20)} -span#textcolor2367{color:rgb(163,20,20)} -span#textcolor2368{color:rgb(163,20,20)} +span#textcolor2366{color:rgb(0,0,255)} +span#textcolor2367{color:rgb(0,127,0)} +span#textcolor2368{color:rgb(0,0,255)} span#textcolor2369{color:rgb(0,0,255)} -span#textcolor2370{color:rgb(163,20,20)} -span#textcolor2371{color:rgb(163,20,20)} -span#textcolor2372{color:rgb(163,20,20)} -span#textcolor2373{color:rgb(0,0,255)} +span#textcolor2370{color:rgb(43,145,175)} +span#textcolor2371{color:rgb(43,145,175)} +span#textcolor2372{color:rgb(43,145,175)} +span#textcolor2373{color:rgb(163,20,20)} span#textcolor2374{color:rgb(163,20,20)} span#textcolor2375{color:rgb(163,20,20)} -span#textcolor2376{color:rgb(163,20,20)} -span#textcolor2377{color:rgb(163,20,20)} -span#textcolor2378{color:rgb(0,0,255)} +span#textcolor2376{color:rgb(0,127,0)} +span#textcolor2377{color:rgb(0,0,255)} +span#textcolor2378{color:rgb(163,20,20)} span#textcolor2379{color:rgb(163,20,20)} span#textcolor2380{color:rgb(163,20,20)} -span#textcolor2381{color:rgb(163,20,20)} -span#textcolor2382{color:rgb(0,0,255)} +span#textcolor2381{color:rgb(0,0,255)} +span#textcolor2382{color:rgb(0,127,0)} span#textcolor2383{color:rgb(0,0,255)} span#textcolor2384{color:rgb(163,20,20)} span#textcolor2385{color:rgb(163,20,20)} @@ -2916,84 +2927,106 @@ span#textcolor2387{color:rgb(0,0,255)} span#textcolor2388{color:rgb(163,20,20)} span#textcolor2389{color:rgb(163,20,20)} span#textcolor2390{color:rgb(163,20,20)} -span#textcolor2391{color:rgb(163,20,20)} -span#textcolor2392{color:rgb(0,0,255)} +span#textcolor2391{color:rgb(0,0,255)} +span#textcolor2392{color:rgb(163,20,20)} span#textcolor2393{color:rgb(163,20,20)} span#textcolor2394{color:rgb(163,20,20)} -span#textcolor2395{color:rgb(163,20,20)} -span#textcolor2396{color:rgb(0,0,255)} -span#textcolor2397{color:rgb(0,0,255)} -span#textcolor2398{color:rgb(0,127,0)} -span#textcolor2399{color:rgb(0,0,255)} +span#textcolor2395{color:rgb(0,0,255)} +span#textcolor2396{color:rgb(163,20,20)} +span#textcolor2397{color:rgb(163,20,20)} +span#textcolor2398{color:rgb(163,20,20)} +span#textcolor2399{color:rgb(163,20,20)} span#textcolor2400{color:rgb(0,0,255)} -span#textcolor2401{color:rgb(43,145,175)} -span#textcolor2402{color:rgb(43,145,175)} -span#textcolor2403{color:rgb(43,145,175)} -span#textcolor2404{color:rgb(163,20,20)} -span#textcolor2405{color:rgb(163,20,20)} +span#textcolor2401{color:rgb(163,20,20)} +span#textcolor2402{color:rgb(163,20,20)} +span#textcolor2403{color:rgb(163,20,20)} +span#textcolor2404{color:rgb(0,0,255)} +span#textcolor2405{color:rgb(0,0,255)} span#textcolor2406{color:rgb(163,20,20)} -span#textcolor2407{color:rgb(0,127,0)} -span#textcolor2408{color:rgb(0,127,0)} +span#textcolor2407{color:rgb(163,20,20)} +span#textcolor2408{color:rgb(163,20,20)} span#textcolor2409{color:rgb(0,0,255)} -span#textcolor2410{color:rgb(0,127,0)} +span#textcolor2410{color:rgb(163,20,20)} span#textcolor2411{color:rgb(163,20,20)} span#textcolor2412{color:rgb(163,20,20)} +span#textcolor2413{color:rgb(163,20,20)} +span#textcolor2414{color:rgb(0,0,255)} +span#textcolor2415{color:rgb(163,20,20)} +span#textcolor2416{color:rgb(163,20,20)} +span#textcolor2417{color:rgb(163,20,20)} +span#textcolor2418{color:rgb(0,0,255)} +span#textcolor2419{color:rgb(0,0,255)} +span#textcolor2420{color:rgb(0,127,0)} +span#textcolor2421{color:rgb(0,0,255)} +span#textcolor2422{color:rgb(0,0,255)} +span#textcolor2423{color:rgb(43,145,175)} +span#textcolor2424{color:rgb(43,145,175)} +span#textcolor2425{color:rgb(43,145,175)} +span#textcolor2426{color:rgb(163,20,20)} +span#textcolor2427{color:rgb(163,20,20)} +span#textcolor2428{color:rgb(163,20,20)} +span#textcolor2429{color:rgb(0,127,0)} +span#textcolor2430{color:rgb(0,127,0)} +span#textcolor2431{color:rgb(0,0,255)} +span#textcolor2432{color:rgb(0,127,0)} +span#textcolor2433{color:rgb(163,20,20)} +span#textcolor2434{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; } -span#textcolor2413{color:rgb(0,127,0)} -span#textcolor2414{color:rgb(0,127,0)} -span#textcolor2415{color:rgb(0,127,0)} -span#textcolor2416{color:rgb(0,0,255)} -span#textcolor2417{color:rgb(0,127,0)} -span#textcolor2418{color:rgb(0,0,255)} -span#textcolor2419{color:rgb(0,127,0)} -span#textcolor2420{color:rgb(0,0,255)} -span#textcolor2421{color:rgb(0,0,255)} -span#textcolor2422{color:rgb(43,145,175)} -span#textcolor2423{color:rgb(43,145,175)} -span#textcolor2424{color:rgb(43,145,175)} -span#textcolor2425{color:rgb(43,145,175)} -span#textcolor2426{color:rgb(43,145,175)} -span#textcolor2427{color:rgb(163,20,20)} -span#textcolor2428{color:rgb(163,20,20)} -span#textcolor2429{color:rgb(163,20,20)} -span#textcolor2430{color:rgb(163,20,20)} -span#textcolor2431{color:rgb(163,20,20)} -span#textcolor2432{color:rgb(0,0,255)} -span#textcolor2433{color:rgb(163,20,20)} -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(43,145,175)} -span#textcolor2440{color:rgb(43,145,175)} -span#textcolor2441{color:rgb(43,145,175)} -span#textcolor2442{color:rgb(163,20,20)} -span#textcolor2443{color:rgb(43,145,175)} -span#textcolor2444{color:rgb(0,0,255)} -span#textcolor2445{color:rgb(0,0,255)} -span#textcolor2446{color:rgb(163,20,20)} -span#textcolor2447{color:rgb(0,0,255)} -span#textcolor2448{color:rgb(0,0,255)} -span#textcolor2449{color:rgb(0,0,255)} -span#textcolor2450{color:rgb(0,0,255)} -span#textcolor2451{color:rgb(0,0,255)} -span#textcolor2452{color:rgb(0,0,255)} -span#textcolor2453{color:rgb(0,0,255)} +span#textcolor2435{color:rgb(0,127,0)} +span#textcolor2436{color:rgb(0,127,0)} +span#textcolor2437{color:rgb(0,127,0)} +span#textcolor2438{color:rgb(0,0,255)} +span#textcolor2439{color:rgb(0,127,0)} +span#textcolor2440{color:rgb(0,0,255)} +span#textcolor2441{color:rgb(0,127,0)} +span#textcolor2442{color:rgb(0,0,255)} +span#textcolor2443{color:rgb(0,0,255)} +span#textcolor2444{color:rgb(43,145,175)} +span#textcolor2445{color:rgb(43,145,175)} +span#textcolor2446{color:rgb(43,145,175)} +span#textcolor2447{color:rgb(43,145,175)} +span#textcolor2448{color:rgb(43,145,175)} +span#textcolor2449{color:rgb(163,20,20)} +span#textcolor2450{color:rgb(163,20,20)} +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(0,0,255)} -span#textcolor2456{color:rgb(0,0,255)} -span#textcolor2457{color:rgb(0,0,255)} -span#textcolor2458{color:rgb(0,0,255)} -span#textcolor2459{color:rgb(0,0,255)} -span#textcolor2460{color:rgb(43,145,175)} +span#textcolor2455{color:rgb(163,20,20)} +span#textcolor2456{color:rgb(43,145,175)} +span#textcolor2457{color:rgb(43,145,175)} +span#textcolor2458{color:rgb(163,20,20)} +span#textcolor2459{color:rgb(163,20,20)} +span#textcolor2460{color:rgb(163,20,20)} span#textcolor2461{color:rgb(43,145,175)} -span#textcolor2462{color:rgb(163,20,20)} -span#textcolor2463{color:rgb(163,20,20)} +span#textcolor2462{color:rgb(43,145,175)} +span#textcolor2463{color:rgb(43,145,175)} +span#textcolor2464{color:rgb(163,20,20)} +span#textcolor2465{color:rgb(43,145,175)} +span#textcolor2466{color:rgb(0,0,255)} +span#textcolor2467{color:rgb(0,0,255)} +span#textcolor2468{color:rgb(163,20,20)} +span#textcolor2469{color:rgb(0,0,255)} +span#textcolor2470{color:rgb(0,0,255)} +span#textcolor2471{color:rgb(0,0,255)} +span#textcolor2472{color:rgb(0,0,255)} +span#textcolor2473{color:rgb(0,0,255)} +span#textcolor2474{color:rgb(0,0,255)} +span#textcolor2475{color:rgb(0,0,255)} +span#textcolor2476{color:rgb(0,0,255)} +span#textcolor2477{color:rgb(0,0,255)} +span#textcolor2478{color:rgb(0,0,255)} +span#textcolor2479{color:rgb(0,0,255)} +span#textcolor2480{color:rgb(0,0,255)} +span#textcolor2481{color:rgb(0,0,255)} +span#textcolor2482{color:rgb(43,145,175)} +span#textcolor2483{color:rgb(43,145,175)} +span#textcolor2484{color:rgb(163,20,20)} +span#textcolor2485{color:rgb(163,20,20)} pre#fancyvrb68{padding:5.69054pt;} pre#fancyvrb68{ border-top: solid 0.4pt; } pre#fancyvrb68{ border-left: solid 0.4pt; } @@ -3009,240 +3042,244 @@ 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#textcolor2464{color:rgb(0,127,0)} -span#textcolor2465{color:rgb(0,127,0)} -span#textcolor2466{color:rgb(0,127,0)} -span#textcolor2467{color:rgb(0,0,255)} -span#textcolor2468{color:rgb(0,127,0)} -span#textcolor2469{color:rgb(0,0,255)} -span#textcolor2470{color:rgb(0,127,0)} -span#textcolor2471{color:rgb(0,0,255)} -span#textcolor2472{color:rgb(0,127,0)} -span#textcolor2473{color:rgb(0,0,255)} -span#textcolor2474{color:rgb(0,0,255)} -span#textcolor2475{color:rgb(0,0,255)} -span#textcolor2476{color:rgb(0,0,255)} -span#textcolor2477{color:rgb(43,145,175)} -span#textcolor2478{color:rgb(0,0,255)} -span#textcolor2479{color:rgb(0,0,255)} -span#textcolor2480{color:rgb(0,0,255)} -span#textcolor2481{color:rgb(0,0,255)} -span#textcolor2482{color:rgb(0,0,255)} -span#textcolor2483{color:rgb(43,145,175)} -span#textcolor2484{color:rgb(43,145,175)} -span#textcolor2485{color:rgb(43,145,175)} -span#textcolor2486{color:rgb(0,0,255)} -span#textcolor2487{color:rgb(0,0,255)} -span#textcolor2488{color:rgb(0,0,255)} -span#textcolor2489{color:rgb(43,145,175)} -span#textcolor2490{color:rgb(0,0,255)} +span#textcolor2486{color:rgb(0,127,0)} +span#textcolor2487{color:rgb(0,127,0)} +span#textcolor2488{color:rgb(0,127,0)} +span#textcolor2489{color:rgb(0,0,255)} +span#textcolor2490{color:rgb(0,127,0)} span#textcolor2491{color:rgb(0,0,255)} -span#textcolor2492{color:rgb(0,0,255)} +span#textcolor2492{color:rgb(0,127,0)} span#textcolor2493{color:rgb(0,0,255)} -span#textcolor2494{color:rgb(0,0,255)} +span#textcolor2494{color:rgb(0,127,0)} span#textcolor2495{color:rgb(0,0,255)} -span#textcolor2496{color:rgb(0,0,255)} -span#textcolor2497{color:rgb(43,145,175)} -span#textcolor2498{color:rgb(0,0,255)} -span#textcolor2499{color:rgb(43,145,175)} +span#textcolor2496{color:rgb(0,127,0)} +span#textcolor2497{color:rgb(0,0,255)} +span#textcolor2498{color:rgb(0,127,0)} +span#textcolor2499{color:rgb(0,0,255)} span#textcolor2500{color:rgb(0,0,255)} span#textcolor2501{color:rgb(0,0,255)} span#textcolor2502{color:rgb(0,0,255)} -span#textcolor2503{color:rgb(0,0,255)} +span#textcolor2503{color:rgb(43,145,175)} span#textcolor2504{color:rgb(0,0,255)} span#textcolor2505{color:rgb(0,0,255)} -span#textcolor2506{color:rgb(163,20,20)} -span#textcolor2507{color:rgb(163,20,20)} -span#textcolor2508{color:rgb(163,20,20)} -span#textcolor2509{color:rgb(0,0,255)} -span#textcolor2510{color:rgb(0,0,255)} -span#textcolor2511{color:rgb(163,20,20)} -span#textcolor2512{color:rgb(163,20,20)} -span#textcolor2513{color:rgb(163,20,20)} +span#textcolor2506{color:rgb(0,0,255)} +span#textcolor2507{color:rgb(0,0,255)} +span#textcolor2508{color:rgb(0,0,255)} +span#textcolor2509{color:rgb(43,145,175)} +span#textcolor2510{color:rgb(43,145,175)} +span#textcolor2511{color:rgb(43,145,175)} +span#textcolor2512{color:rgb(0,0,255)} +span#textcolor2513{color:rgb(0,0,255)} span#textcolor2514{color:rgb(0,0,255)} -span#textcolor2515{color:rgb(0,0,255)} +span#textcolor2515{color:rgb(43,145,175)} span#textcolor2516{color:rgb(0,0,255)} -span#textcolor2517{color:rgb(43,145,175)} +span#textcolor2517{color:rgb(0,0,255)} span#textcolor2518{color:rgb(0,0,255)} -span#textcolor2519{color:rgb(43,145,175)} +span#textcolor2519{color:rgb(0,0,255)} span#textcolor2520{color:rgb(0,0,255)} span#textcolor2521{color:rgb(0,0,255)} span#textcolor2522{color:rgb(0,0,255)} -span#textcolor2523{color:rgb(163,20,20)} -span#textcolor2524{color:rgb(163,20,20)} -span#textcolor2525{color:rgb(163,20,20)} -span#textcolor2526{color:rgb(0,127,0)} +span#textcolor2523{color:rgb(43,145,175)} +span#textcolor2524{color:rgb(0,0,255)} +span#textcolor2525{color:rgb(43,145,175)} +span#textcolor2526{color:rgb(0,0,255)} span#textcolor2527{color:rgb(0,0,255)} -span#textcolor2528{color:rgb(0,127,0)} -span#textcolor2529{color:rgb(0,127,0)} -span#textcolor2530{color:rgb(0,127,0)} -span#textcolor2531{color:rgb(0,127,0)} -span#textcolor2532{color:rgb(0,127,0)} -span#textcolor2533{color:rgb(0,127,0)} -span#textcolor2534{color:rgb(0,127,0)} -span#textcolor2535{color:rgb(0,127,0)} -span#textcolor2536{color:rgb(0,127,0)} -span#textcolor2537{color:rgb(0,0,255)} -span#textcolor2538{color:rgb(0,0,255)} -span#textcolor2539{color:rgb(43,145,175)} -span#textcolor2540{color:rgb(43,145,175)} -span#textcolor2541{color:rgb(43,145,175)} +span#textcolor2528{color:rgb(0,0,255)} +span#textcolor2529{color:rgb(0,0,255)} +span#textcolor2530{color:rgb(0,0,255)} +span#textcolor2531{color:rgb(0,0,255)} +span#textcolor2532{color:rgb(163,20,20)} +span#textcolor2533{color:rgb(163,20,20)} +span#textcolor2534{color:rgb(163,20,20)} +span#textcolor2535{color:rgb(0,0,255)} +span#textcolor2536{color:rgb(0,0,255)} +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,0,255)} +span#textcolor2541{color:rgb(0,0,255)} span#textcolor2542{color:rgb(0,0,255)} span#textcolor2543{color:rgb(43,145,175)} -span#textcolor2544{color:rgb(43,145,175)} +span#textcolor2544{color:rgb(0,0,255)} span#textcolor2545{color:rgb(43,145,175)} span#textcolor2546{color:rgb(0,0,255)} -span#textcolor2547{color:rgb(163,20,20)} +span#textcolor2547{color:rgb(0,0,255)} span#textcolor2548{color:rgb(0,0,255)} span#textcolor2549{color:rgb(163,20,20)} span#textcolor2550{color:rgb(163,20,20)} span#textcolor2551{color:rgb(163,20,20)} -span#textcolor2552{color:rgb(0,0,255)} +span#textcolor2552{color:rgb(0,127,0)} span#textcolor2553{color:rgb(0,0,255)} -span#textcolor2554{color:rgb(0,0,255)} -span#textcolor2555{color:rgb(163,20,20)} -span#textcolor2556{color:rgb(163,20,20)} -span#textcolor2557{color:rgb(163,20,20)} -span#textcolor2558{color:rgb(0,0,255)} +span#textcolor2554{color:rgb(0,127,0)} +span#textcolor2555{color:rgb(0,127,0)} +span#textcolor2556{color:rgb(0,127,0)} +span#textcolor2557{color:rgb(0,127,0)} +span#textcolor2558{color:rgb(0,127,0)} span#textcolor2559{color:rgb(0,127,0)} -span#textcolor2560{color:rgb(43,145,175)} -span#textcolor2561{color:rgb(163,20,20)} +span#textcolor2560{color:rgb(0,127,0)} +span#textcolor2561{color:rgb(0,127,0)} span#textcolor2562{color:rgb(0,127,0)} -span#textcolor2563{color:rgb(43,145,175)} -span#textcolor2564{color:rgb(163,20,20)} -span#textcolor2565{color:rgb(0,127,0)} -span#textcolor2566{color:rgb(0,0,255)} -span#textcolor2567{color:rgb(163,20,20)} -span#textcolor2568{color:rgb(163,20,20)} -span#textcolor2569{color:rgb(163,20,20)} -span#textcolor2570{color:rgb(0,0,255)} -span#textcolor2571{color:rgb(163,20,20)} -span#textcolor2572{color:rgb(163,20,20)} +span#textcolor2563{color:rgb(0,0,255)} +span#textcolor2564{color:rgb(0,0,255)} +span#textcolor2565{color:rgb(43,145,175)} +span#textcolor2566{color:rgb(43,145,175)} +span#textcolor2567{color:rgb(43,145,175)} +span#textcolor2568{color:rgb(0,0,255)} +span#textcolor2569{color:rgb(43,145,175)} +span#textcolor2570{color:rgb(43,145,175)} +span#textcolor2571{color:rgb(43,145,175)} +span#textcolor2572{color:rgb(0,0,255)} span#textcolor2573{color:rgb(163,20,20)} -span#textcolor2574{color:rgb(163,20,20)} +span#textcolor2574{color:rgb(0,0,255)} span#textcolor2575{color:rgb(163,20,20)} span#textcolor2576{color:rgb(163,20,20)} -span#textcolor2577{color:rgb(0,0,255)} -span#textcolor2578{color:rgb(0,127,0)} +span#textcolor2577{color:rgb(163,20,20)} +span#textcolor2578{color:rgb(0,0,255)} span#textcolor2579{color:rgb(0,0,255)} -span#textcolor2580{color:rgb(163,20,20)} +span#textcolor2580{color:rgb(0,0,255)} span#textcolor2581{color:rgb(163,20,20)} span#textcolor2582{color:rgb(163,20,20)} -span#textcolor2583{color:rgb(0,0,255)} +span#textcolor2583{color:rgb(163,20,20)} span#textcolor2584{color:rgb(0,0,255)} span#textcolor2585{color:rgb(0,127,0)} -span#textcolor2586{color:rgb(0,0,255)} +span#textcolor2586{color:rgb(43,145,175)} 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(43,145,175)} -span#textcolor2592{color:rgb(163,20,20)} -span#textcolor2593{color:rgb(0,127,0)} -span#textcolor2594{color:rgb(0,0,255)} -span#textcolor2595{color:rgb(0,0,255)} -span#textcolor2596{color:rgb(163,20,20)} +span#textcolor2588{color:rgb(0,127,0)} +span#textcolor2589{color:rgb(43,145,175)} +span#textcolor2590{color:rgb(163,20,20)} +span#textcolor2591{color:rgb(0,127,0)} +span#textcolor2592{color:rgb(0,0,255)} +span#textcolor2593{color:rgb(163,20,20)} +span#textcolor2594{color:rgb(163,20,20)} +span#textcolor2595{color:rgb(163,20,20)} +span#textcolor2596{color:rgb(0,0,255)} 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(43,145,175)} -span#textcolor2601{color:rgb(43,145,175)} -span#textcolor2602{color:rgb(0,127,0)} -span#textcolor2603{color:rgb(43,145,175)} -span#textcolor2604{color:rgb(163,20,20)} -span#textcolor2605{color:rgb(163,20,20)} -span#textcolor2606{color:rgb(0,0,255)} -span#textcolor2607{color:rgb(43,145,175)} -span#textcolor2608{color:rgb(43,145,175)} -span#textcolor2609{color:rgb(163,20,20)} -span#textcolor2610{color:rgb(163,20,20)} +span#textcolor2599{color:rgb(163,20,20)} +span#textcolor2600{color:rgb(163,20,20)} +span#textcolor2601{color:rgb(163,20,20)} +span#textcolor2602{color:rgb(163,20,20)} +span#textcolor2603{color:rgb(0,0,255)} +span#textcolor2604{color:rgb(0,127,0)} +span#textcolor2605{color:rgb(0,0,255)} +span#textcolor2606{color:rgb(163,20,20)} +span#textcolor2607{color:rgb(163,20,20)} +span#textcolor2608{color:rgb(163,20,20)} +span#textcolor2609{color:rgb(0,0,255)} +span#textcolor2610{color:rgb(0,0,255)} +span#textcolor2611{color:rgb(0,127,0)} +span#textcolor2612{color:rgb(0,0,255)} +span#textcolor2613{color:rgb(163,20,20)} +span#textcolor2614{color:rgb(163,20,20)} +span#textcolor2615{color:rgb(163,20,20)} +span#textcolor2616{color:rgb(0,0,255)} +span#textcolor2617{color:rgb(43,145,175)} +span#textcolor2618{color:rgb(163,20,20)} +span#textcolor2619{color:rgb(0,127,0)} +span#textcolor2620{color:rgb(0,0,255)} +span#textcolor2621{color:rgb(0,0,255)} +span#textcolor2622{color:rgb(163,20,20)} +span#textcolor2623{color:rgb(163,20,20)} +span#textcolor2624{color:rgb(163,20,20)} +span#textcolor2625{color:rgb(0,0,255)} +span#textcolor2626{color:rgb(43,145,175)} +span#textcolor2627{color:rgb(43,145,175)} +span#textcolor2628{color:rgb(0,127,0)} +span#textcolor2629{color:rgb(43,145,175)} +span#textcolor2630{color:rgb(163,20,20)} +span#textcolor2631{color:rgb(163,20,20)} +span#textcolor2632{color:rgb(0,0,255)} +span#textcolor2633{color:rgb(43,145,175)} +span#textcolor2634{color:rgb(43,145,175)} +span#textcolor2635{color:rgb(163,20,20)} +span#textcolor2636{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#textcolor2611{color:rgb(0,127,0)} -span#textcolor2612{color:rgb(0,127,0)} -span#textcolor2613{color:rgb(0,127,0)} -span#textcolor2614{color:rgb(0,0,255)} -span#textcolor2615{color:rgb(0,127,0)} -span#textcolor2616{color:rgb(0,0,255)} -span#textcolor2617{color:rgb(0,127,0)} -span#textcolor2618{color:rgb(0,0,255)} -span#textcolor2619{color:rgb(0,127,0)} -span#textcolor2620{color:rgb(0,0,255)} -span#textcolor2621{color:rgb(43,145,175)} -span#textcolor2622{color:rgb(43,145,175)} -span#textcolor2623{color:rgb(0,0,255)} -span#textcolor2624{color:rgb(43,145,175)} -span#textcolor2625{color:rgb(0,0,255)} -span#textcolor2626{color:rgb(0,0,255)} -span#textcolor2627{color:rgb(0,0,255)} -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(163,20,20)} -span#textcolor2634{color:rgb(0,127,0)} -span#textcolor2635{color:rgb(0,0,255)} -span#textcolor2636{color:rgb(0,0,255)} -span#textcolor2637{color:rgb(43,145,175)} -span#textcolor2638{color:rgb(0,0,255)} -span#textcolor2639{color:rgb(163,20,20)} -span#textcolor2640{color:rgb(163,20,20)} -span#textcolor2641{color:rgb(163,20,20)} -span#textcolor2642{color:rgb(0,127,0)} -span#textcolor2643{color:rgb(0,0,255)} +span#textcolor2637{color:rgb(0,127,0)} +span#textcolor2638{color:rgb(0,127,0)} +span#textcolor2639{color:rgb(0,127,0)} +span#textcolor2640{color:rgb(0,0,255)} +span#textcolor2641{color:rgb(0,127,0)} +span#textcolor2642{color:rgb(0,0,255)} +span#textcolor2643{color:rgb(0,127,0)} span#textcolor2644{color:rgb(0,0,255)} -span#textcolor2645{color:rgb(43,145,175)} +span#textcolor2645{color:rgb(0,127,0)} span#textcolor2646{color:rgb(0,0,255)} -span#textcolor2647{color:rgb(163,20,20)} -span#textcolor2648{color:rgb(163,20,20)} -span#textcolor2649{color:rgb(163,20,20)} -span#textcolor2650{color:rgb(0,127,0)} +span#textcolor2647{color:rgb(43,145,175)} +span#textcolor2648{color:rgb(43,145,175)} +span#textcolor2649{color:rgb(0,0,255)} +span#textcolor2650{color:rgb(43,145,175)} span#textcolor2651{color:rgb(0,0,255)} span#textcolor2652{color:rgb(0,0,255)} -span#textcolor2653{color:rgb(43,145,175)} -span#textcolor2654{color:rgb(0,0,255)} +span#textcolor2653{color:rgb(0,0,255)} +span#textcolor2654{color:rgb(163,20,20)} span#textcolor2655{color:rgb(163,20,20)} span#textcolor2656{color:rgb(163,20,20)} span#textcolor2657{color:rgb(163,20,20)} -span#textcolor2658{color:rgb(0,127,0)} -span#textcolor2659{color:rgb(0,0,255)} -span#textcolor2660{color:rgb(0,0,255)} +span#textcolor2658{color:rgb(163,20,20)} +span#textcolor2659{color:rgb(163,20,20)} +span#textcolor2660{color:rgb(0,127,0)} span#textcolor2661{color:rgb(0,0,255)} span#textcolor2662{color:rgb(0,0,255)} -span#textcolor2663{color:rgb(0,0,255)} +span#textcolor2663{color:rgb(43,145,175)} span#textcolor2664{color:rgb(0,0,255)} span#textcolor2665{color:rgb(163,20,20)} -span#textcolor2666{color:rgb(0,0,255)} -span#textcolor2667{color:rgb(43,145,175)} -span#textcolor2668{color:rgb(43,145,175)} -span#textcolor2669{color:rgb(43,145,175)} -span#textcolor2670{color:rgb(163,20,20)} -span#textcolor2671{color:rgb(163,20,20)} -span#textcolor2672{color:rgb(163,20,20)} -span#textcolor2673{color:rgb(0,0,255)} +span#textcolor2666{color:rgb(163,20,20)} +span#textcolor2667{color:rgb(163,20,20)} +span#textcolor2668{color:rgb(0,127,0)} +span#textcolor2669{color:rgb(0,0,255)} +span#textcolor2670{color:rgb(0,0,255)} +span#textcolor2671{color:rgb(43,145,175)} +span#textcolor2672{color:rgb(0,0,255)} +span#textcolor2673{color:rgb(163,20,20)} span#textcolor2674{color:rgb(163,20,20)} span#textcolor2675{color:rgb(163,20,20)} -span#textcolor2676{color:rgb(163,20,20)} +span#textcolor2676{color:rgb(0,127,0)} span#textcolor2677{color:rgb(0,0,255)} span#textcolor2678{color:rgb(0,0,255)} -span#textcolor2679{color:rgb(0,0,255)} -span#textcolor2680{color:rgb(43,145,175)} -span#textcolor2681{color:rgb(43,145,175)} +span#textcolor2679{color:rgb(43,145,175)} +span#textcolor2680{color:rgb(0,0,255)} +span#textcolor2681{color:rgb(163,20,20)} span#textcolor2682{color:rgb(163,20,20)} span#textcolor2683{color:rgb(163,20,20)} -span#textcolor2684{color:rgb(163,20,20)} -span#textcolor2685{color:rgb(163,20,20)} -span#textcolor2686{color:rgb(163,20,20)} +span#textcolor2684{color:rgb(0,127,0)} +span#textcolor2685{color:rgb(0,0,255)} +span#textcolor2686{color:rgb(0,0,255)} +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(0,0,255)} +span#textcolor2691{color:rgb(163,20,20)} +span#textcolor2692{color:rgb(0,0,255)} +span#textcolor2693{color:rgb(43,145,175)} +span#textcolor2694{color:rgb(43,145,175)} +span#textcolor2695{color:rgb(43,145,175)} +span#textcolor2696{color:rgb(163,20,20)} +span#textcolor2697{color:rgb(163,20,20)} +span#textcolor2698{color:rgb(163,20,20)} +span#textcolor2699{color:rgb(0,0,255)} +span#textcolor2700{color:rgb(163,20,20)} +span#textcolor2701{color:rgb(163,20,20)} +span#textcolor2702{color:rgb(163,20,20)} +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(43,145,175)} +span#textcolor2707{color:rgb(43,145,175)} +span#textcolor2708{color:rgb(163,20,20)} +span#textcolor2709{color:rgb(163,20,20)} +span#textcolor2710{color:rgb(163,20,20)} +span#textcolor2711{color:rgb(163,20,20)} +span#textcolor2712{color:rgb(163,20,20)} pre#fancyvrb72{padding:5.69054pt;} pre#fancyvrb72{ border-top: solid 0.4pt; } pre#fancyvrb72{ border-left: solid 0.4pt; } pre#fancyvrb72{ border-bottom: solid 0.4pt; } pre#fancyvrb72{ border-right: solid 0.4pt; } -span#textcolor2687{color:rgb(0,0,255)} -span#textcolor2688{color:rgb(0,0,255)} +span#textcolor2713{color:rgb(0,0,255)} +span#textcolor2714{color:rgb(0,0,255)} /* end css.sty */ diff --git a/lkmpg-for-ht.html b/lkmpg-for-ht.html index c09a05c..5f0ed00 100644 --- a/lkmpg-for-ht.html +++ b/lkmpg-for-ht.html @@ -20,7 +20,7 @@

The Linux Kernel Module Programming Guide

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

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

0.11 Blocking Processes and threads

@@ -3221,286 +3230,286 @@ $

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

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

@@ -3516,82 +3525,82 @@ 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> 
+   
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; 
+10static struct { 
+11    struct completion crank_comp; 
+12    struct completion flywheel_comp; 
 13} machine; 
 14 
-15static int machine_crank_thread(void *arg) 
+15static int machine_crank_thread(void *arg) 
 16{ 
-17    pr_info("Turn the crank\n"); 
+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) 
+23static int machine_flywheel_spinup_thread(void *arg) 
 24{ 
 25    wait_for_completion(&machine.crank_comp); 
 26 
-27    pr_info("Flywheel spins up\n"); 
+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) 
+33static int completions_init(void) 
 34{ 
-35    struct task_struct *crank_thread; 
-36    struct task_struct *flywheel_thread; 
+35    struct task_struct *crank_thread; 
+36    struct task_struct *flywheel_thread; 
 37 
-38    pr_info("completions example\n"); 
+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; 
+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; 
+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; 
+55    return 0; 
 56 
 57ERROR_THREAD_2: 
 58    kthread_stop(crank_thread); 
 59ERROR_THREAD_1: 
 60 
-61    return -1; 
+61    return -1; 
 62} 
 63 
-64void completions_exit(void) 
+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"); 
+69    pr_info("completions exit\n"); 
 70} 
 71 
 72module_init(completions_init); 
 73module_exit(completions_exit); 
 74 
-75MODULE_DESCRIPTION("Completions example"); 
-76MODULE_LICENSE("GPL");
+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 @@ -3621,47 +3630,47 @@ might deploy them in userland. This may be all that is needed to avoid collision 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> 
+   
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) 
+11static int example_mutex_init(void) 
 12{ 
-13    int ret; 
+13    int ret; 
 14 
-15    pr_info("example_mutex init\n"); 
+15    pr_info("example_mutex init\n"); 
 16 
 17    ret = mutex_trylock(&mymutex); 
-18    if (ret != 0) { 
-19        pr_info("mutex is locked\n"); 
+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"); 
+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"); 
+25        pr_info("mutex is unlocked\n"); 
+26    } else 
+27        pr_info("Failed to lock\n"); 
 28 
-29    return 0; 
+29    return 0; 
 30} 
 31 
-32static void example_mutex_exit(void) 
+32static void example_mutex_exit(void) 
 33{ 
-34    pr_info("example_mutex exit\n"); 
+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");
+40MODULE_DESCRIPTION("Mutex example"); +41MODULE_LICENSE("GPL");

0.12.2 Spinlocks

@@ -3679,69 +3688,69 @@ they will not be forgotten and will activate when the unlock happens, using the
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> 
+   
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) 
+13static void example_spinlock_static(void) 
 14{ 
-15    unsigned long flags; 
+15    unsigned long flags; 
 16 
 17    spin_lock_irqsave(&sl_static, flags); 
-18    pr_info("Locked static spinlock\n"); 
+18    pr_info("Locked static spinlock\n"); 
 19 
-20    /* Do something or other safely. Because this uses 100% CPU time, this 
-21     * code should take no more than a few milliseconds to run. 
-22     */ 
+20    /* Do something or other safely. Because this uses 100% CPU time, this 
+21     * code should take no more than a few milliseconds to run. 
+22     */ 
 23 
 24    spin_unlock_irqrestore(&sl_static, flags); 
-25    pr_info("Unlocked static spinlock\n"); 
+25    pr_info("Unlocked static spinlock\n"); 
 26} 
 27 
-28static void example_spinlock_dynamic(void) 
+28static void example_spinlock_dynamic(void) 
 29{ 
-30    unsigned long flags; 
+30    unsigned long flags; 
 31 
 32    spin_lock_init(&sl_dynamic); 
 33    spin_lock_irqsave(&sl_dynamic, flags); 
-34    pr_info("Locked dynamic spinlock\n"); 
+34    pr_info("Locked dynamic spinlock\n"); 
 35 
-36    /* Do something or other safely. Because this uses 100% CPU time, this 
-37     * code should take no more than a few milliseconds to run. 
-38     */ 
+36    /* Do something or other safely. Because this uses 100% CPU time, this 
+37     * code should take no more than a few milliseconds to run. 
+38     */ 
 39 
 40    spin_unlock_irqrestore(&sl_dynamic, flags); 
-41    pr_info("Unlocked dynamic spinlock\n"); 
+41    pr_info("Unlocked dynamic spinlock\n"); 
 42} 
 43 
-44static int example_spinlock_init(void) 
+44static int example_spinlock_init(void) 
 45{ 
-46    pr_info("example spinlock started\n"); 
+46    pr_info("example spinlock started\n"); 
 47 
 48    example_spinlock_static(); 
 49    example_spinlock_dynamic(); 
 50 
-51    return 0; 
+51    return 0; 
 52} 
 53 
-54static void example_spinlock_exit(void) 
+54static void example_spinlock_exit(void) 
 55{ 
-56    pr_info("example spinlock exit\n"); 
+56    pr_info("example spinlock exit\n"); 
 57} 
 58 
 59module_init(example_spinlock_init); 
 60module_exit(example_spinlock_exit); 
 61 
-62MODULE_DESCRIPTION("Spinlock example"); 
-63MODULE_LICENSE("GPL");
+62MODULE_DESCRIPTION("Spinlock example"); +63MODULE_LICENSE("GPL");

0.12.3 Read and write locks

@@ -3755,61 +3764,61 @@ 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> 
+   
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) 
+10static void example_read_lock(void) 
 11{ 
-12    unsigned long flags; 
+12    unsigned long flags; 
 13 
 14    read_lock_irqsave(&myrwlock, flags); 
-15    pr_info("Read Locked\n"); 
+15    pr_info("Read Locked\n"); 
 16 
-17    /* Read from something */ 
+17    /* Read from something */ 
 18 
 19    read_unlock_irqrestore(&myrwlock, flags); 
-20    pr_info("Read Unlocked\n"); 
+20    pr_info("Read Unlocked\n"); 
 21} 
 22 
-23static void example_write_lock(void) 
+23static void example_write_lock(void) 
 24{ 
-25    unsigned long flags; 
+25    unsigned long flags; 
 26 
 27    write_lock_irqsave(&myrwlock, flags); 
-28    pr_info("Write Locked\n"); 
+28    pr_info("Write Locked\n"); 
 29 
-30    /* Write to something */ 
+30    /* Write to something */ 
 31 
 32    write_unlock_irqrestore(&myrwlock, flags); 
-33    pr_info("Write Unlocked\n"); 
+33    pr_info("Write Unlocked\n"); 
 34} 
 35 
-36static int example_rwlock_init(void) 
+36static int example_rwlock_init(void) 
 37{ 
-38    pr_info("example_rwlock started\n"); 
+38    pr_info("example_rwlock started\n"); 
 39 
 40    example_read_lock(); 
 41    example_write_lock(); 
 42 
-43    return 0; 
+43    return 0; 
 44} 
 45 
-46static void example_rwlock_exit(void) 
+46static void example_rwlock_exit(void) 
 47{ 
-48    pr_info("example_rwlock exit\n"); 
+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");
+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) @@ -3825,80 +3834,80 @@ and was not 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> 
+   
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') 
+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) 
+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 */ 
+22    /* subtract one */ 
 23    atomic_dec(&debbie); 
 24 
 25    atomic_add(7, &debbie); 
 26 
-27    /* add one */ 
+27    /* add one */ 
 28    atomic_inc(&debbie); 
 29 
-30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
+30    pr_info("chris: %d, debbie: %d\n", atomic_read(&chris), 
 31            atomic_read(&debbie)); 
 32} 
 33 
-34static void atomic_bitwise(void) 
+34static void atomic_bitwise(void) 
 35{ 
-36    unsigned long word = 0; 
+36    unsigned long word = 0; 
 37 
-38    pr_info("Bits 0: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
+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)); 
+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)); 
+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)); 
+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)); 
+52    pr_info("Bits 5: " BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(word)); 
 53} 
 54 
-55static int example_atomic_init(void) 
+55static int example_atomic_init(void) 
 56{ 
-57    pr_info("example_atomic started\n"); 
+57    pr_info("example_atomic started\n"); 
 58 
 59    atomic_add_subtract(); 
 60    atomic_bitwise(); 
 61 
-62    return 0; 
+62    return 0; 
 63} 
 64 
-65static void example_atomic_exit(void) 
+65static void example_atomic_exit(void) 
 66{ 
-67    pr_info("example_atomic exit\n"); 
+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");
+73MODULE_DESCRIPTION("Atomic operations example"); +74MODULE_LICENSE("GPL");
@@ -3922,83 +3931,83 @@ 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 
-3 * it is through X11, telnet, etc.  We do this by printing the string to the 
-4 * tty 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 */ 
+   
1/* 
+2 * print_string.c - Send output to the tty we're running on, regardless if 
+3 * it is through X11, telnet, etc.  We do this by printing the string to the 
+4 * tty 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 
-12static void print_string(char *str) 
+12static void print_string(char *str) 
 13{ 
-14    struct tty_struct *my_tty; 
-15    const struct tty_operations *ttyops; 
+14    struct tty_struct *my_tty; 
+15    const struct tty_operations *ttyops; 
 16 
-17    /* The tty for the current task, for 2.6.6+ kernels */ 
+17    /* The tty for the current task, for 2.6.6+ kernels */ 
 18    my_tty = get_current_tty(); 
 19    ttyops = my_tty->driver->ops; 
 20 
-21    /* If my_tty is NULL, the current task has no tty you can print to (i.e., 
-22     * if it is a daemon). If so, there is nothing we can do. 
-23     */ 
-24    if (my_tty) { 
-25        /* my_tty->driver is a struct which holds the tty's functions, 
-26         * one of which (write) is used to write strings to the tty. 
-27         * It can be used to take a string either from the user's or 
-28         * kernel's memory segment. 
-29         * 
-30         * The function's 1st parameter is the tty to write to, because the 
-31         * same function would normally be used for all tty's of a certain 
-32         * type. 
-33         * The 2nd parameter is a pointer to a string. 
-34         * The 3rd parameter is the length of the string. 
-35         * 
-36         * As you will see below, sometimes it's necessary to use 
-37         * preprocessor stuff to create code that works for different 
-38         * kernel versions. The (naive) approach we've taken here does not 
-39         * scale well. The right way to deal with this is described in 
-40         * section 2 of 
-41         * linux/Documentation/SubmittingPatches 
-42         */ 
-43        (ttyops->write)(my_tty,       /* The tty itself */ 
-44                        str,          /* String                 */ 
-45                        strlen(str)); /* Length */ 
+21    /* If my_tty is NULL, the current task has no tty you can print to (i.e., 
+22     * if it is a daemon). If so, there is nothing we can do. 
+23     */ 
+24    if (my_tty) { 
+25        /* my_tty->driver is a struct which holds the tty's functions, 
+26         * one of which (write) is used to write strings to the tty. 
+27         * It can be used to take a string either from the user's or 
+28         * kernel's memory segment. 
+29         * 
+30         * The function's 1st parameter is the tty to write to, because the 
+31         * same function would normally be used for all tty's of a certain 
+32         * type. 
+33         * The 2nd parameter is a pointer to a string. 
+34         * The 3rd parameter is the length of the string. 
+35         * 
+36         * As you will see below, sometimes it's necessary to use 
+37         * preprocessor stuff to create code that works for different 
+38         * kernel versions. The (naive) approach we've taken here does not 
+39         * scale well. The right way to deal with this is described in 
+40         * section 2 of 
+41         * linux/Documentation/SubmittingPatches 
+42         */ 
+43        (ttyops->write)(my_tty,       /* The tty itself */ 
+44                        str,          /* String                 */ 
+45                        strlen(str)); /* Length */ 
 46 
-47        /* ttys were originally hardware devices, which (usually) strictly 
-48         * followed the ASCII standard. In ASCII, to move to a new line you 
-49         * need two characters, a carriage return and a line feed. On Unix, 
-50         * the ASCII line feed is used for both purposes - so we can not 
-51         * just use \n, because it would not have a carriage return and the 
-52         * next line will start at the column right after the line feed. 
-53         * 
-54         * This is why text files are different between Unix and MS Windows. 
-55         * In CP/M and derivatives, like MS-DOS and MS Windows, the ASCII 
-56         * standard was strictly adhered to, and therefore a newline requirs 
-57         * both a LF and a CR. 
-58         */ 
-59        (ttyops->write)(my_tty, "\015\012", 2); 
+47        /* ttys were originally hardware devices, which (usually) strictly 
+48         * followed the ASCII standard. In ASCII, to move to a new line you 
+49         * need two characters, a carriage return and a line feed. On Unix, 
+50         * the ASCII line feed is used for both purposes - so we can not 
+51         * just use \n, because it would not have a carriage return and the 
+52         * next line will start at the column right after the line feed. 
+53         * 
+54         * This is why text files are different between Unix and MS Windows. 
+55         * In CP/M and derivatives, like MS-DOS and MS Windows, the ASCII 
+56         * standard was strictly adhered to, and therefore a newline requirs 
+57         * both a LF and a CR. 
+58         */ 
+59        (ttyops->write)(my_tty, "\015\012", 2); 
 60    } 
 61} 
 62 
-63static int __init print_string_init(void) 
+63static int __init print_string_init(void) 
 64{ 
-65    print_string("The module has been inserted.  Hello world!"); 
-66    return 0; 
+65    print_string("The module has been inserted.  Hello world!"); 
+66    return 0; 
 67} 
 68 
-69static void __exit print_string_exit(void) 
+69static void __exit print_string_exit(void) 
 70{ 
-71    print_string("The module has been removed.  Farewell world!"); 
+71    print_string("The module has been removed.  Farewell world!"); 
 72} 
 73 
 74module_init(print_string_init); 
 75module_exit(print_string_exit); 
 76 
-77MODULE_LICENSE("GPL");
+77MODULE_LICENSE("GPL");

0.13.2 Flashing keyboard LEDs

@@ -4012,49 +4021,49 @@ file. loaded, starts blinking the keyboard LEDs until it is unloaded.

-
1/* 
-2 * kbleds.c - Blink keyboard leds until the module is unloaded. 
-3 */ 
+   
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 */ 
+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 */ 
+12#include <linux/console_struct.h> /* For vc_cons */ 
 13 
-14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
+14MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs."); 
 15 
-16struct timer_list my_timer; 
-17struct tty_driver *my_driver; 
-18char kbledstatus = 0; 
+16struct timer_list my_timer; 
+17struct tty_driver *my_driver; 
+18char kbledstatus = 0; 
 19 
-20#define BLINK_DELAY HZ / 5 
-21#define ALL_LEDS_ON 0x07 
-22#define RESTORE_LEDS 0xFF 
+20#define BLINK_DELAY HZ / 5 
+21#define ALL_LEDS_ON 0x07 
+22#define RESTORE_LEDS 0xFF 
 23 
-24/* Function my_timer_func blinks the keyboard LEDs periodically by invoking 
-25 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
-26 * terminal ioctl operations, please see file: 
-27 *   drivers/tty/vt/vt_ioctl.c, function vt_ioctl(). 
-28 * 
-29 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
-30 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
-31 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
-32 * the LEDs reflect the actual keyboard status).  To learn more on this, 
-33 * please see file: drivers/tty/vt/keyboard.c, function setledstate(). 
-34 */ 
+24/* Function my_timer_func blinks the keyboard LEDs periodically by invoking 
+25 * command KDSETLED of ioctl() on the keyboard driver. To learn more on virtual 
+26 * terminal ioctl operations, please see file: 
+27 *   drivers/tty/vt/vt_ioctl.c, function vt_ioctl(). 
+28 * 
+29 * The argument to KDSETLED is alternatively set to 7 (thus causing the led 
+30 * mode to be set to LED_SHOW_IOCTL, and all the leds are lit) and to 0xFF 
+31 * (any value above 7 switches back the led mode to LED_SHOW_FLAGS, thus 
+32 * the LEDs reflect the actual keyboard status).  To learn more on this, 
+33 * please see file: drivers/tty/vt/keyboard.c, function setledstate(). 
+34 */ 
 35 
-36static void my_timer_func(unsigned long ptr) 
+36static void my_timer_func(unsigned long ptr) 
 37{ 
-38    unsigned long *pstatus = (unsigned long *) ptr; 
-39    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
+38    unsigned long *pstatus = (unsigned long *) ptr; 
+39    struct tty_struct *t = vc_cons[fg_console].d->port.tty; 
 40 
-41    if (*pstatus == ALL_LEDS_ON) 
+41    if (*pstatus == ALL_LEDS_ON) 
 42        *pstatus = RESTORE_LEDS; 
-43    else 
+43    else 
 44        *pstatus = ALL_LEDS_ON; 
 45 
 46    (my_driver->ops->ioctl)(t, KDSETLED, *pstatus); 
@@ -4063,35 +4072,35 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
 49    add_timer(&my_timer); 
 50} 
 51 
-52static int __init kbleds_init(void) 
+52static int __init kbleds_init(void) 
 53{ 
-54    int i; 
+54    int i; 
 55 
-56    pr_info("kbleds: loading\n"); 
-57    pr_info("kbleds: fgconsole is %x\n", fg_console); 
-58    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
-59        if (!vc_cons[i].d) 
-60            break; 
-61        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
-62                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
+56    pr_info("kbleds: loading\n"); 
+57    pr_info("kbleds: fgconsole is %x\n", fg_console); 
+58    for (i = 0; i < MAX_NR_CONSOLES; i++) { 
+59        if (!vc_cons[i].d) 
+60            break; 
+61        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES, 
+62                vc_cons[i].d->vc_num, (unsigned long) vc_cons[i].d->port.tty); 
 63    } 
-64    pr_info("kbleds: finished scanning consoles\n"); 
+64    pr_info("kbleds: finished scanning consoles\n"); 
 65 
 66    my_driver = vc_cons[fg_console].d->port.tty->driver; 
-67    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
+67    pr_info("kbleds: tty driver magic %x\n", my_driver->magic); 
 68 
-69    /* Set up the LED blink timer the first time. */ 
-70    timer_setup(&my_timer, (void *) &my_timer_func, 
-71                (unsigned long) &kbledstatus); 
+69    /* Set up the LED blink timer the first time. */ 
+70    timer_setup(&my_timer, (void *) &my_timer_func, 
+71                (unsigned long) &kbledstatus); 
 72    my_timer.expires = jiffies + BLINK_DELAY; 
 73    add_timer(&my_timer); 
 74 
-75    return 0; 
+75    return 0; 
 76} 
 77 
-78static void __exit kbleds_cleanup(void) 
+78static void __exit kbleds_cleanup(void) 
 79{ 
-80    pr_info("kbleds: unloading...\n"); 
+80    pr_info("kbleds: unloading...\n"); 
 81    del_timer(&my_timer); 
 82    (my_driver->ops->ioctl)(vc_cons[fg_console].d->port.tty, KDSETLED, 
 83                            RESTORE_LEDS); 
@@ -4100,7 +4109,7 @@ loaded, starts blinking the keyboard LEDs until it is unloaded.
 86module_init(kbleds_init); 
 87module_exit(kbleds_cleanup); 
 88 
-89MODULE_LICENSE("GPL");
+89MODULE_LICENSE("GPL");
@@ -4137,43 +4146,50 @@ better suited to running multiple things in a sequence.
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> 
+   
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} 
+9/* Macro DECLARE_TASKLET_OLD exists for compatibiity. 
+10 * See https://lwn.net/Articles/830964/ 
+11 */ 
+12#ifndef DECLARE_TASKLET_OLD 
+13#define DECLARE_TASKLET_OLD(arg1, arg2) DECLARE_TASKLET(arg1, arg2, 0L) 
+14#endif 
 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");
+16static void tasklet_fn(unsigned long data) +17{ +18    pr_info("Example tasklet starts\n"); +19    mdelay(5000); +20    pr_info("Example tasklet ends\n"); +21} +22 +23DECLARE_TASKLET_OLD(mytask, tasklet_fn); +24 +25static int example_tasklet_init(void) +26{ +27    pr_info("tasklet example init\n"); +28    tasklet_schedule(&mytask); +29    mdelay(200); +30    pr_info("Example tasklet init continues...\n"); +31    return 0; +32} +33 +34static void example_tasklet_exit(void) +35{ +36    pr_info("tasklet example exit\n"); +37    tasklet_kill(&mytask); +38} +39 +40module_init(example_tasklet_init); +41module_exit(example_tasklet_exit); +42 +43MODULE_DESCRIPTION("Tasklet example"); +44MODULE_LICENSE("GPL");

So with this example loaded dmesg should show: @@ -4186,39 +4202,51 @@ Example tasklet starts Example tasklet init continues... Example tasklet ends

-

-

+

Although tasklet is easy to use, it comes with several defators, and developers are +discussing about getting rid of tasklet in linux kernel. The tasklet callback +runs in atomic context, inside a software interrupt, meaning that it cannot +sleep or access user-space data, so not all work can be done in a tasklet +handler. Also, the kernel only allows one instance of any given tasklet to be +running at any given time; multiple different tasklet callbacks can run in +parallel. +

In recent kernels, tasklets can be replaced by workqueues, timers, or threaded +interrupts.1 +While the removal of tasklets remains a longer-term goal, the current kernel contains more +than a hundred uses of tasklets. Now developers are proceeding with the API changes and +the macro DECLARE_TASKLET_OLD + exists for compatibiity. For further information, see https://lwn.net/Articles/830964/. +

0.14.2 Work queues

-

To add a task to the scheduler we can use a workqueue. The kernel then uses the +

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> 
+   
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; 
+8static struct workqueue_struct *queue = NULL; 
+9static struct work_struct work; 
 10 
-11static void work_handler(struct work_struct *data) 
+11static void work_handler(struct work_struct *data) 
 12{ 
-13    pr_info("work handler function.\n"); 
+13    pr_info("work handler function.\n"); 
 14} 
 15 
-16static int __init sched_init(void) 
+16static int __init sched_init(void) 
 17{ 
-18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
+18    queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); 
 19    INIT_WORK(&work, work_handler); 
 20    schedule_work(&work); 
 21 
-22    return 0; 
+22    return 0; 
 23} 
 24 
-25static void __exit sched_exit(void) 
+25static void __exit sched_exit(void) 
 26{ 
 27    destroy_workqueue(queue); 
 28} 
@@ -4226,38 +4254,38 @@ Completely Fair Scheduler (CFS) to execute work within the queue.
 30module_init(sched_init); 
 31module_exit(sched_exit); 
 32 
-33MODULE_LICENSE("GPL"); 
-34MODULE_DESCRIPTION("Workqueue example");
-

+33MODULE_LICENSE("GPL"); +34MODULE_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 have done as a +

Except for the last chapter, everything we did in the kernel so far we have 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 is not 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 +

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 order 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 do not read their information when available, it is lost. - - - -

Under Linux, hardware interrupts are called IRQ’s (Interrupt ReQuests). There +

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 is better to declare an interrupt handler to be long. -

When the CPU receives an interrupt, it stops whatever it is doing (unless it is +

When the CPU receives an interrupt, it stops whatever it is doing (unless it is 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 @@ -4269,10 +4297,10 @@ 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 +

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 +

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 @@ -4282,11 +4310,14 @@ 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 are 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 is not enough to know if a certain IRQs has happened, it’s also important to know what CPU(s) it was for. People still interested in more details, might want to refer to "APIC" now. -

This function receives the IRQ number, the name of the function, +

This function receives the IRQ number, the name of the function, flags, a name for /proc/interrupts and a parameter to be passed 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 @@ -4296,132 +4327,129 @@ How many IRQs there are is hardware-dependent. The flags can include SA_INTERRUPT to indicate this is a fast interrupt. This function will only succeed if there is not already a handler on this IRQ, or if you are both willing to share. - - - -

+

0.15.2 Detecting button presses

-

Many popular single board computers, such as Raspberry Pi or Beagleboards, have a +

Many popular single board computers, such as Raspberry Pi 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 is better for the input to trigger the CPU to then run a particular handling function. -

Here is an example where buttons are connected to GPIO numbers 17 and 18 and +

Here is 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 */ 
+   
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> 
+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}; 
+16static int button_irqs[] = {-1, -1}; 
 17 
-18/* Define GPIOs for LEDs. 
-19 * TODO: Change the numbers for the GPIO on your board. 
-20 */ 
-21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
+18/* Define GPIOs for LEDs. 
+19 * TODO: Change the numbers for the GPIO on your board. 
+20 */ 
+21static struct gpio leds[] = {{4, GPIOF_OUT_INIT_LOW, "LED 1"}}; 
 22 
-23/* Define GPIOs for BUTTONS 
-24 * TODO: Change the numbers for the GPIO on your board. 
-25 */ 
-26static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
-27                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
+23/* Define GPIOs for BUTTONS 
+24 * TODO: Change the numbers for the GPIO on your board. 
+25 */ 
+26static struct gpio buttons[] = {{17, GPIOF_IN, "LED 1 ON BUTTON"}, 
+27                                {18, GPIOF_IN, "LED 1 OFF BUTTON"}}; 
 28 
-29/* interrupt function triggered when a button is pressed. */ 
-30static irqreturn_t button_isr(int irq, void *data) 
+29/* interrupt function triggered when a button is pressed. */ 
+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)) 
+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)) 
+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; 
+39    return IRQ_HANDLED; 
 40} 
 41 
-42static int __init intrpt_init(void) 
+42static int __init intrpt_init(void) 
 43{ 
-44    int ret = 0; 
+44    int ret = 0; 
 45 
-46    pr_info("%s\n", __func__); 
+46    pr_info("%s\n", __func__); 
 47 
-48    /* register LED gpios */ 
+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; 
+51    if (ret) { 
+52        pr_err("Unable to request GPIOs for LEDs: %d\n", ret); 
+53        return ret; 
 54    } 
 55 
-56    /* register BUTTON gpios */ 
+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; 
+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)); 
+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; 
+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]); 
+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); 
+79                      "gpiomod#button1", NULL); 
 80 
-81    if (ret) { 
-82        pr_err("Unable to request IRQ: %d\n", ret); 
-83        goto fail2; 
+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; 
+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]); 
+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); 
+100                      "gpiomod#button2", NULL); 
 101 
-102    if (ret) { 
-103        pr_err("Unable to request IRQ: %d\n", ret); 
-104        goto fail3; 
+102    if (ret) { 
+103        pr_err("Unable to request IRQ: %d\n", ret); 
+104        goto fail3; 
 105    } 
 106 
-107    return 0; 
+107    return 0; 
 108 
-109/* cleanup what has been setup so far */ 
+109/* cleanup what has been setup so far */ 
 110fail3: 
 111    free_irq(button_irqs[0], NULL); 
 112 
@@ -4431,24 +4459,24 @@ appropriate for your board.
 116fail1: 
 117    gpio_free_array(leds, ARRAY_SIZE(leds)); 
 118 
-119    return ret; 
+119    return ret; 
 120} 
 121 
-122static void __exit intrpt_exit(void) 
+122static void __exit intrpt_exit(void) 
 123{ 
-124    int i; 
+124    int i; 
 125 
-126    pr_info("%s\n", __func__); 
+126    pr_info("%s\n", __func__); 
 127 
-128    /* free irqs */ 
+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++) 
+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 */ 
+136    /* unregister */ 
 137    gpio_free_array(leds, ARRAY_SIZE(leds)); 
 138    gpio_free_array(buttons, ARRAY_SIZE(buttons)); 
 139} 
@@ -4456,480 +4484,492 @@ appropriate for your board.
 141module_init(intrpt_init); 
 142module_exit(intrpt_exit); 
 143 
-144MODULE_LICENSE("GPL"); 
-145MODULE_DESCRIPTION("Handle some GPIO interrupts");
-

+144MODULE_LICENSE("GPL"); +145MODULE_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 +

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 +

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

+142    return ret; +143} +144 +145static void __exit bottomhalf_exit(void) +146{ +147    int i; +148 +149    pr_info("%s\n", __func__); +150 +151    /* free irqs */ +152    free_irq(button_irqs[0], NULL); +153    free_irq(button_irqs[1], NULL); +154 +155    /* turn all LEDs off */ +156    for (i = 0; i < ARRAY_SIZE(leds); i++) +157        gpio_set_value(leds[i].gpio, 0); +158 +159    /* unregister */ +160    gpio_free_array(leds, ARRAY_SIZE(leds)); +161    gpio_free_array(buttons, ARRAY_SIZE(buttons)); +162} +163 +164module_init(bottomhalf_init); +165module_exit(bottomhalf_exit); +166 +167MODULE_LICENSE("GPL"); +168MODULE_DESCRIPTION("Interrupt with top and bottom half");

+

0.16 Crypto

-

At the dawn of the internet, everybody trusted everybody completely…but that did +

At the dawn of the internet, everybody trusted everybody completely…but that did not 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 is 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 +

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> 
+   
1/* 
+2 * cryptosha256.c 
+3 */ 
+4#include <crypto/internal/hash.h> 
+5#include <linux/module.h> 
 6 
-7#define SHA256_LENGTH 32 
+7#define SHA256_LENGTH 32 
 8 
-9static void show_hash_result(char *plaintext, char *hash_sha256) 
+9static void show_hash_result(char *plaintext, char *hash_sha256) 
 10{ 
-11    int i; 
-12    char str[SHA256_LENGTH * 2 + 1]; 
+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]); 
+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); 
+18    pr_info("%s\n", str); 
 19} 
 20 
-21int cryptosha256_init(void) 
+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; 
+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; 
+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), 
+32    shash = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(sha256), 
 33                    GFP_KERNEL); 
-34    if (!shash) 
-35        return -ENOMEM; 
+34    if (!shash) 
+35        return -ENOMEM; 
 36 
 37    shash->tfm = sha256; 
 38 
-39    if (crypto_shash_init(shash)) 
-40        return -1; 
+39    if (crypto_shash_init(shash)) 
+40        return -1; 
 41 
-42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
-43        return -1; 
+42    if (crypto_shash_update(shash, plaintext, strlen(plaintext))) 
+43        return -1; 
 44 
-45    if (crypto_shash_final(shash, hash_sha256)) 
-46        return -1; 
+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; 
+53    return 0; 
 54} 
 55 
-56void cryptosha256_exit(void) {} 
+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: +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: +

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 +

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

+169    pr_info("Encryption request successful\n"); +170 +171out: +172    return ret; +173} +174 +175int cryptoapi_init(void) +176{ +177    /* The world's favorite password */ +178    char *password = "password123"; +179 +180    sk.tfm = NULL; +181    sk.req = NULL; +182    sk.scratchpad = NULL; +183    sk.ciphertext = NULL; +184    sk.ivdata = NULL; +185 +186    test_skcipher_encrypt("Testing", password, &sk); +187    return 0; +188} +189 +190void cryptoapi_exit(void) +191{ +192    test_skcipher_finish(&sk); +193} +194 +195module_init(cryptoapi_init); +196module_exit(cryptoapi_exit); +197 +198MODULE_DESCRIPTION("Symmetric key encryption example"); +199MODULE_LICENSE("GPL");

+

0.17 Standardizing the interfaces: The Device Model

-

Up to this point we have seen all kinds of modules doing all kinds of things, but there +

Up to this point we have 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 standardized way to start, suspend and resume a device a device model was added. An example is shown below, and you can @@ -4937,59 +4977,59 @@ 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> 
+   
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; 
+8struct devicemodel_data { 
+9    char *greeting; 
+10    int number; 
 11}; 
 12 
-13static int devicemodel_probe(struct platform_device *dev) 
+13static int devicemodel_probe(struct platform_device *dev) 
 14{ 
-15    struct devicemodel_data *pd = 
-16        (struct devicemodel_data *) (dev->dev.platform_data); 
+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); 
+18    pr_info("devicemodel probe\n"); 
+19    pr_info("devicemodel greeting: %s; %d\n", pd->greeting, pd->number); 
 20 
-21    /* Your device initialization code */ 
+21    /* Your device initialization code */ 
 22 
-23    return 0; 
+23    return 0; 
 24} 
 25 
-26static int devicemodel_remove(struct platform_device *dev) 
+26static int devicemodel_remove(struct platform_device *dev) 
 27{ 
-28    pr_info("devicemodel example removed\n"); 
+28    pr_info("devicemodel example removed\n"); 
 29 
-30    /* Your device removal code */ 
+30    /* Your device removal code */ 
 31 
-32    return 0; 
+32    return 0; 
 33} 
 34 
-35static int devicemodel_suspend(struct device *dev) 
+35static int devicemodel_suspend(struct device *dev) 
 36{ 
-37    pr_info("devicemodel example suspend\n"); 
+37    pr_info("devicemodel example suspend\n"); 
 38 
-39    /* Your device suspend code */ 
+39    /* Your device suspend code */ 
 40 
-41    return 0; 
+41    return 0; 
 42} 
 43 
-44static int devicemodel_resume(struct device *dev) 
+44static int devicemodel_resume(struct device *dev) 
 45{ 
-46    pr_info("devicemodel example resume\n"); 
+46    pr_info("devicemodel example resume\n"); 
 47 
-48    /* Your device resume code */ 
+48    /* Your device resume code */ 
 49 
-50    return 0; 
+50    return 0; 
 51} 
 52 
-53static const struct dev_pm_ops devicemodel_pm_ops = { 
+53static const struct dev_pm_ops devicemodel_pm_ops = { 
 54    .suspend = devicemodel_suspend, 
 55    .resume = devicemodel_resume, 
 56    .poweroff = devicemodel_suspend, 
@@ -4998,10 +5038,10 @@ functions.
 59    .restore = devicemodel_resume, 
 60}; 
 61 
-62static struct platform_driver devicemodel_driver = { 
+62static struct platform_driver devicemodel_driver = { 
 63    .driver = 
 64        { 
-65            .name = "devicemodel_example", 
+65            .name = "devicemodel_example", 
 66            .owner = THIS_MODULE, 
 67            .pm = &devicemodel_pm_ops, 
 68        }, 
@@ -5009,43 +5049,40 @@ functions.
 70    .remove = devicemodel_remove, 
 71}; 
 72 
-73static int devicemodel_init(void) 
+73static int devicemodel_init(void) 
 74{ 
-75    int ret; 
+75    int ret; 
 76 
-77    pr_info("devicemodel init\n"); 
+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; 
+81    if (ret) { 
+82        pr_err("Unable to register driver\n"); 
+83        return ret; 
 84    } 
 85 
-86    return 0; 
+86    return 0; 
 87} 
 88 
-89static void devicemodel_exit(void) 
+89static void devicemodel_exit(void) 
 90{ 
-91    pr_info("devicemodel exit\n"); 
+91    pr_info("devicemodel exit\n"); 
 92    platform_driver_unregister(&devicemodel_driver); 
 93} 
 94 
 95module_init(devicemodel_init); 
 96module_exit(devicemodel_exit); 
 97 
-98MODULE_LICENSE("GPL"); 
-99MODULE_DESCRIPTION("Linux Device Model example");
- - - -

+98MODULE_LICENSE("GPL"); +99MODULE_DESCRIPTION("Linux Device Model example");

+

0.18 Optimizations

-

+

0.18.1 Likely and Unlikely conditions

-

Sometimes you might want your code to run as quickly as possible, +

Sometimes you might want your code to run as quickly as possible, especially if it is handling an interrupt or doing something which might cause noticeable latency. If your code contains boolean conditions and if you know that the conditions are almost always likely to evaluate as either @@ -5059,56 +5096,63 @@ to succeed.

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

When the unlikely + + + +

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

-

+

0.19.1 Using standard libraries

-

You can not do that. In a kernel module, you can only use kernel functions which are +

You can not 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 do not enable +

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

+

0.20 Where To Go From Here?

-

For people seriously interested in kernel programming, I recommend kernelnewbies.org +

For people seriously interested in kernel programming, I recommend kernelnewbies.org and the Documentation subdirectory within the kernel source code which is not always easy to understand but can be a starting point for further investigation. Also, as Linus Torvalds said, the best way to learn the kernel is to read the source code yourself. -

If you are interested in more examples of short kernel modules then searching on +

If you are 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 + + + +

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 would like to contribute to this guide or notice anything glaringly wrong, +

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

Happy hacking! +

Happy hacking!

- +

1The goal of threaded interrupts is to push more of the work to separate threads, so that the +minimum needed for acknowledging an interrupt is reduced, and therefore the time spent handling +the interrupt (where it can’t handle any other interrupts at the same time) is reduced. See +https://lwn.net/Articles/302043/

+ \ No newline at end of file diff --git a/lkmpg-for-ht0x.svg b/lkmpg-for-ht0x.svg index a352728..aa3e657 100644 --- a/lkmpg-for-ht0x.svg +++ b/lkmpg-for-ht0x.svg @@ -2,25 +2,25 @@ - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/lkmpg-for-ht1x.svg b/lkmpg-for-ht1x.svg index b61a59c..56485b1 100644 --- a/lkmpg-for-ht1x.svg +++ b/lkmpg-for-ht1x.svg @@ -2,125 +2,125 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -129,23 +129,23 @@ - - + + - - + + - - - + + +