diff --git a/3.16/LKMPG-3.16.html b/3.16/LKMPG-3.16.html index de17eec..02d1968 100644 --- a/3.16/LKMPG-3.16.html +++ b/3.16/LKMPG-3.16.html @@ -3,11 +3,11 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + The Linux Kernel Module Programming Guide - + @@ -56,13 +56,97 @@ border: 1px solid black; } pre.src:hover:before { display: inline;} - pre.src-sh:before { content: 'sh'; } - pre.src-bash:before { content: 'sh'; } + /* Languages per Org manual */ + pre.src-asymptote:before { content: 'Asymptote'; } + pre.src-awk:before { content: 'Awk'; } + pre.src-C:before { content: 'C'; } + /* pre.src-C++ doesn't work in CSS */ + pre.src-clojure:before { content: 'Clojure'; } + pre.src-css:before { content: 'CSS'; } + pre.src-D:before { content: 'D'; } + pre.src-ditaa:before { content: 'ditaa'; } + pre.src-dot:before { content: 'Graphviz'; } + pre.src-calc:before { content: 'Emacs Calc'; } pre.src-emacs-lisp:before { content: 'Emacs Lisp'; } - pre.src-R:before { content: 'R'; } - pre.src-perl:before { content: 'Perl'; } - pre.src-java:before { content: 'Java'; } - pre.src-sql:before { content: 'SQL'; } + pre.src-fortran:before { content: 'Fortran'; } + pre.src-gnuplot:before { content: 'gnuplot'; } + pre.src-haskell:before { content: 'Haskell'; } + pre.src-java:before { content: 'Java'; } + pre.src-js:before { content: 'Javascript'; } + pre.src-latex:before { content: 'LaTeX'; } + pre.src-ledger:before { content: 'Ledger'; } + pre.src-lisp:before { content: 'Lisp'; } + pre.src-lilypond:before { content: 'Lilypond'; } + pre.src-lua:before { content: 'Lua'; } + pre.src-matlab:before { content: 'MATLAB'; } + pre.src-mscgen:before { content: 'Mscgen'; } + pre.src-ocaml:before { content: 'Objective Caml'; } + pre.src-octave:before { content: 'Octave'; } + pre.src-org:before { content: 'Org mode'; } + pre.src-oz:before { content: 'OZ'; } + pre.src-plantuml:before { content: 'Plantuml'; } + pre.src-processing:before { content: 'Processing.js'; } + pre.src-python:before { content: 'Python'; } + pre.src-R:before { content: 'R'; } + pre.src-ruby:before { content: 'Ruby'; } + pre.src-sass:before { content: 'Sass'; } + pre.src-scheme:before { content: 'Scheme'; } + pre.src-screen:before { content: 'Gnu Screen'; } + pre.src-sed:before { content: 'Sed'; } + pre.src-sh:before { content: 'shell'; } + pre.src-sql:before { content: 'SQL'; } + pre.src-sqlite:before { content: 'SQLite'; } + /* additional languages in org.el's org-babel-load-languages alist */ + pre.src-forth:before { content: 'Forth'; } + pre.src-io:before { content: 'IO'; } + pre.src-J:before { content: 'J'; } + pre.src-makefile:before { content: 'Makefile'; } + pre.src-maxima:before { content: 'Maxima'; } + pre.src-perl:before { content: 'Perl'; } + pre.src-picolisp:before { content: 'Pico Lisp'; } + pre.src-scala:before { content: 'Scala'; } + pre.src-shell:before { content: 'Shell Script'; } + pre.src-ebnf2ps:before { content: 'ebfn2ps'; } + /* additional language identifiers per "defun org-babel-execute" + in ob-*.el */ + pre.src-cpp:before { content: 'C++'; } + pre.src-abc:before { content: 'ABC'; } + pre.src-coq:before { content: 'Coq'; } + pre.src-groovy:before { content: 'Groovy'; } + /* additional language identifiers from org-babel-shell-names in + ob-shell.el: ob-shell is the only babel language using a lambda to put + the execution function name together. */ + pre.src-bash:before { content: 'bash'; } + pre.src-csh:before { content: 'csh'; } + pre.src-ash:before { content: 'ash'; } + pre.src-dash:before { content: 'dash'; } + pre.src-ksh:before { content: 'ksh'; } + pre.src-mksh:before { content: 'mksh'; } + pre.src-posh:before { content: 'posh'; } + /* Additional Emacs modes also supported by the LaTeX listings package */ + pre.src-ada:before { content: 'Ada'; } + pre.src-asm:before { content: 'Assembler'; } + pre.src-caml:before { content: 'Caml'; } + pre.src-delphi:before { content: 'Delphi'; } + pre.src-html:before { content: 'HTML'; } + pre.src-idl:before { content: 'IDL'; } + pre.src-mercury:before { content: 'Mercury'; } + pre.src-metapost:before { content: 'MetaPost'; } + pre.src-modula-2:before { content: 'Modula-2'; } + pre.src-pascal:before { content: 'Pascal'; } + pre.src-ps:before { content: 'PostScript'; } + pre.src-prolog:before { content: 'Prolog'; } + pre.src-simula:before { content: 'Simula'; } + pre.src-tcl:before { content: 'tcl'; } + pre.src-tex:before { content: 'TeX'; } + pre.src-plain-tex:before { content: 'Plain TeX'; } + pre.src-verilog:before { content: 'Verilog'; } + pre.src-vhdl:before { content: 'VHDL'; } + pre.src-xml:before { content: 'XML'; } + pre.src-nxml:before { content: 'XML'; } + /* add a generic configuration mode; LaTeX export needs an additional + (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */ + pre.src-conf:before { content: 'Configuration File'; } table { border-collapse:collapse; } caption.t-above { caption-side: top; } @@ -95,11 +179,12 @@ { font-size: 10px; font-weight: bold; white-space: nowrap; } .org-info-js_search-highlight { background-color: #ffff00; color: #000000; font-weight: bold; } + .org-svg { width: 90%; } /*]]>*/--> - - - + + + diff --git a/3.16/LKMPG-3.16.org b/3.16/LKMPG-3.16.org index 99e6480..e7ba22a 100644 --- a/3.16/LKMPG-3.16.org +++ b/3.16/LKMPG-3.16.org @@ -752,34 +752,34 @@ For example, every character driver needs to define a function that reads from t #+BEGIN_SRC c struct file_operations { - struct module *owner; - loff_t (*llseek) (struct file *, loff_t, int); - ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); - ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); - ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - int (*iterate) (struct file *, struct dir_context *); - unsigned int (*poll) (struct file *, struct poll_table_struct *); - long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); - long (*compat_ioctl) (struct file *, unsigned int, unsigned long); - int (*mmap) (struct file *, struct vm_area_struct *); - int (*open) (struct inode *, struct file *); - int (*flush) (struct file *, fl_owner_t id); - int (*release) (struct inode *, struct file *); - int (*fsync) (struct file *, loff_t, loff_t, int datasync); - int (*aio_fsync) (struct kiocb *, int datasync); - int (*fasync) (int, struct file *, int); - int (*lock) (struct file *, int, struct file_lock *); - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); - int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); - int (*setlease)(struct file *, long, struct file_lock **); - long (*fallocate)(struct file *file, int mode, loff_t offset, - loff_t len); - int (*show_fdinfo)(struct seq_file *m, struct file *f); + struct module *owner; + loff_t (*llseek) (struct file *, loff_t, int); + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); + ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + int (*iterate) (struct file *, struct dir_context *); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + long (*compat_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct inode *, struct file *); + int (*flush) (struct file *, fl_owner_t id); + int (*release) (struct inode *, struct file *); + int (*fsync) (struct file *, loff_t, loff_t, int datasync); + int (*aio_fsync) (struct kiocb *, int datasync); + int (*fasync) (int, struct file *, int); + int (*lock) (struct file *, int, struct file_lock *); + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); + int (*setlease)(struct file *, long, struct file_lock **); + long (*fallocate)(struct file *file, int mode, loff_t offset, + loff_t len); + int (*show_fdinfo)(struct seq_file *m, struct file *f); }; #+END_SRC @@ -1074,38 +1074,38 @@ struct proc_dir_entry *Our_Proc_File; ssize_t procfile_read(struct file *filePointer,char *buffer, size_t buffer_length, loff_t * offset) { - int ret=0; - if(strlen(buffer) ==0) { - printk(KERN_INFO "procfile read %s\n",filePointer->f_path.dentry->d_name.name); - ret=copy_to_user(buffer,"HelloWorld!\n",sizeof("HelloWorld!\n")); - ret=sizeof("HelloWorld!\n"); - } - return ret; + int ret=0; + if(strlen(buffer) ==0) { + printk(KERN_INFO "procfile read %s\n",filePointer->f_path.dentry->d_name.name); + ret=copy_to_user(buffer,"HelloWorld!\n",sizeof("HelloWorld!\n")); + ret=sizeof("HelloWorld!\n"); + } + return ret; } static const struct file_operations proc_file_fops = { - .owner = THIS_MODULE, - .read = procfile_read, + .owner = THIS_MODULE, + .read = procfile_read, }; int init_module() { - Our_Proc_File = proc_create(procfs_name,0644,NULL,&proc_file_fops); - if(NULL==Our_Proc_File) { - proc_remove(Our_Proc_File); - printk(KERN_ALERT "Error:Could not initialize /proc/%s\n",procfs_name); - return -ENOMEM; - } + Our_Proc_File = proc_create(procfs_name,0644,NULL,&proc_file_fops); + if(NULL==Our_Proc_File) { + proc_remove(Our_Proc_File); + printk(KERN_ALERT "Error:Could not initialize /proc/%s\n",procfs_name); + return -ENOMEM; + } - printk(KERN_INFO "/proc/%s created\n", procfs_name); - return 0; + printk(KERN_INFO "/proc/%s created\n", procfs_name); + return 0; } void cleanup_module() { - proc_remove(Our_Proc_File); - printk(KERN_INFO "/proc/%s removed\n", procfs_name); + proc_remove(Our_Proc_File); + printk(KERN_INFO "/proc/%s removed\n", procfs_name); } #+END_SRC @@ -1157,13 +1157,13 @@ static unsigned long procfs_buffer_size = 0; ssize_t procfile_read(struct file *filePointer,char *buffer, size_t buffer_length, loff_t * offset) { - int ret=0; - if(strlen(buffer) ==0) { - printk(KERN_INFO "procfile read %s\n",filePointer->f_path.dentry->d_name.name); - ret=copy_to_user(buffer,"HelloWorld!\n",sizeof("HelloWorld!\n")); - ret=sizeof("HelloWorld!\n"); - } - return ret; + int ret=0; + if(strlen(buffer) ==0) { + printk(KERN_INFO "procfile read %s\n",filePointer->f_path.dentry->d_name.name); + ret=copy_to_user(buffer,"HelloWorld!\n",sizeof("HelloWorld!\n")); + ret=sizeof("HelloWorld!\n"); + } + return ret; } @@ -1174,7 +1174,7 @@ ssize_t procfile_read(struct file *filePointer,char *buffer, static ssize_t procfile_write(struct file *file, const char *buff, size_t len, loff_t *off) { - procfs_buffer_size = len; + procfs_buffer_size = len; if (procfs_buffer_size > PROCFS_MAX_SIZE) procfs_buffer_size = PROCFS_MAX_SIZE; @@ -1186,9 +1186,9 @@ static ssize_t procfile_write(struct file *file, const char *buff, } static const struct file_operations proc_file_fops = { - .owner = THIS_MODULE, - .read = procfile_read, - .write = procfile_write, + .owner = THIS_MODULE, + .read = procfile_read, + .write = procfile_write, }; /** @@ -1197,15 +1197,15 @@ static const struct file_operations proc_file_fops = { */ int init_module() { - Our_Proc_File = proc_create(PROCFS_NAME,0644,NULL,&proc_file_fops); - if(NULL==Our_Proc_File) { - proc_remove(Our_Proc_File); - printk(KERN_ALERT "Error:Could not initialize /proc/%s\n",PROCFS_NAME); - return -ENOMEM; - } + Our_Proc_File = proc_create(PROCFS_NAME,0644,NULL,&proc_file_fops); + if(NULL==Our_Proc_File) { + proc_remove(Our_Proc_File); + printk(KERN_ALERT "Error:Could not initialize /proc/%s\n",PROCFS_NAME); + return -ENOMEM; + } - printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME); - return 0; + printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME); + return 0; } /** @@ -1214,8 +1214,8 @@ int init_module() */ void cleanup_module() { - proc_remove(Our_Proc_File); - printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME); + proc_remove(Our_Proc_File); + printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME); } #+END_SRC @@ -1245,7 +1245,7 @@ static char procfs_buffer[PROCFS_MAX_SIZE]; static unsigned long procfs_buffer_size = 0; static ssize_t procfs_read(struct file *filp, char *buffer, - size_t length, loff_t *offset) + size_t length, loff_t *offset) { static int finished = 0; if(finished) @@ -1261,7 +1261,7 @@ static ssize_t procfs_read(struct file *filp, char *buffer, return procfs_buffer_size; } static ssize_t procfs_write(struct file *file, const char *buffer, - size_t len, loff_t *off) + size_t len, loff_t *off) { if(len>PROCFS_MAX_SIZE) procfs_buffer_size = PROCFS_MAX_SIZE; @@ -1302,7 +1302,7 @@ int init_module() proc_set_size(Our_Proc_File, 80); proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); - printk(KERN_DEBUG "/proc/%s created\n", PROCFS_ENTRY_FILENAME); + printk(KERN_DEBUG "/proc/%s created\n", PROCFS_ENTRY_FILENAME); return 0; } void cleanup_module() @@ -1530,49 +1530,49 @@ static struct kobject *mymodule; static int myvariable = 0; static ssize_t myvariable_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) + struct kobj_attribute *attr, + char *buf) { - return sprintf(buf, "%d\n", myvariable); + return sprintf(buf, "%d\n", myvariable); } static ssize_t myvariable_store(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf, size_t count) + struct kobj_attribute *attr, + char *buf, size_t count) { - sscanf(buf, "%du", &myvariable); - return count; + sscanf(buf, "%du", &myvariable); + return count; } static struct kobj_attribute myvariable_attribute = - __ATTR(myvariable, 0660, myvariable_show, - myvariable_store); + __ATTR(myvariable, 0660, myvariable_show, + myvariable_store); static int __init mymodule_init (void) { - int error = 0; + int error = 0; - printk(KERN_INFO "mymodule: initialised\n"); + printk(KERN_INFO "mymodule: initialised\n"); - mymodule = - kobject_create_and_add("mymodule", kernel_kobj); - if (!mymodule) - return -ENOMEM; + mymodule = + kobject_create_and_add("mymodule", kernel_kobj); + if (!mymodule) + return -ENOMEM; - error = sysfs_create_file(mymodule, &myvariable_attribute.attr); - if (error) { - printk(KERN_INFO "failed to create the myvariable file " \ - "in /sys/kernel/mymodule\n"); - } + error = sysfs_create_file(mymodule, &myvariable_attribute.attr); + if (error) { + printk(KERN_INFO "failed to create the myvariable file " \ + "in /sys/kernel/mymodule\n"); + } - return error; + return error; } static void __exit mymodule_exit (void) { - printk(KERN_INFO "mymodule: Exit success\n"); - kobject_put(mymodule); + printk(KERN_INFO "mymodule: Exit success\n"); + kobject_put(mymodule); } module_init(mymodule_init); @@ -2263,7 +2263,7 @@ void cleanup_module() * Blocking Processes -What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: /"Not right now, I'm busy. Go away!"/. But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). +What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: "/Not right now, I'm busy. Go away!/". But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). This kernel module is an example of this. The file (called */proc/sleep*) can only be opened by a single process at a time. If the file is already open, the kernel module calls wait_event_interruptible[12]. This function changes the status of the task (a task is the kernel data structure which holds information about a process and the system call it's in, if any) to *TASK_INTERRUPTIBLE*, which means that the task will not run until it is woken up somehow, and adds it to WaitQ, the queue of tasks waiting to access the file. Then, the function calls the scheduler to context switch to a different process, one which has some use for the CPU. @@ -2460,7 +2460,7 @@ static int module_open(struct inode *inode, struct file *file) for (i = 0; i < _NSIG_WORDS && !is_sig; i++) is_sig = current->pending.signal.sig[i] & ~current-> - blocked.sig[i]; + blocked.sig[i]; if (is_sig) { /* @@ -2485,8 +2485,8 @@ static int module_open(struct inode *inode, struct file *file) /* * Open the file */ - Already_Open = 1; - return 0; /* Allow the access */ + Already_Open = 1; + return 0; /* Allow the access */ } /* @@ -2524,10 +2524,10 @@ int module_close(struct inode *inode, struct file *file) * means we don't want to deal with something. */ static struct file_operations File_Ops_4_Our_Proc_File = { - .read = module_output, /* "read" from the file */ - .write = module_input, /* "write" to the file */ - .open = module_open, /* called when the /proc file is opened */ - .release = module_close, /* called when it's closed */ + .read = module_output, /* "read" from the file */ + .write = module_input, /* "write" to the file */ + .open = module_open, /* called when the /proc file is opened */ + .release = module_close, /* called when it's closed */ }; /* @@ -2996,7 +2996,7 @@ int __init init_module() /* * Create our /proc file */ - Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); + Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); if (Our_Proc_File == NULL) { remove_proc_entry(PROC_ENTRY_FILENAME, NULL); diff --git a/3.16/img/seq_file.png b/3.16/img/seq_file.png index e665ae7..4d15a3a 100644 Binary files a/3.16/img/seq_file.png and b/3.16/img/seq_file.png differ diff --git a/3.8/LKMPG-3.8.html b/3.8/LKMPG-3.8.html index b7b84dc..d811ace 100644 --- a/3.8/LKMPG-3.8.html +++ b/3.8/LKMPG-3.8.html @@ -3,11 +3,11 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + The Linux Kernel Module Programming Guide - + @@ -264,178 +264,178 @@ for the JavaScript code in this tag.

Table of Contents

-The Linux Kernel Module Programming Guide is a free book; you may reproduce and/or modify it under the terms of the Open Software License, version 1.1. You can obtain a copy of this license at http://opensource.org/licenses/osl.php. +The Linux Kernel Module Programming Guide is a free book; you may reproduce and/or modify it under the terms of the Open Software License, version 1.1. You can obtain a copy of this license at http://opensource.org/licenses/osl.php.

@@ -486,12 +486,12 @@ The source code and discussions should apply to most architectures, but I can't The following people have contributed corrections or good suggestions: Ignacio Martin, David Porter, Daniele Paolo Scarpazza, Dimo Velev, Francois Audeon, Horst Schirmeier and Bob Mottram.

-
-

Introduction

-
-
-

What Is A Kernel Module?

-
+
+

Introduction

+
+
+

What Is A Kernel Module?

+

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

@@ -502,9 +502,9 @@ What exactly is a kernel module? Modules are pieces of code that can be loaded a
-
-

How Do Modules Get Into The Kernel?

-
+
+

How Do Modules Get Into The Kernel?

+

You can see what modules are already loaded into the kernel by running lsmod, which gets its information by reading the file /proc/modules.

@@ -573,9 +573,9 @@ Now you know how modules get into the kernel. There's a bit more to the story if

-
-

Before We Begin

-
+
+

Before We Begin

+

Before we delve into code, there are a few issues we need to cover. Everyone's system is different and everyone has their own groove. Getting @@ -585,7 +585,7 @@ for the first time, it will be smooth sailing thereafter.

-
  • Modversioning
    +
    • Modversioning

      A module compiled for one kernel won't load if you boot a different kernel unless you enable CONFIG_MODVERSIONS in the kernel. We won't go into module @@ -597,7 +597,7 @@ versioning errors, compile a kernel with modversioning turned off.

    • -
    • Using X
      +
    • Using X

      It is highly recommended that you type in, compile and load all the examples this guide discusses. It's also highly recommended you do this from a @@ -614,7 +614,7 @@ information, do all your work from the console.

    • -
    • Compiling Issues and Kernel Version
      +
    • Compiling Issues and Kernel Version

      Very often, Linux distros will distribute kernel source that has been patched in various non-standard ways, which may cause trouble. @@ -644,12 +644,12 @@ by using gcc's -I switch.

    -
    -

    Hello World

    -
    -
    -

    Hello, World (part 1): The Simplest Module

    -
    +
    +

    Hello World

    +
    +
    +

    Hello, World (part 1): The Simplest Module

    +

    When the first caveman programmer chiseled the first program on the walls of the first cave computer, it was a program to paint the string `Hello, world' in Antelope pictures. Roman programming textbooks began with the `Salut, Mundi' program. I don't know what happens to people who break with this tradition, but I think it's safer not to find out. We'll start with a series of hello world programs that demonstrate the different aspects of the basics of writing a kernel module.

    @@ -659,9 +659,9 @@ Here's the simplest module possible. Don't compile it yet; we'll cover module co

    -
    -

    Example: hello-1.c

    -
    +
    +

    Example: hello-1.c

    +

    #+BEGIN_SRC: c /* @@ -670,7 +670,7 @@ Here's the simplest module possible. Don't compile it yet; we'll cover module co

  • hello-1.c - The simplest kernel module.

-/ + / #include <linux/module.h> / Needed by all modules / #include <linux/kernel.h> / Needed for KERN_INFO */

@@ -688,8 +688,8 @@ int init_module(void)
  • A non 0 return means init_module failed; module can't be loaded.
  • - */ -return 0; + */ + return 0; }

    @@ -717,9 +717,9 @@ Lastly, every kernel module needs to include linux/module.h. We needed to includ
    -
    -

    Introducing printk()

    -
    +
    +

    Introducing printk()

    +

    Despite what you might think, printk() was not meant to communicate information to the user, even though we used it for exactly this purpose in hello-1! It happens to be a logging mechanism for the kernel, and is used to log information or give warnings. Therefore, each printk() statement comes with a priority, which is the <1> and KERN_ALERT you see. There are 8 priorities and the kernel has macros for them, so you don't have to use cryptic numbers, and you can view them (and their meanings) in linux/kernel.h. If you don't specify a priority level, the default priority, DEFAULT_MESSAGE_LOGLEVEL, will be used. @@ -735,9 +735,9 @@ If the priority is less than int console_loglevel, the message is printed on you

    -
    -

    Compiling Kernel Modules

    -
    +
    +

    Compiling Kernel Modules

    +

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

    @@ -747,9 +747,9 @@ So, let's look at a simple Makefile for compiling a module named hello-1.c:

    -
    -

    Example: Makefile for a basic kernel module

    -
    +
    +

    Example: Makefile for a basic kernel module

    +
    obj-m += hello-1.o
     
    @@ -846,17 +846,17 @@ Here's another exercise for the reader. See that comment above the return statem
     
    -
    -

    Hello World (part 2)

    -
    +
    +

    Hello World (part 2)

    +

    As of Linux 2.4, you can rename the init and cleanup functions of your modules; they no longer have to be called init_module() and cleanup_module() respectively. This is done with the module_init() and module_exit() macros. These macros are defined in linux/init.h. The only caveat is that your init and cleanup functions must be defined before calling the macros, otherwise you'll get compilation errors. Here's an example of this technique:

    -
    -

    Example: hello-2.c

    -
    +
    +

    Example: hello-2.c

    +

    #+BEGIN_SRC: c /* @@ -866,7 +866,7 @@ As of Linux 2.4, you can rename the init and cleanup functions of your modules;

  • This is preferred over using init_module() and cleanup_module().
  • -/ + / #include <linux/module.h> / Needed by all modules / #include <linux/kernel.h> / Needed for KERN_INFO / #include <linux/init.h> / Needed for the macros */ @@ -899,9 +899,9 @@ So now we have two real kernel modules under our belt. Adding another module is

    -
    -

    Example: Makefile for both our modules

    -
    +
    +

    Example: Makefile for both our modules

    +
    obj-m += hello-1.o
     obj-m += hello-2.o
    @@ -922,9 +922,9 @@ you can see, some things get hardwired into the kernel (obj-y) but where are all
     
    -
    -

    Hello World (part 3): The __init and __exit Macros

    -
    +
    +

    Hello World (part 3): The __init and __exit Macros

    +

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

    @@ -942,9 +942,9 @@ These macros are defined in linux/init.h and serve to free up kernel memory. Whe

    -
    -

    Example: hello-3.c

    -
    +
    +

    Example: hello-3.c

    +

    #+BEGIN_SRC: c /* @@ -953,7 +953,7 @@ These macros are defined in linux/init.h and serve to free up kernel memory. Whe

  • hello-3.c - Illustrating the __init, __initdata and __exit macros.
  • -/ + / #include <linux/module.h> / Needed by all modules / #include <linux/kernel.h> / Needed for KERN_INFO / #include <linux/init.h> / Needed for the macros */ @@ -987,9 +987,9 @@ module_exit(hello_3_exit);

    -
    -

    Hello World (part 4): Licensing and Module Documentation

    -
    +
    +

    Hello World (part 4): Licensing and Module Documentation

    +

    If you're running kernel 2.4 or later, you might have noticed something like this when you loaded proprietary modules:

    @@ -1047,7 +1047,7 @@ In kernel 2.4 and later, a mechanism was devised to identify code licensed under
  • 3. So vendors can do likewise based on their own policies
  • -*/ + */ #+END_SRC

    @@ -1069,9 +1069,9 @@ Users of traditional Unix editors, like emacs or vi will also find tag files use
    -
    -

    Example: hello-4.c

    -
    +
    +

    Example: hello-4.c

    +

    #+BEGIN_SRC: c /* @@ -1080,7 +1080,7 @@ Users of traditional Unix editors, like emacs or vi will also find tag files use

  • hello-4.c - Demonstrates module documentation.
  • -/ + / #include <linux/module.h> / Needed by all modules / #include <linux/kernel.h> / Needed for KERN_INFO / #include <linux/init.h> / Needed for the macros */ @@ -1125,7 +1125,7 @@ module_exit(cleanup_hello_4);

  • Get rid of taint message by declaring code as GPL.
  • -*/ + */ MODULE_LICENSE("GPL");

    @@ -1136,7 +1136,7 @@ MODULE_LICENSE("GPL");
  • Or with defines, like this:
  • -/ + / MODULE_AUTHOR(DRIVER_AUTHOR); / Who wrote this module? / MODULE_DESCRIPTION(DRIVER_DESC); / What does this module do */

    @@ -1150,7 +1150,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); / What does this module do */
  • currently unused other than for documentation purposes.
  • -*/ + */ MODULE_SUPPORTED_DEVICE("testdevice"); #+END_SRC

    @@ -1158,9 +1158,9 @@ MODULE_SUPPORTED_DEVICE("testdevice");
    -
    -

    Passing Command Line Arguments to a Module

    -
    +
    +

    Passing Command Line Arguments to a Module

    +

    Modules can take command line arguments, but not with the argc/argv you might be used to.

    @@ -1207,9 +1207,9 @@ Lastly, there's a macro function, MODULE_PARM_DESC(), that is used to document a
    -
    -

    Example: hello-5.c

    -
    +
    +

    Example: hello-5.c

    +

    #+BEGIN_SRC: c /* @@ -1218,7 +1218,7 @@ Lastly, there's a macro function, MODULE_PARM_DESC(), that is used to document a

  • hello-5.c - Demonstrates command line argument passing to a module.
  • -*/ + */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -1277,7 +1277,7 @@ MODULE_PARM_DESC(mystring, "A character string");

  • The fourth argument is the permission bits
  • -*/ + */ module_param_array(myintArray, int, &arr_argc, 0000); MODULE_PARM_DESC(myintArray, "An array of integers");

    @@ -1358,9 +1358,9 @@ hello-5.o: invalid argument syntax for mylong: 'h'
    -
    -

    Modules Spanning Multiple Files

    -
    +
    +

    Modules Spanning Multiple Files

    +

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

    @@ -1370,9 +1370,9 @@ Here's an example of such a kernel module.

    -
    -

    Example: start.c

    -
    +
    +

    Example: start.c

    +

    #+BEGIN_SRC: c /* @@ -1405,9 +1405,9 @@ The next file:

    -
    -

    Example: stop.c

    -
    +
    +

    Example: stop.c

    +

    #+BEGIN_SRC: c /* @@ -1439,9 +1439,9 @@ And finally, the makefile:

    -
    -

    Example: Makefile

    -
    +
    +

    Example: Makefile

    +

    #+BEGIN_SRC: makefile obj-m += hello-1.o @@ -1474,9 +1474,9 @@ make what object files are part of that module.

    -
    -

    Building modules for a precompiled kernel

    -
    +
    +

    Building modules for a precompiled kernel

    +

    Obviously, we strongly suggest you to recompile your kernel, so that you can enable a number of useful debugging features, such as forced module unloading (MODULE_FORCE_UNLOAD): when this option is enabled, you can force the kernel to unload a module even when it believes it is unsafe, via a rmmod -f module command. This option can save you a lot of time and a number of reboots during the development of a module.

    @@ -1573,12 +1573,12 @@ If you do not desire to actually compile the kernel, you can interrupt the build
    -
    -

    Preliminaries

    -
    -
    -

    How modules begin and end

    -
    +
    +

    Preliminaries

    +
    +
    +

    How modules begin and end

    +

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

    @@ -1593,9 +1593,9 @@ Every module must have an entry function and an exit function. Since there's mor
    -
    -

    Functions available to modules

    -
    +
    +

    Functions available to modules

    +

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

    @@ -1630,9 +1630,9 @@ You can even write modules to replace the kernel's system calls, which we'll do
    -
    -

    User Space vs Kernel Space

    -
    +
    +

    User Space vs Kernel Space

    +

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

    @@ -1643,9 +1643,9 @@ Recall the discussion about library functions vs system calls. Typically, you us
    -
    -

    Name Space

    -
    +
    +

    Name Space

    +

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

    @@ -1660,9 +1660,9 @@ The file /proc/kallsyms holds all the symbols that the kernel knows about
    -
    -

    Code space

    -
    +
    +

    Code space

    +

    Memory management is a very complicated subject—the majority of O'Reilly's `Understanding The Linux Kernel' is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.

    @@ -1681,15 +1681,15 @@ By the way, I would like to point out that the above discussion is true for any
    -
    -

    Device Drivers

    -
    +
    +

    Device Drivers

    +

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

    -
    • Major and Minor Numbers
      +
      • Major and Minor Numbers

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

        @@ -1757,12 +1757,12 @@ By now you can look at these two device files and know instantly that they are b
      -
      -

      Character Device drivers

      -
      -
      -

      The file_operations Structure

      -
      +
      +

      Character Device drivers

      +
      +
      +

      The file_operations Structure

      +

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

      @@ -1850,9 +1850,9 @@ An instance of struct file_operations containing pointers to functions that are
      -
      -

      The file structure

      -
      +
      +

      The file structure

      +

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

      @@ -1867,9 +1867,9 @@ Go ahead and look at the definition of file. Most of the entries you see, like s
      -
      -

      Registering A Device

      -
      +
      +

      Registering A Device

      +

      As discussed earlier, char devices are accessed through device files, usually located in /dev[7]. The major number tells you which driver handles which device file. The minor number is used only by the driver itself to differentiate which device it's operating on, just in case the driver handles more than one device.

      @@ -1898,9 +1898,9 @@ If you pass a major number of 0 to register_chrdev, the return value will be the
      -
      -

      Unregistering A Device

      -
      +
      +

      Unregistering A Device

      +

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

      @@ -1921,9 +1921,9 @@ It's important to keep the counter accurate; if you ever do lose track of the co
      -
      -

      chardev.c

      -
      +
      +

      chardev.c

      +

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

      @@ -1939,9 +1939,9 @@ cat /proc/devices

      -
      -

      Example: chardev.c

      -
      +
      +

      Example: chardev.c

      +

      #+BEGIN_SRC: c /* @@ -1968,7 +1968,7 @@ cat /proc/devices

    • Prototypes - this would normally go in a .h file

    -*/ + */ int init_module(void); void cleanup_module(void); static int device_open(struct inode *, struct file *); @@ -2021,10 +2021,10 @@ static struct file_operations fops = {

  • This function is called when the module is loaded
  • -*/ + */ int init_module(void) { - Major = register_chrdev(0, DEVICE_NAME, &fops); + Major = register_chrdev(0, DEVICE_NAME, &fops);

    @@ -2044,7 +2044,7 @@ printk(KERN_INFO "Remove the device file and module when done.\n");

    -return SUCCESS; + return SUCCESS; }

    @@ -2055,17 +2055,17 @@ return SUCCESS;
  • This function is called when the module is unloaded
  • -*/ + */ void cleanup_module(void) { - /* + /*

    • Unregister the device

    - */ -unregister_chrdev(Major, DEVICE_NAME); + */ + unregister_chrdev(Major, DEVICE_NAME); }

    @@ -2087,10 +2087,10 @@ unregister_chrdev(Major, DEVICE_NAME);
  • "cat /dev/mycharfile"
  • -*/ + */ static int device_open(struct inode *inode, struct file *file) { - static int counter = 0; + static int counter = 0;

    @@ -2106,7 +2106,7 @@ try_module_get(THIS_MODULE);

    -return SUCCESS; + return SUCCESS; }

    @@ -2117,10 +2117,10 @@ return SUCCESS;
  • Called when a process closes the device file.
  • -*/ + */ static int device_release(struct inode *inode, struct file *file) { - Device_Open–; * We're now ready for our next caller * + Device_Open–; * We're now ready for our next caller *

    @@ -2136,7 +2136,7 @@ module_put(THIS_MODULE);

    -return 0; + return 0; }

    @@ -2148,13 +2148,13 @@ return 0;
  • read from it.
  • -/ + / static ssize_t device_read(struct file *filp, / see include/linux/fs.h / - char *buffer, / buffer to fill with data / - size_t length, / length of the buffer */ - loff_t * offset) + char *buffer, / buffer to fill with data / + size_t length, / length of the buffer */ + loff_t * offset) { - /* + /*

    • Number of bytes actually written to the buffer
    • @@ -2215,8 +2215,8 @@ put_user(*(msg_Ptr++), buffer++);
    • Most read functions return the number of bytes put into the buffer

    - */ -return bytes_read; + */ + return bytes_read; }

    @@ -2227,12 +2227,12 @@ return bytes_read;
  • Called when a process writes to dev file: echo "hi" > /dev/hello
  • -*/ + */ static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off) { - printk(KERN_ALERT "Sorry, this operation isn't supported.\n"); - return -EINVAL; + printk(KERN_ALERT "Sorry, this operation isn't supported.\n"); + return -EINVAL; } #+END_SRC

    @@ -2240,9 +2240,9 @@ device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
    -
    -

    Writing Modules for Multiple Kernel Versions

    -
    +
    +

    Writing Modules for Multiple Kernel Versions

    +

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

    @@ -2266,9 +2266,9 @@ Update: What we've said above was true for kernels up to and including 2.6.10. Y
    -
    -

    The /proc File System

    -
    +
    +

    The /proc File System

    +

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

    @@ -2305,9 +2305,9 @@ HelloWorld!

    -
    -

    Example: procfs1.c

    -
    +
    +

    Example: procfs1.c

    +

    #+BEGIN_SRC: c /* @@ -2338,7 +2338,7 @@ HelloWorld!

  • -*/ + */ struct proc_dir_entry *Our_Proc_File;

    @@ -2386,13 +2386,13 @@ struct proc_dir_entry *Our_Proc_File;
  • free - use it.
  • -*/ + */ int procfile_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) + char **buffer_location, + off_t offset, int buffer_length, int *eof, void *data) { - int ret; + int ret;

    @@ -2426,7 +2426,7 @@ if (offset > 0) {

    -return ret; + return ret; }

    @@ -2455,8 +2455,8 @@ Our_Proc_File->size = 37;

    -printk(KERN_INFO "proc/%s created\n", procfs_name); -return 0; /* everything is ok * + printk(KERN_INFO "proc/%s created\n", procfs_name); + return 0; /* everything is ok * }

    @@ -2471,9 +2471,9 @@ void cleanup_module()
    -
    -

    Read and Write a /proc File

    -
    +
    +

    Read and Write a /proc File

    +

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

    @@ -2487,9 +2487,9 @@ The only memory segment accessible to a process is its own, so when writing regu

    -
    -

    Example: procfs2.c

    -
    +
    +

    Example: procfs2.c

    +

    #+BEGIN_SRC: c /** @@ -2522,7 +2522,7 @@ The only memory segment accessible to a process is its own, so when writing regu

  • -*/ + */ static struct proc_dir_entry *Our_Proc_File;

    @@ -2534,7 +2534,7 @@ static struct proc_dir_entry *Our_Proc_File;
  • -*/ + */ static char procfs_buffer[PROCFS_MAX_SIZE];

    @@ -2546,7 +2546,7 @@ static char procfs_buffer[PROCFS_MAX_SIZE];
  • -*/ + */ static unsigned long procfs_buffer_size = 0;

    @@ -2558,13 +2558,13 @@ static unsigned long procfs_buffer_size = 0;
  • -*/ + */ int procfile_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) + char **buffer_location, + off_t offset, int buffer_length, int *eof, void *data) { - int ret; + int ret;

    @@ -2583,7 +2583,7 @@ if (offset > 0) {

    -return ret; + return ret; }

    @@ -2595,15 +2595,15 @@ return ret;
  • -*/ + */ int procfile_write(struct file *file, const char *buffer, unsigned long count, - void *data) + void *data) { - * get buffer size * - procfs_buffer_size = count; - if (procfs_buffer_size > PROCFS_MAX_SIZE ) { - procfs_buffer_size = PROCFS_MAX_SIZE; - } + * get buffer size * + procfs_buffer_size = count; + if (procfs_buffer_size > PROCFS_MAX_SIZE ) { + procfs_buffer_size = PROCFS_MAX_SIZE; + }

    @@ -2614,7 +2614,7 @@ if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {

    -return procfs_buffer_size; + return procfs_buffer_size; }

    @@ -2626,11 +2626,11 @@ return procfs_buffer_size;
  • -*/ + */ int init_module() { - * create the /proc file * - Our_Proc_File = proc_create(PROCFS_NAME, 0, NULL, NULL); + * create the /proc file * + Our_Proc_File = proc_create(PROCFS_NAME, 0, NULL, NULL);

    @@ -2652,8 +2652,8 @@ Our_Proc_File->size = 37;

    -printk(KERN_INFO "proc/%s created\n", PROCFS_NAME); -return 0; /* everything is ok * + printk(KERN_INFO "proc/%s created\n", PROCFS_NAME); + return 0; /* everything is ok * }

    @@ -2665,11 +2665,11 @@ return 0; /* everything is ok *
  • -*/ + */ void cleanup_module() { - remove_proc_entry(PROCFS_NAME, NULL); - printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME); + remove_proc_entry(PROCFS_NAME, NULL); + printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME); } #+END_SRC

    @@ -2677,9 +2677,9 @@ void cleanup_module()
    -
    -

    Manage /proc file with standard filesystem

    -
    +
    +

    Manage /proc file with standard filesystem

    +

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

    @@ -2697,9 +2697,9 @@ It's important to note that the standard roles of read and write are reversed in

    -
    -

    Example: procfs3.c

    -
    +
    +

    Example: procfs3.c

    +

    #+BEGIN_SRC: c /* @@ -2733,7 +2733,7 @@ It's important to note that the standard roles of read and write are reversed in

  • -*/ + */ static char procfs_buffer[PROCFS_MAX_SIZE];

    @@ -2745,7 +2745,7 @@ static char procfs_buffer[PROCFS_MAX_SIZE];
  • -*/ + */ static unsigned long procfs_buffer_size = 0;

    @@ -2757,7 +2757,7 @@ static unsigned long procfs_buffer_size = 0;
  • -*/ + */ static struct proc_dir_entry *Our_Proc_File;

    @@ -2769,13 +2769,13 @@ static struct proc_dir_entry *Our_Proc_File;
  • -/ + / static ssize_t procfs_read(struct file *filp, / see include/linux/fs.h / - char *buffer, / buffer to fill with data / - size_t length, / length of the buffer */ - loff_t * offset) + char *buffer, / buffer to fill with data / + size_t length, / length of the buffer */ + loff_t * offset) { - static int finished = 0; + static int finished = 0;

    @@ -2820,7 +2820,7 @@ printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size);

    -return procfs_buffer_size; * Return the number of bytes "read" * + return procfs_buffer_size; * Return the number of bytes "read" * }

    @@ -2831,16 +2831,16 @@ return procfs_buffer_size; * Return the number of bytes "read" *
  • This function is called when /proc is written
  • -*/ + */ static ssize_t procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off) { - if ( len > PROCFS_MAX_SIZE ) { - procfs_buffer_size = PROCFS_MAX_SIZE; - } - else { - procfs_buffer_size = len; - } + if ( len > PROCFS_MAX_SIZE ) { + procfs_buffer_size = PROCFS_MAX_SIZE; + } + else { + procfs_buffer_size = len; + }

    @@ -2854,7 +2854,7 @@ printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size);

    -return procfs_buffer_size; + return procfs_buffer_size; }

    @@ -2878,10 +2878,10 @@ return procfs_buffer_size;
  • for referece only, and can be overridden here.
  • -*/ + */ static int module_permission(struct inode *inode, int op) { - /* + /*

    • We allow everybody to read from our module, but
    • @@ -2900,8 +2900,8 @@ if (op = 4 || (op = 2 && current_euid() == 0))
    • If it's anything else, access is denied

    - */ -return -EACCES; + */ + return -EACCES; }

    @@ -2914,11 +2914,11 @@ return -EACCES;
  • module's reference count.
  • -*/ + */ int procfs_open(struct inode *inode, struct file *file) { - try_module_get(THIS_MODULE); - return 0; + try_module_get(THIS_MODULE); + return 0; }

    @@ -2930,11 +2930,11 @@ int procfs_open(struct inode *inode, struct file *file)
  • of the reference count.
  • -*/ + */ int procfs_close(struct inode *inode, struct file *file) { - module_put(THIS_MODULE); - return 0; * success * + module_put(THIS_MODULE); + return 0; * success * }

    @@ -2976,11 +2976,11 @@ static struct inode_operations Inode_Ops_4_Our_Proc_File = {
  • Module initialization and cleanup
  • -*/ + */ int init_module() { - * create the /proc file * - Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); + * create the /proc file * + Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL);

    @@ -3006,7 +3006,7 @@ printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);

    -return 0; * success * + return 0; * success * }

    @@ -3026,9 +3026,9 @@ Still hungry for procfs examples? Well, first of all keep in mind, there are rum
    -
    -

    Manage /proc file with seq_file

    -
    +
    +

    Manage /proc file with seq_file

    +

    As we have seen, writing a /proc file may be quite "complex". So to help people writting /proc file, there is an API named seq_file that helps @@ -3046,9 +3046,9 @@ BE CARREFUL: when a sequence is finished, another one starts. That means that at

    -
    -

    Figure: How seq_file works

    -
    +
    +

    Figure: How seq_file works

    +
    @@ -3069,9 +3069,9 @@ BE CARREFUL: when a sequence is finished, another one starts. That means that at -
    -

    Example: procfs4.c

    -
    +
    +

    Example: procfs4.c

    +

    #+BEGIN_SRC: c /** @@ -3112,23 +3112,23 @@ MODULE_LICENSE("GPL");

  • -*/ + */ static void *my_seq_start(struct seq_file *s, loff_t *pos) { - static unsigned long counter = 0; + static unsigned long counter = 0;

    -* beginning a new sequence ? * -if ( pos == 0 ) { - / yes => return a non null value to begin the sequence */ - return &counter; -} -else { - * no => it's the end of the sequence, return end to stop reading * - *pos = 0; - return NULL; -} + * beginning a new sequence ? * + if ( pos == 0 ) { + / yes => return a non null value to begin the sequence */ + return &counter; + } + else { + * no => it's the end of the sequence, return end to stop reading * + *pos = 0; + return NULL; + } }

    @@ -3141,13 +3141,13 @@ else {
  • -*/ + */ static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos) { - unsigned long *tmp_v = (unsigned long *)v; - (*tmp_v)++; - (*pos)++; - return NULL; + unsigned long *tmp_v = (unsigned long *)v; + (*tmp_v)++; + (*pos)++; + return NULL; }

    @@ -3159,10 +3159,10 @@ static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
  • -*/ + */ static void my_seq_stop(struct seq_file *s, void *v) { - * nothing to do, we use a static value in start() * + * nothing to do, we use a static value in start() * }

    @@ -3174,15 +3174,15 @@ static void my_seq_stop(struct seq_file *s, void *v)
  • -*/ + */ static int my_seq_show(struct seq_file *s, void *v) { - loff_t *spos = (loff_t *) v; + loff_t *spos = (loff_t *) v;

    -seq_printf(s, "%Ld\n", *spos); -return 0; + seq_printf(s, "%Ld\n", *spos); + return 0; }

    @@ -3194,12 +3194,12 @@ return 0;
  • -*/ + */ static struct seq_operations my_seq_ops = { - .start = my_seq_start, - .next = my_seq_next, - .stop = my_seq_stop, - .show = my_seq_show + .start = my_seq_start, + .next = my_seq_next, + .stop = my_seq_stop, + .show = my_seq_show };

    @@ -3211,10 +3211,10 @@ static struct seq_operations my_seq_ops = {
  • -*/ + */ static int my_open(struct inode *inode, struct file *file) { - return seq_open(file, &my_seq_ops); + return seq_open(file, &my_seq_ops); };

    @@ -3226,13 +3226,13 @@ static int my_open(struct inode *inode, struct file *file)
  • -*/ + */ static struct file_operations my_file_ops = { - .owner = THIS_MODULE, - .open = my_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release + .owner = THIS_MODULE, + .open = my_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release };

    @@ -3245,10 +3245,10 @@ static struct file_operations my_file_ops = {
  • -*/ + */ int init_module(void) { - struct proc_dir_entry *entry; + struct proc_dir_entry *entry;

    @@ -3259,7 +3259,7 @@ if (entry) {

    -return 0; + return 0; }

    @@ -3271,10 +3271,10 @@ return 0;
  • -*/ + */ void cleanup_module(void) { - remove_proc_entry(PROC_NAME, NULL); + remove_proc_entry(PROC_NAME, NULL); } #+END_SRC

    @@ -3298,12 +3298,12 @@ You can also read the code of fs/seq_file.c in the linux kernel.
    -
    -

    Using /proc For Input

    -
    -
    -

    TODO : Write a chapter about sysfs

    -
    +
    +

    Using /proc For Input

    +
    +
    +

    TODO : Write a chapter about sysfs

    +

    This is just a placeholder for now. Finally I'd like to see a (yet to be written) chapter about sysfs instead here. If you are familiar with sysfs and would like to take part in writing this chapter, feel free to contact us (the LKMPG maintainers) for further details.

    @@ -3311,9 +3311,9 @@ This is just a placeholder for now. Finally I'd like to see a (yet to be written
    -
    -

    Talking To Device Files

    -
    +
    +

    Talking To Device Files

    +

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

    @@ -3335,9 +3335,9 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o

    -
    -

    Example: chardev.c

    -
    +
    +

    Example: chardev.c

    +

    #+BEGIN_SRC: c /* @@ -3368,7 +3368,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o

  • concurent access into the same device
  • -*/ + */ static int Device_Open = 0;

    @@ -3379,7 +3379,7 @@ static int Device_Open = 0;
  • The message the device will give when asked
  • -*/ + */ static char Message[BUF_LEN];

    @@ -3392,7 +3392,7 @@ static char Message[BUF_LEN];
  • buffer we get to fill in device_read.
  • -*/ + */ static char *Message_Ptr;

    @@ -3403,11 +3403,11 @@ static char *Message_Ptr;
  • This is called whenever a process attempts to open the device file
  • -*/ + */ static int device_open(struct inode *inode, struct file *file) { #ifdef DEBUG - printk(KERN_INFO "device_open(%p)\n", file); + printk(KERN_INFO "device_open(%p)\n", file); #endif

    @@ -3431,10 +3431,10 @@ Device_Open++;
  • Initialize the message
  • - */ -Message_Ptr = Message; -try_module_get(THIS_MODULE); -return SUCCESS; + */ + Message_Ptr = Message; + try_module_get(THIS_MODULE); + return SUCCESS; }

    @@ -3458,8 +3458,8 @@ Device_Open–;

    -module_put(THIS_MODULE); -return SUCCESS; + module_put(THIS_MODULE); + return SUCCESS; }

    @@ -3471,18 +3471,18 @@ return SUCCESS;
  • device file attempts to read from it.
  • -/ + / static ssize_t device_read(struct file *file, / see include/linux/fs.h / - char __user * buffer, / buffer to be + char __user * buffer, / buffer to be

    • filled with data */

    - size_t length, * length of the buffer * - loff_t * offset) + size_t length, * length of the buffer * + loff_t * offset) { -/* + /*

    • Number of bytes actually written to the buffer
    • @@ -3533,10 +3533,10 @@ while (length && *Message_Ptr) {
    • user data segment.

    -*/ -put_user(*(Message_Ptr++), buffer++); -length–; -bytes_read++; + */ + put_user(*(Message_Ptr++), buffer++); + length–; + bytes_read++; }

    @@ -3554,8 +3554,8 @@ bytes_read++;
  • of bytes actually inserted into the buffer
  • - */ -return bytes_read; + */ + return bytes_read; }

    @@ -3567,12 +3567,12 @@ return bytes_read;
  • write into our device file.
  • -*/ + */ static ssize_t device_write(struct file *file, - const char __user * buffer, size_t length, loff_t * offset) + const char __user * buffer, size_t length, loff_t * offset) { - int i; + int i;

    @@ -3597,8 +3597,8 @@ Message_Ptr = Message;

  • Again, return the number of input characters used
  • - */ -return i; + */ + return i; }

    @@ -3617,14 +3617,14 @@ return i;
  • -/ + / long device_ioctl(struct file *file, / ditto / - unsigned int ioctl_num, / number and param for ioctl */ - unsigned long ioctl_param) + unsigned int ioctl_num, / number and param for ioctl */ + unsigned long ioctl_param) { - int i; - char *temp; - char ch; + int i; + char *temp; + char ch;

    @@ -3709,7 +3709,7 @@ case IOCTL_GET_NTH_BYTE:

    -return SUCCESS; + return SUCCESS; }

    @@ -3728,13 +3728,13 @@ return SUCCESS;
  • init_module. NULL is for unimplemented functions.
  • -*/ + */ struct file_operations Fops = { - .read = device_read, - .write = device_write, - .unlocked_ioctl = device_ioctl, - .open = device_open, - .release = device_release, * a.k.a. close * + .read = device_read, + .write = device_write, + .unlocked_ioctl = device_ioctl, + .open = device_open, + .release = device_release, * a.k.a. close * };

    @@ -3745,11 +3745,11 @@ struct file_operations Fops = {
  • Initialize the module - Register the character device
  • -*/ + */ int init_module() { - int ret_val; - /* + int ret_val; + /*

    • Register the character device (atleast try)
    • @@ -3787,7 +3787,7 @@ printk(KERN_INFO "file you'll use.\n");

      -return 0; + return 0; }

      @@ -3798,26 +3798,26 @@ return 0;
    • Cleanup - unregister the appropriate file from /proc

    -*/ + */ void cleanup_module() { - /* + /*

    • Unregister the device

    - */ -unregister_chrdev(MAJOR_NUM, DEVICE_NAME); + */ + unregister_chrdev(MAJOR_NUM, DEVICE_NAME); } #+END_SRC

    -
    -

    Example: chardev.h

    -
    +
    +

    Example: chardev.h

    +

    #+BEGIN_SRC: c /* @@ -3852,7 +3852,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);

  • it.
  • -*/ + */ #define MAJOR_NUM 100

    @@ -3863,7 +3863,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
  • Set the message of the device driver
  • -*/ + */ #define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char ) /

    @@ -3895,7 +3895,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
  • Get the message of the device driver
  • -*/ + */ #define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char ) /

    @@ -3916,7 +3916,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
  • Get the n'th byte of the message
  • -*/ + */ #define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int) /*

    @@ -3936,7 +3936,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
  • The name of the device file
  • -*/ + */ #define DEVICE_FILE_NAME "char_dev"

    @@ -3947,9 +3947,9 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
    -
    -

    Example: ioctl.c

    -
    +
    +

    Example: ioctl.c

    +

    #+BEGIN_SRC: c /* @@ -3973,7 +3973,7 @@ unregister_chrdev(MAJOR_NUM, DEVICE_NAME);

  • major device file.
  • -*/ + */ #include "chardev.h"

    @@ -4006,10 +4006,10 @@ ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

    -if (ret_val < 0) { - printf("ioctl_set_msg failed:%d\n", ret_val); - exit(-1); -} + if (ret_val < 0) { + printf("ioctl_set_msg failed:%d\n", ret_val); + exit(-1); + } }

    @@ -4044,7 +4044,7 @@ if (ret_val < 0) {

    -printf("get_msg %s\n", message); + printf("get_msg message:%s\n", message); }

    @@ -4074,9 +4074,9 @@ if (c < 0) {

    - putchar(c); -} while (c != 0); -putchar('\n'); + putchar(c); + } while (c != 0); + putchar('\n'); }

    @@ -4087,11 +4087,11 @@ putchar('\n');
  • Main - Call the ioctl functions
  • -*/ + */ main() { - int file_desc, ret_val; - char *msg = "Message passed by ioctl\n"; + int file_desc, ret_val; + char *msg = "Message passed by ioctl\n";

    @@ -4109,7 +4109,7 @@ ioctl_set_msg(file_desc, msg);

    -close(file_desc); + close(file_desc); } #+END_SRC

    @@ -4117,9 +4117,9 @@ close(file_desc);
    -
    -

    System Calls

    -
    +
    +

    System Calls

    +

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

    @@ -4165,9 +4165,9 @@ Note that all the related problems make syscall stealing unfeasiable for product

    -
    -

    Example: syscall.c

    -
    +
    +

    Example: syscall.c

    +

    #+BEGIN_SRC: c /* @@ -4209,7 +4209,7 @@ Note that all the related problems make syscall stealing unfeasiable for product

  • Standard in kernel modules
  • -/ + / #include <linux/kernel.h> / We're doing kernel work / #include <linux/module.h> / Specifically, a module, / #include <linux/moduleparam.h> / which will have params / @@ -4224,7 +4224,7 @@ Note that all the related problems make syscall stealing unfeasiable for product

  • this to know who the current user is.
  • -*/ + */ #include <linux/sched.h> #include <asm/uaccess.h>

    @@ -4244,7 +4244,7 @@ Note that all the related problems make syscall stealing unfeasiable for product
  • and recompile it.
  • -*/ + */ extern void *sys_call_table[];

    @@ -4256,7 +4256,7 @@ extern void *sys_call_table[];
  • command line
  • -*/ + */ static int uid; module_param(uid, int, 0644);

    @@ -4279,7 +4279,7 @@ module_param(uid, int, 0644);
  • It's a static variable, so it is not exported.
  • -*/ + */ asmlinkage int (*original_call) (const char *, int, int);

    @@ -4302,11 +4302,11 @@ asmlinkage int (*original_call) (const char *, int, int);
  • processes).
  • -*/ + */ asmlinkage int our_sys_open(const char *filename, int flags, int mode) { - int i = 0; - char ch; + int i = 0; + char ch;

    @@ -4343,8 +4343,8 @@ if (uid == current->uid) {

  • the ability to open files
  • - */ -return original_call(filename, flags, mode); + */ + return original_call(filename, flags, mode); }

    @@ -4355,10 +4355,10 @@ return original_call(filename, flags, mode);
  • Initialize the module - replace the system call
  • -*/ + */ int init_module() { - /* + /*

    • Warning - too late for it now, but maybe for
    • @@ -4405,7 +4405,7 @@ printk(KERN_INFO "Spying on UID:%d\n", uid);

      -return 0; + return 0; }

      @@ -4416,10 +4416,10 @@ return 0;
    • Cleanup - unregister the appropriate file from /proc

    -*/ + */ void cleanup_module() { - /* + /*

    • Return the system call back to normal
    • @@ -4435,7 +4435,7 @@ if (sys_call_table[__NR_open] != our_sys_open) {

      -sys_call_table[__NR_open] = original_call; + sys_call_table[__NR_open] = original_call; } #+END_SRC

      @@ -4443,11 +4443,11 @@ sys_call_table[__NR_open] = original_call;
    -
    -

    Blocking Processes

    -
    +
    +

    Blocking Processes

    +

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

    @@ -4497,9 +4497,9 @@ hostname:~/lkmpg-examples/09-BlockingProcesses#

    -
    -

    Example: sleep.c

    -
    +
    +

    Example: sleep.c

    +

    #+BEGIN_SRC: c /* @@ -4539,7 +4539,7 @@ hostname:~/lkmpg-examples/09-BlockingProcesses#

  • input
  • -*/ + */ #define MESSAGE_LENGTH 80 static char Message[MESSAGE_LENGTH];

    @@ -4558,16 +4558,16 @@ static struct proc_dir_entry *Our_Proc_File;
  • function
  • -/ + / static ssize_t module_output(struct file *file, / see include/linux/fs.h / - char *buf, / The buffer to put data to - (in the user segment) / - size_t len, / The length of the buffer */ - loff_t * offset) + char *buf, / The buffer to put data to + (in the user segment) / + size_t len, / The length of the buffer */ + loff_t * offset) { - static int finished = 0; - int i; - char message[MESSAGE_LENGTH + 30]; + static int finished = 0; + int i; + char message[MESSAGE_LENGTH + 30];

    @@ -4600,8 +4600,8 @@ for (i = 0; i < len && message[i]; i++)

    -finished = 1; -return i; * Return the number of bytes "read" * + finished = 1; + return i; * Return the number of bytes "read" * }

    @@ -4613,13 +4613,13 @@ return i; * Return the number of bytes "read" *
  • file.
  • -/ + / static ssize_t module_input(struct file *file, / The file itself / - const char *buf, / The buffer with input / - size_t length, / The buffer's length */ - loff_t * offset) + const char *buf, / The buffer with input / + size_t length, / The buffer's length */ + loff_t * offset) { * offset to file - ignore * - int i; + int i;

    @@ -4650,8 +4650,8 @@ Message[i] = '\0';

  • We need to return the number of input characters used
  • - */ -return i; + */ + return i; }

    @@ -4662,7 +4662,7 @@ return i;
  • 1 if the file is currently open by somebody
  • -*/ + */ int Already_Open = 0;

    @@ -4673,7 +4673,7 @@ int Already_Open = 0;
  • Queue of processes who want our file
  • -*/ + */ DECLARE_WAIT_QUEUE_HEAD(WaitQ); /*

    @@ -4681,10 +4681,10 @@ DECLARE_WAIT_QUEUE_HEAD(WaitQ);
  • Called when the /proc file is opened
  • -*/ + */ static int module_open(struct inode *inode, struct file *file) { - /* + /*

    • If the file's flags include O_NONBLOCK, it means the process doesn't
    • @@ -4820,9 +4820,9 @@ if (is_sig) {
    • Open the file

    -*/ -Already_Open = 1; -return 0; * Allow the access * + */ + Already_Open = 1; + return 0; * Allow the access * }

    @@ -4833,10 +4833,10 @@ return 0; * Allow the access *
  • Called when the /proc file is closed
  • -*/ + */ int module_close(struct inode *inode, struct file *file) { - /* + /*

    • Set Already_Open to zero, so one of the processes in the WaitQ will
    • @@ -4866,7 +4866,7 @@ module_put(THIS_MODULE);

      -return 0; * success * + return 0; * success * }

      @@ -4888,10 +4888,10 @@ return 0; * success *
    • returned by ls -l are for reference only, and can be overridden here.

    -*/ + */ static int module_permission(struct inode *inode, int op, struct nameidata *nd) { - /* + /*

    • We allow everybody to read from our module, but only root (uid 0)
    • @@ -4910,8 +4910,8 @@ if (op = 4 || (op = 2 && current->euid == 0))
    • If it's anything else, access is denied

    - */ -return -EACCES; + */ + return -EACCES; }

    @@ -4935,12 +4935,12 @@ return -EACCES;
  • means we don't want to deal with something.
  • -*/ + */ static struct file_operations File_Ops_4_Our_Proc_File = { - .read = module_output, * "read" from the file * - .write = module_input, * "write" to the file * - .open = module_open, * called when the /proc file is opened * - .release = module_close, * called when it's closed * + .read = module_output, * "read" from the file * + .write = module_input, * "write" to the file * + .open = module_open, * called when the /proc file is opened * + .release = module_close, * called when it's closed * };

    @@ -5013,7 +5013,7 @@ printk(KERN_INFO "/proc/test created\n");

    -return 0; + return 0; }

    @@ -5027,23 +5027,23 @@ return 0;
  • of a kernel module in such a case in chapter 10.
  • -*/ + */ void cleanup_module() { - remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root); + remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);

    -printk(KERN_INFO "/proc/test removed\n"); + printk(KERN_INFO "/proc/test removed\n"); } #+END_SRC

    -
    -

    Example: cat_noblock.c

    -
    +
    +

    Example: cat_noblock.c

    +

    #+BEGIN_SRC: c /* cat_noblock.c - open a file and display its contents, but exit rather than @@ -5137,8 +5137,8 @@ if (bytes > 0) {

    - * While there are no errors and the file isn't over * -} while (bytes > 0); + * While there are no errors and the file isn't over * + } while (bytes > 0); } #+END_SRC

    @@ -5146,12 +5146,12 @@ if (bytes > 0) {
    -
    -

    Replacing Printks

    -
    -
    -

    Replacing printk

    -
    +
    +

    Replacing Printks

    +
    +
    +

    Replacing printk

    +

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

    @@ -5161,9 +5161,9 @@ The way this is done is by using current, a pointer to the currently running tas

    -
    -

    Example: print_string.c

    -
    +
    +

    Example: print_string.c

    +

    #+BEGIN_SRC: c /* @@ -5174,7 +5174,7 @@ The way this is done is by using current, a pointer to the currently running tas

  • associated with the current task.
  • -*/ + */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -5202,27 +5202,27 @@ static void print_string(char *str)

  • tty struct went into signal struct in 2.6.6
  • - */ + */ #if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,5) ) -/* + /*

    • The tty for the current task

    - */ -my_tty = current->tty; + */ + my_tty = current->tty; #else -/* + /*

    • The tty for the current task, for 2.6.6+ kernels

    - */ -my_tty = current->signal->tty; + */ + my_tty = current->signal->tty; #endif -ttyops = my_tty->driver->ops; + ttyops = my_tty->driver->ops;

    @@ -5265,14 +5265,14 @@ if (my_tty != NULL) {

  • linux/Documentation/SubmittingPatches
  • - / -(ttyops->write) (my_tty, / The tty itself */ + / + (ttyops->write) (my_tty, / The tty itself */ #if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9) ) - 0, * Don't take the string - from user space * + 0, * Don't take the string + from user space * #endif - str, * String * - strlen(str)); * Length * + str, * String * + strlen(str)); * Length *

    @@ -5331,9 +5331,9 @@ module_exit(print_string_exit);

    -
    -

    Flashing keyboard LEDs

    -
    +
    +

    Flashing keyboard LEDs

    +

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

    @@ -5343,9 +5343,9 @@ The following source code illustrates a minimal kernel module which, when loaded

    -
    -

    Example: kbleds.c

    -
    +
    +

    Example: kbleds.c

    +

    #+BEGIN_SRC: c /* @@ -5427,8 +5427,8 @@ else

    -my_timer.expires = jiffies + BLINK_DELAY; -add_timer(&my_timer); + my_timer.expires = jiffies + BLINK_DELAY; + add_timer(&my_timer); }

    @@ -5472,7 +5472,7 @@ add_timer(&my_timer);

    -return 0; + return 0; }

    @@ -5510,9 +5510,9 @@ it does not show up in production code.
    -
    -

    Scheduling Tasks

    -
    +
    +

    Scheduling Tasks

    +

    Very often, we have "housekeeping" tasks which have to be done at a certain time, or every so often. If the task is to be done by a process, we do it by putting it in the crontab file. If the task is to be done by a kernel module, we have two possibilities. The first is to put a process in the crontab file which will wake up the module by a system call when necessary, for example by opening a file. This is terribly inefficient, however – we run a new process off of crontab, read a new executable to memory, and all this just to wake up a kernel module which is in memory anyway.

    @@ -5526,9 +5526,9 @@ There's one more point we need to remember here. When a module is removed by rmm

    -
    -

    Example: sched.c

    -
    +
    +

    Example: sched.c

    +

    #+BEGIN_SRC: c /* @@ -5560,13 +5560,13 @@ There's one more point we need to remember here. When a module is removed by rmm

  • Standard in kernel modules
  • -/ + / #include <linux/kernel.h> / We're doing kernel work / #include <linux/module.h> / Specifically, a module / #include <linux/proc_fs.h> / Necessary because we use the proc fs / #include <linux/workqueue.h> / We scheduale tasks here / #include <linux/sched.h> / We need to put ourselves to sleep - and wake up later / + and wake up later / #include <linux/init.h> / For __init and __exit / #include <linux/interrupt.h> / For irqreturn_t */

    @@ -5584,7 +5584,7 @@ struct proc_dir_entry *Our_Proc_File;
  • The number of times the timer interrupt has been called so far
  • -*/ + */ static int TimerIntrpt = 0;

    @@ -5603,7 +5603,7 @@ static int die = 0; * set this to 1 for shutdown *
  • The work queue structure for this task, from workqueue.h
  • -*/ + */ static struct workqueue_struct *my_workqueue;

    @@ -5621,10 +5621,10 @@ static DECLARE_DELAYED_WORK(Task, intrpt_routine);
  • getting a different parameter.
  • -*/ + */ static void intrpt_routine(struct work_struct *work) { - /* + /*

    • Increment the counter
    • @@ -5641,9 +5641,9 @@ TimerIntrpt++;
    • If cleanup wants us to die

    - */ -if (die == 0) - queue_delayed_work(my_workqueue, &Task, 100); + */ + if (die == 0) + queue_delayed_work(my_workqueue, &Task, 100); }

    @@ -5654,13 +5654,13 @@ if (die == 0)
  • Put data into the proc fs file.
  • -*/ + */ int procfile_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) + char **buffer_location, + off_t offset, int buffer_length, int *eof, void *data) { - int len; * The number of bytes actually used * + int len; * The number of bytes actually used *

    @@ -5717,8 +5717,8 @@ len = sprintf(my_buffer, "Timer called %d times so far\n", TimerIntrpt);

  • Return the length
  • - */ -return len; + */ + return len; }

    @@ -5729,10 +5729,10 @@ return len;
  • Initialize the module - register the proc file
  • -*/ + */ int __init init_module() { - /* + /*

    • Create our /proc file
    • @@ -5777,7 +5777,7 @@ printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);

      -return 0; + return 0; }

      @@ -5788,10 +5788,10 @@ return 0;
    • Cleanup

    -*/ + */ void __exit cleanup_module() { - /* + /*

    • Unregister our /proc file
    • @@ -5823,7 +5823,7 @@ destroy_workqueue(my_workqueue);
    • routine it's time to die.

    -*/ + */ }

    @@ -5835,7 +5835,7 @@ destroy_workqueue(my_workqueue);
  • are just available to GPL licensed Modules
  • -*/ + */ MODULE_LICENSE("GPL"); #+END_SRC

    @@ -5843,12 +5843,12 @@ MODULE_LICENSE("GPL");
    -
    -

    Interrupt Handlers

    -
    -
    -

    Interrupt Handlers

    -
    +
    +

    Interrupt Handlers

    +
    +
    +

    Interrupt Handlers

    +

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

    @@ -5875,9 +5875,9 @@ Then, from within the interrupt handler, we communicate with the hardware and th
    -
    -

    Keyboards on the Intel Architecture

    -
    +
    +

    Keyboards on the Intel Architecture

    +

    The rest of this chapter is completely Intel specific. If you're not running on an Intel platform, it will not work. Don't even try to compile the code here.

    @@ -5893,9 +5893,9 @@ used (the first seven bits of the scan code) and whether it has been pressed (if

    -
    -

    Example: intrpt.c

    -
    +
    +

    Example: intrpt.c

    +

    #+BEGIN_SRC: c /* @@ -5927,7 +5927,7 @@ used (the first seven bits of the scan code) and whether it has been pressed (if

  • Standard in kernel modules
  • -/ + / #include <linux/kernel.h> / We're doing kernel work / #include <linux/module.h> / Specifically, a module */ #include <linux/sched.h> @@ -5952,12 +5952,12 @@ static struct workqueue_struct *my_workqueue;

  • to do everything normally allowed by kernel modules.
  • -*/ + */ static void got_char(void *scancode) { - printk(KERN_INFO "Scan Code %x %s.\n", - (int)*((char *)scancode) & 0x7F, - *((char *)scancode) & 0x80 ? "Released" : "Pressed"); + printk(KERN_INFO "Scan Code %x %s.\n", + (int)*((char *)scancode) & 0x7F, + *((char *)scancode) & 0x80 ? "Released" : "Pressed"); }

    @@ -5970,10 +5970,10 @@ static void got_char(void *scancode)
  • part into the work queue. This will be run when the kernel considers it safe.
  • -*/ + */ irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) { - /* + /*

    • This variables are static because they need to be
    • @@ -6013,7 +6013,7 @@ queue_work(my_workqueue, &task);

      -return IRQ_HANDLED; + return IRQ_HANDLED; }

      @@ -6024,10 +6024,10 @@ return IRQ_HANDLED;
    • Initialize the module - register the IRQ handler

    -*/ + */ int init_module() { - my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME); + my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);

    @@ -6054,11 +6054,11 @@ free_irq(1, NULL);

  • SA_INTERRUPT can be used to make the handler into a fast interrupt.
  • - / -return request_irq(1, / The number of the keyboard IRQ on PCs / - irq_handler, / our handler */ - SA_SHIRQ, "test_keyboard_irq_handler", - (void *)(irq_handler)); + / + return request_irq(1, / The number of the keyboard IRQ on PCs / + irq_handler, / our handler */ + SA_SHIRQ, "test_keyboard_irq_handler", + (void *)(irq_handler)); }

    @@ -6069,10 +6069,10 @@ return request_irq(1, /
    The number of the keyboard IRQ on PCs /
  • Cleanup
  • -*/ + */ void cleanup_module() { - /* + /*

    • This is only here for completeness. It's totally irrelevant, since
    • @@ -6080,8 +6080,8 @@ void cleanup_module()
    • computer is completely useless and has to be rebooted.

    - */ -free_irq(1, NULL); + */ + free_irq(1, NULL); }

    @@ -6092,7 +6092,7 @@ free_irq(1, NULL);
  • some work_queue related functions are just available to GPL licensed Modules
  • -*/ + */ MODULE_LICENSE("GPL"); #+END_SRC

    @@ -6101,9 +6101,9 @@ MODULE_LICENSE("GPL");
    -
    -

    Symmetric Multi Processing

    -
    +
    +

    Symmetric Multi Processing

    +

    One of the easiest and cheapest ways to improve hardware performance is to put more than one CPU on the board. This can be done either making the different CPU's take on different jobs (asymmetrical multi-processing) or by making them all run in parallel, doing the same job (symmetrical multi-processing, a.k.a. SMP). Doing asymmetrical multi-processing effectively requires specialized knowledge about the tasks the computer should do, which is unavailable in a general purpose operating system such as Linux. On the other hand, symmetrical multi-processing is relatively easy to implement.

    @@ -6126,35 +6126,35 @@ In version 2.2.x, several CPU's can be in the kernel at the same time. This is s
    -
    -

    Common Pitfalls

    -
    +
    +

    Common Pitfalls

    +

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

    -
    -

    Using standard libraries

    -
    +
    +

    Using standard libraries

    +

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

    -
    -

    Disabling interrupts

    -
    +
    +

    Disabling interrupts

    +

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

    -
    -

    Sticking your head inside a large carnivore

    -
    +
    +

    Sticking your head inside a large carnivore

    +

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

    @@ -6162,18 +6162,18 @@ I probably don't have to warn you about this, but I figured I will anyway, just
    -
    -

    Appendix A. Changes: 2.4 To 2.6

    -
    +
    +

    Appendix A. Changes: 2.4 To 2.6

    +

    I don't know the entire kernel well enough to document all of the changes. Some hints for porting can be found by comparing this version of the LKMPG with it's counterpart for kernel 2.4. Apart from that, anybody who needs to port drivers from 2.4 to 2.6 kernels might want to visit http://lwn.net/ Articles/driver-porting. If you still can't find an example that exactly meets your needs there, find a driver that's similar to your driver and present in both kernel versions. File comparison tools like xxdiff or meld can be a great help then. Also check if your driver is covered by docs in linux/Documentation/ . Before starting with porting and in case you're stuck it's a good idea to find an appropiate mailinglist and ask people there for pointers.

    -
    -

    Appendix B. Where To Go From Here?

    -
    +
    +

    Appendix B. Where To Go From Here?

    +

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

    @@ -6196,9 +6196,9 @@ If you'd like to contribute to this guide, please contact one the maintainers fo
    -
    -

    Notes

    -
    +
    +

    Notes

    +

    [1] In earlier versions of linux, this was known as kerneld. [2] If such a file exists. Note that the acual behavoir might be @@ -6267,9 +6267,9 @@ If you'd like to contribute to this guide, please contact one the maintainers fo

    -
    -

    Edits

    -
    +
    +

    Edits

    +

    linux/fs.h updated file_operations structure (see http://lwn.net/Articles/119652/) unregister_chrdev returns void @@ -6302,7 +6302,7 @@ Fixed sched.c

    diff --git a/3.8/LKMPG-3.8.org b/3.8/LKMPG-3.8.org index 2d55543..ee42452 100644 --- a/3.8/LKMPG-3.8.org +++ b/3.8/LKMPG-3.8.org @@ -799,34 +799,34 @@ For example, every character driver needs to define a function that reads from t #+BEGIN_SRC: c struct file_operations { - struct module *owner; - loff_t (*llseek) (struct file *, loff_t, int); - ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); - ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); - ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); - int (*iterate) (struct file *, struct dir_context *); - unsigned int (*poll) (struct file *, struct poll_table_struct *); - long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); - long (*compat_ioctl) (struct file *, unsigned int, unsigned long); - int (*mmap) (struct file *, struct vm_area_struct *); - int (*open) (struct inode *, struct file *); - int (*flush) (struct file *, fl_owner_t id); - int (*release) (struct inode *, struct file *); - int (*fsync) (struct file *, loff_t, loff_t, int datasync); - int (*aio_fsync) (struct kiocb *, int datasync); - int (*fasync) (int, struct file *, int); - int (*lock) (struct file *, int, struct file_lock *); - ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); - unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - int (*check_flags)(int); - int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); - int (*setlease)(struct file *, long, struct file_lock **); - long (*fallocate)(struct file *file, int mode, loff_t offset, - loff_t len); - int (*show_fdinfo)(struct seq_file *m, struct file *f); + struct module *owner; + loff_t (*llseek) (struct file *, loff_t, int); + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); + ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); + int (*iterate) (struct file *, struct dir_context *); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + long (*compat_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct inode *, struct file *); + int (*flush) (struct file *, fl_owner_t id); + int (*release) (struct inode *, struct file *); + int (*fsync) (struct file *, loff_t, loff_t, int datasync); + int (*aio_fsync) (struct kiocb *, int datasync); + int (*fasync) (int, struct file *, int); + int (*lock) (struct file *, int, struct file_lock *); + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); + int (*setlease)(struct file *, long, struct file_lock **); + long (*fallocate)(struct file *file, int mode, loff_t offset, + loff_t len); + int (*show_fdinfo)(struct seq_file *m, struct file *f); }; #+END_SRC @@ -2377,7 +2377,7 @@ void cleanup_module() * Blocking Processes -What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: "Not right now, I'm busy. Go away!". But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). +What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: "/Not right now, I'm busy. Go away!/". But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). This kernel module is an example of this. The file (called /proc/sleep) can only be opened by a single process at a time. If the file is already open, the kernel module calls wait_event_interruptible[12]. This function changes the status of the task (a task is the kernel data structure which holds information about a process and the system call it's in, if any) to TASK_INTERRUPTIBLE, which means that the task will not run until it is woken up somehow, and adds it to WaitQ, the queue of tasks waiting to access the file. Then, the function calls the scheduler to context switch to a different process, one which has some use for the CPU. @@ -3154,7 +3154,7 @@ int __init init_module() /* * Create our /proc file */ - Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); + Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); if (Our_Proc_File == NULL) { remove_proc_entry(PROC_ENTRY_FILENAME, NULL); diff --git a/4.7.4/LKMPG-4.7.4.html b/4.7.4/LKMPG-4.7.4.html index 520efee..5ba7aec 100644 --- a/4.7.4/LKMPG-4.7.4.html +++ b/4.7.4/LKMPG-4.7.4.html @@ -3,11 +3,11 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + The Linux Kernel Module Programming Guide - + @@ -264,93 +264,93 @@ for the JavaScript code in this tag.

    Table of Contents

    -
    -

    Introduction

    -
    +
    +

    Introduction

    +

    -The Linux Kernel Module Programming Guide is a free book; you may reproduce and/or modify it under the terms of the Open Software License, version 1.1. You can obtain a copy of this license at http://opensource.org/licenses/osl.php. +The Linux Kernel Module Programming Guide is a free book; you may reproduce and/or modify it under the terms of the Open Software License, version 1.1. You can obtain a copy of this license at http://opensource.org/licenses/osl.php.

    @@ -370,18 +370,18 @@ If you publish or distribute this book commercially, donations, royalties, and/o

    -
    -

    Authorship

    -
    +
    +

    Authorship

    +

    The Linux Kernel Module Programming Guide was originally written for the 2.2 kernels by Ori Pomerantz. Eventually, Ori no longer had time to maintain the document. After all, the Linux kernel is a fast moving target. Peter Jay Salzman took over maintenance and updated it for the 2.4 kernels. Eventually, Peter no longer had time to follow developments with the 2.6 kernel, so Michael Burian became a co-maintainer to update the document for the 2.6 kernels. Bob Mottram updated the examples for 3.8 and 4.7.4 kernels and modified or updated some chapters.

    -
    -

    Versioning and Notes

    -
    +
    +

    Versioning and Notes

    +

    The Linux kernel is a moving target. There has always been a question whether the LKMPG should remove deprecated information or keep it around for historical sake. Michael Burian and I decided to create a new branch of the LKMPG for each new stable kernel version. So version LKMPG 4.7.x will address Linux kernel 4.7.4 and LKMPG 2.6.x will address Linux kernel 2.6. No attempt will be made to archive historical information; a person wishing this information should read the appropriately versioned LKMPG.

    @@ -392,18 +392,18 @@ The source code and discussions should apply to most architectures, but I can't
    -
    -

    Acknowledgements

    -
    +
    +

    Acknowledgements

    +

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

    -
    -

    What Is A Kernel Module?

    -
    +
    +

    What Is A Kernel Module?

    +

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

    @@ -414,9 +414,9 @@ What exactly is a kernel module? Modules are pieces of code that can be loaded a
    -
    -

    Kernel module package

    -
    +
    +

    Kernel module package

    +

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

    @@ -441,9 +441,9 @@ On Parabola:
    -
    -

    What Modules are in my Kernel?

    -
    +
    +

    What Modules are in my Kernel?

    +

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

    @@ -473,29 +473,29 @@ This can be a long list, and you might prefer to search for something particular
    -
    -

    Do I need to download and compile the kernel?

    -
    +
    +

    Do I need to download and compile the kernel?

    +

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

    -
    -

    Before We Begin

    -
    +
    +

    Before We Begin

    +

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

    -
    • Modversioning
      +
      • Modversioning

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

      • -
      • Using X
        +
      • Using X

        It is highly recommended that you type in, compile and load all the examples this guide discusses. It's also highly recommended you do this from a console. You should not be working on this stuff in X.

        @@ -507,9 +507,9 @@ Modules can't print to the screen like printf() can, but they can log informatio
      -
      -

      Headers

      -
      +
      +

      Headers

      +

      Before you can build anything you'll need to install the header files for your kernel. On Parabola GNU/Linux:

      @@ -539,9 +539,9 @@ This will tell you what kernel header files are available. Then for example:
      -
      -

      Examples

      -
      +
      +

      Examples

      +

      All the examples from this document are available within the examples subdirectory. To test that they compile:

      @@ -557,12 +557,12 @@ If there are any compile errors then you might have a more recent kernel version

      -
      -

      Hello World

      -
      -
      -

      The Simplest Module

      -
      +
      +

      Hello World

      +
      +
      +

      The Simplest Module

      +

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

      @@ -705,7 +705,7 @@ Lastly, every kernel module needs to include linux/module.h. We needed to includ

      -
      • Introducing printk()
        +
        • Introducing printk()

          Despite what you might think, printk() was not meant to communicate information to the user, even though we used it for exactly this purpose in hello-1! It happens to be a logging mechanism for the kernel, and is used to log information or give warnings. Therefore, each printk() statement comes with a priority, which is the <1> and KERN_ALERT you see. There are 8 priorities and the kernel has macros for them, so you don't have to use cryptic numbers, and you can view them (and their meanings) in linux/kernel.h. If you don't specify a priority level, the default priority, DEFAULT_MESSAGE_LOGLEVEL, will be used.

          @@ -719,7 +719,7 @@ If the priority is less than int console_loglevel, the message is printed on you

        • -
        • About Compiling
          +
        • About Compiling

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

          @@ -736,9 +736,9 @@ Here's another exercise for the reader. See that comment above the return statem
        -
        -

        Hello and Goodbye

        -
        +
        +

        Hello and Goodbye

        +

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

        @@ -790,9 +790,9 @@ Now have a look at linux/drivers/char/Makefile for a real world example. As you
        -
        -

        The __init and __exit Macros

        -
        +
        +

        The __init and __exit Macros

        +

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

        @@ -837,9 +837,9 @@ module_exit(hello_3_exit);
        -
        -

        Licensing and Module Documentation

        -
        +
        +

        Licensing and Module Documentation

        +

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

        @@ -891,9 +891,9 @@ module_exit(cleanup_hello_4);
        -
        -

        Passing Command Line Arguments to a Module

        -
        +
        +

        Passing Command Line Arguments to a Module

        +

        Modules can take command line arguments, but not with the argc/argv you might be used to.

        @@ -922,7 +922,7 @@ module_param_array(myintarray, int, short myshortarray[4]; int count; -module_param_array(myshortarray, short, &count, 0); /* put count into "count" variable */ +module_parm_array(myshortarray, short, &count, 0); /* put count into "count" variable */
        @@ -1043,9 +1043,9 @@ hello-5.o: invalid argument syntax for mylong: 'h'
        -
        -

        Modules Spanning Multiple Files

        -
        +
        +

        Modules Spanning Multiple Files

        +

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

        @@ -1116,9 +1116,9 @@ This is the complete makefile for all the examples we've seen so far. The first
        -
        -

        Building modules for a precompiled kernel

        -
        +
        +

        Building modules for a precompiled kernel

        +

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

        @@ -1210,12 +1210,12 @@ If you do not desire to actually compile the kernel, you can interrupt the build
        -
        -

        Preliminaries

        -
        -
        -

        How modules begin and end

        -
        +
        +

        Preliminaries

        +
        +
        +

        How modules begin and end

        +

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

        @@ -1230,9 +1230,9 @@ Every module must have an entry function and an exit function. Since there's mor
        -
        -

        Functions available to modules

        -
        +
        +

        Functions available to modules

        +

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

        @@ -1266,9 +1266,9 @@ You can even write modules to replace the kernel's system calls, which we'll do
        -
        -

        User Space vs Kernel Space

        -
        +
        +

        User Space vs Kernel Space

        +

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

        @@ -1279,9 +1279,9 @@ Recall the discussion about library functions vs system calls. Typically, you us
        -
        -

        Name Space

        -
        +
        +

        Name Space

        +

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

        @@ -1296,9 +1296,9 @@ The file /proc/kallsyms holds all the symbols that the kernel knows about
        -
        -

        Code space

        -
        +
        +

        Code space

        +

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

        @@ -1317,15 +1317,15 @@ By the way, I would like to point out that the above discussion is true for any
        -
        -

        Device Drivers

        -
        +
        +

        Device Drivers

        +

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

        -
        • Major and Minor Numbers
          +
          • Major and Minor Numbers

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

            @@ -1388,12 +1388,12 @@ By now you can look at these two device files and know instantly that they are b
          -
          -

          Character Device drivers

          -
          -
          -

          The file_operations Structure

          -
          +
          +

          Character Device drivers

          +
          +
          +

          The file_operations Structure

          +

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

          @@ -1478,9 +1478,9 @@ An instance of struct file_operations containing pointers to functions that are
          -
          -

          The file structure

          -
          +
          +

          The file structure

          +

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

          @@ -1495,9 +1495,9 @@ Go ahead and look at the definition of file. Most of the entries you see, like s
          -
          -

          Registering A Device

          -
          +
          +

          Registering A Device

          +

          As discussed earlier, char devices are accessed through device files, usually located in /dev[7]. The major number tells you which driver handles which device file. The minor number is used only by the driver itself to differentiate which device it's operating on, just in case the driver handles more than one device.

          @@ -1525,9 +1525,9 @@ If you pass a major number of 0 to register_chrdev, the return value will be the
          -
          -

          Unregistering A Device

          -
          +
          +

          Unregistering A Device

          +

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

          @@ -1547,9 +1547,9 @@ It's important to keep the counter accurate; if you ever do lose track of the co
          -
          -

          chardev.c

          -
          +
          +

          chardev.c

          +

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

          @@ -1735,9 +1735,9 @@ The next code sample creates a char driver named chardev. You can cat its device
          -
          -

          Writing Modules for Multiple Kernel Versions

          -
          +
          +

          Writing Modules for Multiple Kernel Versions

          +

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

          @@ -1761,9 +1761,9 @@ You might already have noticed that recent kernels look different. In case you h
          -
          -

          The /proc File System

          -
          +
          +

          The /proc File System

          +

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

          @@ -1853,9 +1853,9 @@ HelloWorld!
          -
          -

          Read and Write a /proc File

          -
          +
          +

          Read and Write a /proc File

          +

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

          @@ -1972,9 +1972,9 @@ The only memory segment accessible to a process is its own, so when writing regu
          -
          -

          Manage /proc file with standard filesystem

          -
          +
          +

          Manage /proc file with standard filesystem

          +

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

          @@ -2084,9 +2084,9 @@ Still hungry for procfs examples? Well, first of all keep in mind, there are rum
          -
          -

          Manage /proc file with seq_file

          -
          +
          +

          Manage /proc file with seq_file

          +

          As we have seen, writing a /proc file may be quite "complex". So to help people writting /proc file, there is an API named seq_file that helps @@ -2276,9 +2276,9 @@ You can also read the code of fs/seq_file.c in the linux kernel.

          -
          -

          sysfs: Interacting with your module

          -
          +
          +

          sysfs: Interacting with your module

          +

          sysfs allows you to interact with the running kernel by reading or setting variables inside of modules. This can be useful for debugging purposes, or just as an interface for userland applications or scripts.

          @@ -2408,9 +2408,9 @@ Finally, remove the test module:
          -
          -

          Talking To Device Files

          -
          +
          +

          Talking To Device Files

          +

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

          @@ -2891,9 +2891,9 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
          -
          -

          System Calls

          -
          +
          +

          System Calls

          +

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

          @@ -3096,11 +3096,11 @@ asmlinkage int our
          -
          -

          Blocking Processes

          -
          +
          +

          Blocking Processes

          +

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

          @@ -3488,12 +3488,12 @@ DECLARE_WAIT_QUEUE_HEAD(WaitQ);

          -
          -

          Replacing Printks

          -
          -
          -

          Replacing printk

          -
          +
          +

          Replacing Printks

          +
          +
          +

          Replacing printk

          +

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

          @@ -3616,9 +3616,9 @@ module_exit(print_string_exit);
          -
          -

          Flashing keyboard LEDs

          -
          +
          +

          Flashing keyboard LEDs

          +

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

          @@ -3737,9 +3737,9 @@ While you have seen lots of stuff that can be used to aid debugging here, there
          -
          -

          Scheduling Tasks

          -
          +
          +

          Scheduling Tasks

          +

          Very often, we have "housekeeping" tasks which have to be done at a certain time, or every so often. If the task is to be done by a process, we do it by putting it in the crontab file. If the task is to be done by a kernel module, we have two possibilities. The first is to put a process in the crontab file which will wake up the module by a system call when necessary, for example by opening a file. This is terribly inefficient, however – we run a new process off of crontab, read a new executable to memory, and all this just to wake up a kernel module which is in memory anyway.

          @@ -3922,12 +3922,12 @@ MODULE_LICENSE("GPL");
          -
          -

          Interrupt Handlers

          -
          -
          -

          Interrupt Handlers

          -
          +
          +

          Interrupt Handlers

          +
          +
          +

          Interrupt Handlers

          +

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

          @@ -3954,9 +3954,9 @@ Then, from within the interrupt handler, we communicate with the hardware and th
          -
          -

          Keyboards on the Intel Architecture

          -
          +
          +

          Keyboards on the Intel Architecture

          +

          The rest of this chapter is completely Intel specific. If you're not running on an Intel platform, it will not work. Don't even try to compile the code here. Move right along, nothing to see.

          @@ -4090,35 +4090,35 @@ MODULE_LICENSE("GPL");
          -
          -

          Common Pitfalls

          -
          +
          +

          Common Pitfalls

          +

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

          -
          -

          Using standard libraries

          -
          +
          +

          Using standard libraries

          +

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

          -
          -

          Disabling interrupts

          -
          +
          +

          Disabling interrupts

          +

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

          -
          -

          Sticking your head inside a large carnivore

          -
          +
          +

          Sticking your head inside a large carnivore

          +

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

          @@ -4126,9 +4126,9 @@ I probably don't have to warn you about this, but I figured I will anyway, just
          -
          -

          Where To Go From Here?

          -
          +
          +

          Where To Go From Here?

          +

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

          @@ -4151,9 +4151,9 @@ If you'd like to contribute to this guide, please contact one the maintainers fo
          -
          -

          Notes

          -
          +
          +

          Notes

          +

          [1] In earlier versions of linux, this was known as kerneld. [2] If such a file exists. Note that the acual behavoir might be @@ -4244,7 +4244,7 @@ If you'd like to contribute to this guide, please contact one the maintainers fo

          diff --git a/4.7.4/LKMPG-4.7.4.org b/4.7.4/LKMPG-4.7.4.org index 7558e1e..0f9442d 100644 --- a/4.7.4/LKMPG-4.7.4.org +++ b/4.7.4/LKMPG-4.7.4.org @@ -2193,7 +2193,7 @@ void cleanup_module() #+END_SRC * Blocking Processes -What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: /"Not right now, I'm busy. Go away!"/. But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). +What do you do when somebody asks you for something you can't do right away? If you're a human being and you're bothered by a human being, the only thing you can say is: "/Not right now, I'm busy. Go away!/". But if you're a kernel module and you're bothered by a process, you have another possibility. You can put the process to sleep until you can service it. After all, processes are being put to sleep by the kernel and woken up all the time (that's the way multiple processes appear to run on the same time on a single CPU). This kernel module is an example of this. The file (called */proc/sleep*) can only be opened by a single process at a time. If the file is already open, the kernel module calls wait_event_interruptible[12]. This function changes the status of the task (a task is the kernel data structure which holds information about a process and the system call it's in, if any) to *TASK_INTERRUPTIBLE*, which means that the task will not run until it is woken up somehow, and adds it to WaitQ, the queue of tasks waiting to access the file. Then, the function calls the scheduler to context switch to a different process, one which has some use for the CPU. diff --git a/4.7.4/img/seq_file.png b/4.7.4/img/seq_file.png index f729d95..4d15a3a 100644 Binary files a/4.7.4/img/seq_file.png and b/4.7.4/img/seq_file.png differ