Ubuntu – How to compile Linux kernel module: printk missing

application-developmentcgcckernel

So I'm trying to compile a simple kernel module on Ubuntu 18.04, kernel 4-15.32 generic:

#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void){ 
    printk("<1> Hello,World\n");
    return 0;
}

void cleanup_module(void){
    printk("<1> Goodbye.\n");
}

Notice that I do have <linux/kernel.h> , since there are references on forums that this is a frequent omission when error that I have occurs, but in this case I don't have that problem. Compiling this with gcc -o hello.o hello.c results in the implicit declaration of function 'printk' error.

So the question is how exactly do I get this most basic kernel module to even compile ?

Best Answer

Problem solved with a couple learned lessons:

  • "You must use the kernel headers of the kernel you're compiling against.Using the default /usr/include/linux won't work" (source)

  • Compiling with gcc directly isn't recommended - Kernel has kbuild system: "The author of an external module should supply a makefile that hides most of the complexity, so one only has to type "make" to build the module."

  • $(PWM) for some reason doesn't work, but $(shell pwm) works. (found here). This also played a role because M=$(PWM) would give

    make[2]: *** No rule to make target 'arch/x86/entry/syscalls/syscall_32.tbl', needed by 'arch/x86/include/generated/asm/syscalls_32.h'.  Stop.
    

    error. Also, per kernel documentation one could also do

    
    make -C /lib/modules/`uname -r`/build M=$PWD 
    

    but haven't tried that.


Makefile I've used:

obj-m += hello.o

KDIR := /lib/modules/$(shell uname -r)/build

all:
    $(MAKE) -C $(KDIR) M=$(shell pwd) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

The resulting module works as expected and can be inserted and removed with nice messages "<1> Hello World" and "<1> Goodbye" printed to dmesg.

Related Question