Linux Kernel Module
A simple kernel module.
For the first time I wrote a kernel module.
Basic features:
- can allocate memory
- can create /proc entry
- can read/write to /proc file
- loads and unloads cleanly
- floods with kernel messages
Compilation:
- make sure that you have kernel headers for currently running kernel, we look for a symlink in makefile (/lib/modules/2.6.15-26-amd64-k8/build) which we build using "/lib/modules/"+ uname -r + "/buid". So build should point into a linux headers directory.
# make
make -C /lib/modules/2.6.15-26-amd64-k8/build M=/home/flexray/source/64/kernel_module/moj_modul
make[1]: WejĹ.cie do katalogu `/usr/src/linux-headers-2.6.15-26-amd64-k8'
LD /home/flexray/source/64/kernel_module/moj_modul/built-in.o
CC [M] /home/flexray/source/64/kernel_module/moj_modul/flex.o
Building modules, stage 2.
MODPOST
CC /home/flexray/source/64/kernel_module/moj_modul/flex.mod.o
LD [M] /home/flexray/source/64/kernel_module/moj_modul/flex.ko
make[1]: Opuszczenie katalogu `/usr/src/linux-headers-2.6.15-26-amd64-k8'
Testing:
# insmod flex.ko
# cat /proc/flex
flex:
# echo "some text" > /proc/flex
# cat /proc/flex
flex: some text
# rmmod flex
After that you could look into your kernel log
# dmesg
[ 1447.972539] flex: Hello from the kernel!
[ 1447.972539] flex: I will now try to create a /proc entry, wish me luck!
[ 1447.972539] flex: Now i will eat 1024b of memory for buffers
[ 1447.972539] flex: Module loaded successfully.
[ 1510.232020] flex: Hello again, I'm going now... BYE!
[ 1510.232020] flex: Successfully freed 1024b of memory, no traces left.
[ 1510.232020] flex: Successfully removed /proc entry.
[ 1510.232020] flex: Module unloaded successfully.
Works for me :)
Next time there will be a lot more
flex.c:
/*
########### Maciej Stopa
#
# This is free software; you may redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2,
# or (at your option) any later version.
#
# This is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#define ModuleAuthor "flexray@wp.pl"
#define ModuleDescription "Flexray module"
#define ModuleLicense "GPL"
#define ModuleName "flex"
static char * buf;
static struct proc_dir_entry * proc_entry;
/* flex_read: funkcja pozwala na czytanie z /proc/flex
naglowek musi taki pozostac, ze wzgledu na strukture /proc
bufor przekazywany do usera to * page
*/
int flex_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len;
if (off>0)
{
*eof=1;
return 0;
}
len = sprintf(page, "flex: %s\n",buf);
return len;
}
/* flex_write: funkcja pozwala na pisanie do /proc/flex
naglowek musi taki pozostac, ze wzgledu na strukture /proc
bufor przekazywany przez usera to * buffer
*/
int flex_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
if (copy_from_user(buf, buffer, count))
{
return -EFAULT;
}
buf[count-1]=0;
return count;
}
static int __init flex_init(void)
{
printk(KERN_INFO "%s: Hello from the kernel!\n",ModuleName);
printk(KERN_INFO "%s: I will now try to create a /proc entry, wish me luck!\n",ModuleName);
proc_entry = create_proc_entry("flex", 0644, NULL);
if (proc_entry==NULL)
{
printk(KERN_ERR "%s: Error: Unable to allocate /proc file exiting!\n",ModuleName);
return -ENOMEM;
}
proc_entry->read_proc = flex_read;
proc_entry->write_proc = flex_write;
proc_entry->owner = THIS_MODULE;
printk(KERN_INFO "%s: Now i will eat 1024b of memory for buffers\n",ModuleName);
if (!(buf = (char *)vmalloc(1024)))
{
printk(KERN_ERR "%s: Error: Unable to allocate 1024b of memory, exiting!\n",ModuleName);
return -ENOMEM;
}
memset(buf,0,1024);
printk(KERN_INFO "%s: Module loaded successfully.\n",ModuleName);
return 0;
}
static void __exit flex_exit(void)
{
printk(KERN_INFO "%s: Hello again, I'm going now... BYE!\n",ModuleName);
vfree(buf);
printk(KERN_INFO "%s: Successfully freed 1024b of memory, no traces left.\n",ModuleName);
remove_proc_entry("flex", &proc_root);
printk(KERN_INFO "%s: Successfully removed /proc entry.\n",ModuleName);
printk(KERN_INFO "%s: Module unloaded successfully.\n",ModuleName);
}
module_init(flex_init);
module_exit(flex_exit);
MODULE_AUTHOR(ModuleAuthor);
MODULE_DESCRIPTION(ModuleDescription);
MODULE_LICENSE(ModuleLicense);
Makefile:
obj-m := flex.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
clean:
rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c