Part 1: Create a Helloworld kernel module
The following code is a complete helloworld module.
#include <linux/module .h
#include <linux/kernel .h
int init module ( void ) { printk (KERN INFO ”Hello world !\n”); return 0;
}
void cleanup module ( void ){ printk (KERN INFO ”Goodbye world !\n”);
}
moduleinit ( init module ); module exit ( cleanup module );
MODULE LICENSE(”GPL”);
The module defines two functions. init module is invoked when the module is loaded into the kernel and cleanup module is called when the module is removed from the kernel. module init and module exit are special kernel macros to indicate the role of these two functions. Use the following Makefile to compile the module (you need root permission).
obj−m += new module . o all :
sudo make −C / lib /modules/$( shell uname −r )/ build M=$(PWD) modules clean :
sudo make −C / lib /modules/$( shell uname −r )/ build M=$(PWD) clean
Do you see any errors? If so, how to fix the error? To insert the module into the Linux kernel:
# sudo insmod new module.ko
Use the following command to verify the module has been loaded:
# lsmod
To remove the module from the kernel:
# sudo rmmod new module
Use dmesg to see the module’s output.
Part 2: Create an entry in the /proc file system for user level read and write
Write a kernel module that creates an entry in the /proc file system. Use the following code skeleton to write the module:
#include <linux/module .h
#include <linux/kernel .h
#include <linux/ proc fs .h #include <linux/ string .h
#include <linux/vmalloc .h
#include <asm/uaccess .h
#define MAX LEN 4096 int read info ( char ∗page , char ∗∗ start , off t off , int count , int ∗eof , void ∗data );
ssize t write info ( struct f i l e ∗ filp , const char user ∗buff , unsigned long len , void ∗data );
static struct proc dir entry ∗proc entry ; static char ∗ info ; static int write index ; static int read index ;
int
init module ( void ) { int ret = 0;
// allocated memory space for the proc entry info = ( char ∗) vmalloc (MAX LEN);
memset( info , 0 , MAX LEN);
//implement this : create the proc entry
write index = 0; read index = 0;
// register the write and read callback functions proc entry−read proc = read info ;
proc entry−write proc = write info ; printk (KERN INFO ” test proc created .\n”);
return ret ;
}
void cleanup module ( void ){
//remove the proc entry and free
}
info space
ssize t write info ( struct f i l e ∗ filp , unsigned long len , void ∗ data ){
const char
user
∗buff ,
//copy the written data from user space and save it return len ;
}
in info
int read info ( char ∗buff , char ∗∗ start , off t offset , int count , int ∗eof , void ∗data ){
//output the content of info to user ’ s buffer pointed by buff return len ;
}
The callback functions write info and read info will be invoked whenever the proc file is written and read, respectively, e.g., using the cat and echo commands. write info uses the copy from user function to communicate with the user space. To test your results, load the kernel module and there should be a new entry created under /proc. Use cat and echo to verify and change the content of the new entry.
Note: you need to change the previous Makefile’s obj-m += new module.o line to compile the module.
Part 3: Exchange data between the user and kernel space via mmap
Write a kernel module that creates an entry in the /proc file system. The new entry can not be directly read from or written to using cat and echo. Instead, map the new entry to a user space memory area so that user level processes can read from and write to the kernel space via mmap. The skeleton of the kernel module is given below:
#include<linux/module .h
#include<linux/ l i s t .h
#include<linux/ init .h
#include<linux/kernel .h
#include<linux/types .h
#include<linux/kthread .h
#include<linux/ proc fs .h #include<linux/sched .h #include<linux/mm.h
#include<linux/ fs .h
#include<linux/slab .h
#include <asm/io .h
static
struct proc dir entry ∗tempdir , ∗tempinfo ;
static
unsigned char ∗ buffer ;
static
unsigned char array [12]={0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11};
static static
void allocate memory ( void ); void clear memory ( void );
int my map( struct f i l e ∗ filp , struct vm area struct ∗vma);
static const struct file operations myproc fops = {
.mmap = my map,
};
static int my map( struct f i l e ∗ flip , struct vm area struct ∗vma){ // map vma of user space to a continuous physical space return 0;
}
static int init myproc module ( void ){
// create a directory in /proc
// create a new entry under the new directory printk (” init myproc module successfully \n”);
allocate memory (); // i n i t i a l i z e the buffer for ( i =0; i <12; i++){ buffer [ i ] = array [ i ] ;
}
return 0;
}
static void allocate memory ( void ){
// allocation memory
// set the memory as reserved
}
static void clear memory ( void ){
// clear reserved memory
// free memory
}
static void exit myproc module ( void ){ clear memory (); remove proc entry (”myinfo” , tempdir ); remove proc entry (”mydir” , NULL);
printk (”remove myproc module successfully \n”);
}
moduleinit ( initmyprocmodule ); module exit ( exit myproc module );
MODULE LICENSE(”GPL”);
Write a user space program to test the proc file you just created. Use the following skeleton:
#include <unistd .h #include <stdio .h
#include <stdlib .h
#include <string .h
#include <fcntl .h
#include <linux/fb .h
#include <sys/mman.h
#include <sys/ ioctl .h
#define PAGE SIZE 4096
int main( int argc , char ∗argv [ ] ) { unsigned char ∗p map ;
// open proc f i l e
// map p map to the proc f i l e and grant read & write privilege
// design test case to read from and write to p map
// unmap p map from the proc f i l e return 0 ;
}