The purpose of this project is to practice writing Linux kernel modules to create a new device file and an entry in the proc file system. The objectives of this project is to learn:
- How to write a helloworld Linux kernel module.
- How to create a new device in Linux.
- How to add a new entry in the proc file system.
Project
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 !
); return 0;
}
void cleanup module ( void ){ printk (KERN INFO Goodbye world !
);
}
moduleinit ( init module ); moduleexit ( 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).
objm += 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 modules 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 );
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; |
static struct proc dir entry proc entry ; static char info ; static int write index ; static int read index ;
readindex = 0;
// register the write and read callback proc entry>read proc = read info ; | functions |
return ret ;}void cleanup module ( void ){//remove the proc entry and free info space} | |
ssize t write info ( struct f i l e filp , const char user unsigned long len , void data ){ | buff , |
//copy the written data from user space and save it return len ;} | in info |
procentry>write proc = write info ; printk (KERN INFO test proc created .
);
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 Makefiles 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>
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 | void allocate memory ( void ); |
#include<linux/slab .h> #include <asm/io .h>
static 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
);
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
);
}
moduleinit ( initmyprocmodule ); moduleexit ( 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 ;
}
Reviews
There are no reviews yet.