Linux kernel development
Building a Linux kernel module on Red Hat-derived distributions requires the kernel-devel
package. Place the following in hello.c
:
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
/* NOTE: See kern_levels.h for level constants. */
printk(KERN_INFO "Hello, world!\n");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye, world!\n");
}
MODULE_LICENSE("GPL");
Place the following in Makefile
:
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Build the module using make
. Load the module using insmod hello.ko
, and remove it using rmmod hello
; upon completing either, you should see a message recorded by the computer’s logging system.
Receiving parameters at module load time
The module_param
and MODULE_PARM_DESC
macros aid in declaring and documenting kernel-module parameters, respectively. The module_param
macro takes as arguments a parameter name, parameter type, and a series of permission bits which, if non-zero, apply to a sysfs entry that the module might later create. Each use of module_param
should correspond with a global variable which shares the name of the parameter.
static char *option = "default value";
module_param(option, charp, 0000);
MODULE_PARM_DESC(option, "An example character string option");
The sample option above could be set using the command insmod hello.ko option=foo
.
Reproducing the kernel source used to build the kernel for a Red Hat-derived distribution
These steps require the dnf-utils
and rpm-build
packages, along with the compiler and other tools needed to build the Linux kernel.
yumdownloader --source kernel
rpm -Uvh kernel...
rpmbuild -bp ~/rpmbuild/SPECS/kernel.spec
This will result in a copy of the kernel source tree at ~/rpmbuild/BUILD/kernel...
. One way to build the kernel is to modify this source tree, produce a patch, place the patch in ~/rpmbuild/SOURCES
, modify ~/rpmbuild/SPECS/kernel.spec
to make use of the patch, and rebuild the kernel using rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec
:
- Make a vanilla copy of the kernel source:
cp -a ~/rpmbuild/BUILD/kernel.../linux.../ ~/rpmbuild/BUILD/kernel.../linux...-vanilla/
. - Add
pr_notice("Hello, world!\n");
to~/rpmbuild/BUILD/kernel.../linux.../init/main.c
immediately after the kernel prints"Kernel command line: ..."
. - Set your current directory to
~/rpmbuild/BUILD/kernel.../
and create a patch by runningdiff -u --recursive linux...-vanilla/ linux.../ >~/rpmbuild/SOURCES/kernel-hello.patch
. - Add the patch to the kernel’s RPM specification by adding
Patch2: kernel-hello.patch
to~/rpmbuild/SPECS/kernel.spec
after the definition ofPatch1
. - Set the specification to apply your patch by adding
ApplyOptionalPatch kernel-hello.patch
after the application ofpatch-%{patchversion}-redhat.patch
. - Run
rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec
to build the result. This will take a long time, and it will use a lot of disk space.
Finally run rpm -ivh ~/rpmbuild/RPMS/x86_64/kernel-*
to install your new kernel, and reboot the computer. After booting, you should find that dmesg
includes Hello, world!
in its output.