Friday, July 1, 2011

Beginning Kernel Programming


I have started to learn kernel programming shortly, well, this thing is not much interesting to me, mostly due to academic purpose.

I have been following The Linux Kernel Module Programming Guide which was suggested by our instructor. However, I've found that this one is already a bit old and I faced a lot of trouble even to see the simple yet extremely popular "hello world" on my kernel log. As I use ubuntu distribution (version 11.04), there are lot of differences inside and outside. So I have cooked the first code as followed (as in the guide, it is explained there.)

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

int init_module(void) {
    printk(KERN_ALERT "Hello world 1.\n");
    return 0;
}

void cleanup_module(void) {
    printk(KERN_ALERT "Goodbye cruel world 1.\n");
}

However, this goes quite well without any trouble. But I have to change the "Makefile" a bit to successfully compile this Hello World code (tabs will be expanded as spaces here).

obj-m += hello-1.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

I'm lucky that I figured out only pwd is not working, I had to add shell instruction with it.

After this, everything went on quite well:

$ sudo make

This generated the following output with no errors:

make -C /lib/modules/2.6.38-8-generic/build M=/home/zobayer/Lab/system/kernel modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.38-8-generic'
  Building modules, stage 2.
  MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-2.6.38-8-generic'

Now to install the module:

$ sudo insmod ./hello-1.ko

So I opened the file /proc/modules to check if I was successful and whoa, it was there...

The I removed it from modules:

$ sudo rmmod hello-1.ko

Now I had to make another change, when I try to open /var/log/messages as the guide suggest, I've found that there is no such file, instead, I had to open /var/log/kern.log, and at the far bottom, I've found what I had been looking for:

... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 
Jul  1 14:17:38 zobayer kernel: [   48.569441] 
Jul  1 14:17:38 zobayer kernel: [   48.569447] nouveau 0000:01:00.0: VGA-1: EDID block 0 invalid.
Jul  1 14:17:38 zobayer kernel: [   48.569452] [drm] nouveau 0000:01:00.0: DDC responded, but no EDID for VGA-1
Jul  1 14:17:38 zobayer kernel: [   48.596016] [drm] nouveau 0000:01:00.0: Load detected on output A
Jul  1 14:18:12 zobayer kernel: [   82.640352] Marking TSC unstable due to cpufreq changes
Jul  1 14:18:12 zobayer kernel: [   82.640450] Switching to clocksource acpi_pm
Jul  1 15:23:31 zobayer kernel: [ 4001.644627] hello_1: module license 'unspecified' taints kernel.
Jul  1 15:23:31 zobayer kernel: [ 4001.644636] Disabling lock debugging due to kernel taint
Jul  1 15:23:31 zobayer kernel: [ 4001.647429] Hello world 1.
Jul  1 15:24:58 zobayer kernel: [ 4088.648118] Goodbye cruel world 1.

I think I have to change many things in future, but so far, this may be a good start...

Edit: An addition by Surid vai:

Mellowhost Surid

/var/log/messages is the general log file and kern.log is the kernel log file. In redhat system, until explicitly defined, there is no kern.log, I believe that book is written based on redhat kernels, that is why they are using messages. B...ut for any system, the command "dmesg" should print those module outputs. dmesg is the kernel ring buffer log. You are using Ubuntu, this is why by default it is using kern.log

If you would like to change the kernel log file, you would need to use klogd. It is a daemon to catch and handle kernel messages. Now find how can you make the change :)

http://linux.die.net/man/8/klogd


2 comments:

  1. could not understand make file
    obj-m += hello-1.o
    all:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules // is this path of kernel /lib/modules/$(shell uname -r)/build
    clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
    its not working on my system says nothing to do for all please could u explain

    ReplyDelete
  2. Hey, it is too late, but lets post it anyway.
    You need to have proper spaces in your Makefile, like the third like "make -C /li ...." should be written after pressing TAB. same for 5th line!

    ReplyDelete