How to write a Linux kernel module

Kernel modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system.

## obtaining information
# list loaded modules
$ lsmod
# show module info
$ modinfo MODULENAME
# list dependencies
$ modprobe --show-depends MODULENAME

## automatic module load
# configure udev/systemd-modules to what modules to load at boot, see 'man modules-load.d'
$ vi {/etc,/run,/usr/lib}/modules-load.d/PROGRAM.conf

## manual module load
# load by name
$ modprobe MODULENAME
# load by filename from '/lib/modules/$(uname -r)/'
$ insmod FILENAME [ARGS]
# unload module
$ modprobe -r MODULENAME
# same

## passing parameters to module
# either from '/etc/modprobe.d'
$ vi /etc/modprobe.d/FILENAME.conf
options MODULENAME parametername=parametervalue
# or from kernel command line

## blacklisting: prevent the kernel module from loading
# either from '/etc/modprobe.d'
$ vi /etc/modprobe.d/FILENAME.conf
blacklist MODULENAME
# or from kernel command line

from kernel modules@arch

You can write your own modules, see the linux kernel module programming guide.

# install build dependencies (kernel source)
$(deb) apt-get install build-essential linux-headers-$(uname -r)
$(el) yum install yum install gcc gcc-c++ make kernel-headers
$(arch) pacman -Syu base-devel linux-headers

# write a hello world module
$ vi hello.c
#include <linux/module.h> // all kernel modules
#include <linux/kernel.h> // KERN_EMERG, KERN_ALERT, KERN_CRIT, ... 
#include <linux/init.h>   // __init and __exit macros
MODULE_DESCRIPTION("A Simple Hello World module");
static int __init hello_init(void) {
    printk(KERN_NOTICE "Hello world!n");
    return 0; // non-0 means init_module failed
static void __exit hello_cleanup(void) {
    printk(KERN_NOTICE "Cleaning up module.n");

$ Makefile
obj-m += hello.o
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

# testing
$ make ; sudo insmod hello.ko
$ dmesg|grep -i hello
$ sudo rmmod hello.ko

from how to write your own linux kernel module

How to compile and install Linux kernel in Ubuntu/Debian and RHEL/CentOS

$ sudo apt-get build-dep linux-image-$(uname -r)
$ sudo apt-get groupinstall "Development Tools"
$ sudo apt-get install ncurses-devel libncurses5-dev python-dev

$ sudo yum-builddep kernel
$ sudo yum groupinstall "Development Tools"
$ sudo yum install ncurses-devel libncurses5-dev python-dev

## download sources
$ sudo wget -O - | tar -C /usr/src -xJ

## configure kernel
$ cd /usr/src/linux-3.XX.X
$ sudo cp /boot/config-`uname -r` ./.config
# either generate new config 
$ sudo make menuconfig
# or just use current config
$ sudo sh -c 'yes "" | make oldconfig'

## compile, install and reboot
$ sudo make
$ sudo make modules_install install
$ sudo reboot

from How to upgrade the kernel on RHEL/CentOS, build kernel@centos and custom kernel@centos

## using EPEL repo
$ rpm --import
$ rpm -Uvh | elrepo-release-6-6.el6.elrepo.noarch.rpm | elrepo-release-5-5.el5.elrepo.noarch.rpm
$ sudo yum --enablerepo=elrepo-kernel install kernel-ml
$ sudo reboot

## using Ubuntu Mainline repo
$ export KURL=
$ wget -qO- $KURL | sed -n 's,.*\(linux-.*\(\(all\)\|\('`dpkg --print-architecture`'\)\).deb\).*,'$KURL'\1,p' | wget -i -
$ sudo dpkg -i linux-{headers,image}-*-generic_*.deb linux-headers*_all.deb
$ sudo reboot

# uninstalling upstream kernels
$ dpkg -l | grep "linux\-[a-z]*\-"
$ sudo apt-get purge linux-{image,headers}-3.XX.X.0-*
$ sudo update-grub

from kernel-ml@epel and mainline@ubuntu

$ sudo apt-get install kernel-package libncurses5-dev fakeroot wget bzip2 build-essential udev

## download sources
$ sudo apt-get install linux-source-$(uname -r)
$ cd /usr/src
$ sudo tar xvfvj linux-source-xxxxxx.tar.bz2
$ sudo ln -s linux-source-xxxxxxx ./linux

## configure kernel
$ cd /usr/src/linux
$ sudo make clean && make mrproper
$ sudo cp /boot/config-`uname -r` ./.config
# either generate new config 
$ sudo make menuconfig
# or just use current config
$ sudo sh -c 'yes "" | make oldconfig'

## compile, install and reboot
$ sudo make-kpkg clean
$ sudo fakeroot make deb-pkg
$ sudo dpkg -i /usr/src/linux-image-xxxxxxx.deb

from Howto compile and install Linux kernel in debian from source

How to cleanup rhel/centos/ubuntu/debian old kernels

# remove all unused linux kernel headers, kimages and modules
$ sudo yum install yum-utils && sudo package-cleanup --oldkernels --count=2

see yum@commandlinefu

# query linux kernels, in ubuntu/debian
$ dpkg -l 'linux-*'

# remove all unused linux kernel headers, images and modules
$ dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/(.*)-([^0-9]+)/1/")"'/d;s/^[^ ]* [^ ]* ([^ ]*).*/1/;/[0-9]/!d' | xargs sudo apt-get -y purge

# remove vs purge; purge is identical to remove except that packages are removed and purged, any configuration files are deleted too
$ sudo apt-get|aptitude remove vs sudo apt-get|aptitude purge

# removes all previously downloaded .deb files from the package cache directory '/var/cache/apt/archives,{,/partial}'
$ sudo apt-get|aptitude clean

# same as clean but only removes package files that can no longer be downloaded, and are largely useless
$ sudo apt-get|aptitude autoclean

# remove packages that were automatically installed to satisfy dependencies for other packages and are now no longer needed; automatically done in aptitude
$ sudo apt-get remove --autoremove | sudo apt-get autoremove

# after installing anything with apt-get install, localepurge will remove all translation files and translated man pages in languages you cannot read
$ sudo apt-get install localepurge

# remove orphaned packages
$ sudo apt-get install deborphan
$ sudo deborphan | xargs sudo apt-get -y remove --purge

from cleaning up a Ubuntu GNU/Linux system
see also apt@commandlinefu and dpkg@commandlinefu