Friday, June 22, 2007

3. Simulate a Device Driver

Now I have to simulate a device driver.

The easiest simulation is to insert a test module into kernel (which essentially does nothing) then removing it from the kernel.

We ca use this hello.c source file to make a module

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

int init_module (void) /* Loads a module in the kernel */
{
printk(KERN_INFO "Hello kernel\n");
return 0;
}

void cleanup_module(void) /* Removes module from kernel */
{
printk(KERN_INFO "GoodBye Kernel\n");
}


(Somehow I knew that I need linux-headers linstalled in my linux to compile these sort of codes. )
I tried to compile it for the first time

gizmo@ububtu:~/mod$ gcc -c hello.c
hello.c:1:26: error: linux/module.h: No such file or directory
hello.c: In function ‘init_module’:
hello.c:6: error: ‘KERN_INFO’ undeclared (first use in this function)
hello.c:6: error: (Each undeclared identifier is reported only once
hello.c:6: error: for each function it appears in.)
hello.c:6: error: expected ‘)’ before string constant
hello.c: In function ‘cleanup_module’:
hello.c:12: error: ‘KERN_INFO’ undeclared (first use in this function)
hello.c:12: error: expected ‘)’ before string constant

See the red line. There is an error. I tried to find if there is any module.h is in my include directory.
I always knew that when a header file is included, compiler searches /usr/src/linux-headers-2.x.xx-xx/ directory and attached the header (*.h) file/files.

So I searched the /usr/src/linux-headers-2.6.20-16-generic/include/linux folder (2.6.20-16-generic is my kernel version) and I found module.h. Well I was wrong.

I went to my advisor and he let me know some secrets of GCC which I never knew and still can't find them by Google.

One of them is compiling on verbose mode, by adding -v parameter. Which gives line by line logging when compiling. And another is -save-temps parameter, which saves the intermediate file *.i and some other intermediate files. *.i file is a concatenated file of the header files and the source file (*.c/*.cc/*.cpp).

Let's see what happened to my module code in verbose mode.

gizmo@ububtu:~/mod$ gcc -c hello.c -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 (Ubuntu 4.1.2-0ubuntu4)
/usr/lib/gcc/i486-linux-gnu/4.1.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=generic -auxbase hello -version -fstack-protector -fstack-protector -o /tmp/ccQ7Kn8b.s
ignoring nonexistent directory "/usr/local/include/i486-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../i486-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i486-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc/i486-linux-gnu/4.1.2/include
/usr/include
End of search list.
GNU C version 4.1.2 (Ubuntu 4.1.2-0ubuntu4) (i486-linux-gnu)
compiled by GNU C version 4.1.2 (Ubuntu 4.1.2-0ubuntu4).
GGC heuristics: --param ggc-min-expand=63 --param ggc-min-heapsize=63380
Compiler executable checksum: c0d954aeefbb96d795ff3f6b3b72ef51
hello.c:1:26: error: linux/module.h: No such file or directory
hello.c: In function ‘init_module’:
hello.c:6: error: ‘KERN_INFO’ undeclared (first use in this function)
hello.c:6: error: (Each undeclared identifier is reported only once
hello.c:6: error: for each function it appears in.)
hello.c:6: error: expected ‘)’ before string constant
hello.c: In function ‘cleanup_module’:
hello.c:12: error: ‘KERN_INFO’ undeclared (first use in this function)
hello.c:12: error: expected ‘)’ before string constant


Check out the red lines. I was wrong! GCC 4.1.2 never looks on /usr/src/linux-headers-2.6.20-16-generic/ directory. Now I need to know a way, which can tell GCC to look up on appropriate folder.

In my university lab where PCs are powered by Fedora Core 5, this module code compiled without any error! I use ubuntu fiestly fawn (7.04) at my home. I thought ubuntu has this problem with gcc. So I chosen a shortcut, which led me to a disaster.

This part is kind of an offtopic!
I consider last week as my disaster week. As I saw ubuntu is not doing good, I considered installing Debian 4.0. I took it from a senior student, well I had to take it twice! Both time my DVD's had faults when burning. Then I tried to install fedora core 6. By the way, my DVD-ROM drive was faulty, when I was in the middle of installing FC6, installation corrupted, and I ended up with a broken GRUB (boot loader). Finally, no boot loader to boot any OS, no DVD drive to install anything else. I had to waste a whole week because of this, then bought a new DVD drive and Fedora Core 7 DVD.

FC7 started a new era for Fedora Cores, as it has a community repository now. Which is now letting FC to be a general purpose OS for all. Why? It has no kernel-header installed, no ant installed, most of the dev packages are vanished and it has a nice looking interface!

Guess what ...


when I tried to compile this code again
gizmo@desktop:~/mod$ gcc -c hello.c
the output is ...
hello.c:2:26: error: linux/module.h: No such file or directory


Meanwhile I posted an important thread on www.ubuntuforums.org

You can visit this thread here http://ubuntuforums.org/showthread.php?t=474991

I decided to get back on ubuntu fiesty. Installed it again, updated it up to date. Installed the things I needed and now I'm back to business!

Moral: For developing purpose, DO use whatever you want to use or you were using. DO NOT change distros, it won't help you at all.

Thanks to
alexOoO for showing me a nice example of Makefile and the_unforgiven for giving me a superb link of "The Kernel Module Programming Guide". I am follwing this guide now, as the book I was following previously was for older kernels.

Now I just made a Makefile with these codes.

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

Then I tried to compile with 'make' command, and the output is

gizmo@ububtu:~/mod$ make
make -C /lib/modules/2.6.20-16-generic/build M=/home/gizmo/mod modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.20-16-generic'
CC [M] /home/gizmo/mod/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/gizmo/mod/hello.mod.o
LD [M] /home/gizmo/mod/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.20-16-generic'

NICE! Let's just ignore the warning messages, I can fix that later. At least the module could be compiled by my distro. Lets see if the module information.

gizmo@ububtu:~/mod$ modinfo hello.ko
filename: hello.ko
srcversion: 4C36855B98BAF2C01D9C1E9
depends:
vermagic: 2.6.20-16-generic SMP mod_unload 586


Let's try to insert the module into kernel.
NOTE: Inserting/Removing needs root/superuser permission.

gizmo@ububtu:~/mod$ sudo insmod ./hello.ko

Compiler doesn't show any error, so the module is inserted.
The code was supposed to print "Hello Kernel" on the log when the module is inserted. Let's check out the log if the message is printed.

gizmo@ububtu:~/mod$ cat /var/log/messages
...
...
Jun 22 14:05:20 ububtu -- MARK --
Jun 22 14:08:54 ububtu kernel: [ 6237.218196] hello: module license 'unspecified' taints kernel.
Jun 22 14:25:21 ububtu -- MARK --
Jun 22 14:32:42 ububtu kernel: [ 7662.119510] Hello kernel

Now let's try to remove the module
gizmo@ububtu:~/mod$ sudo rmmod ./hello.ko

and the log file says ...

gizmo@ububtu:~/mod$ cat /var/log/messages
...
...
Jun 22 14:05:20 ububtu -- MARK --
Jun 22 14:08:54 ububtu kernel: [ 6237.218196] hello: module license 'unspecified' taints kernel.
Jun 22 14:25:21 ububtu -- MARK --
Jun 22 14:32:42 ububtu kernel: [ 7662.119510] Hello kernel
Jun 22 14:34:24 ububtu kernel: [ 7764.009453] GoodBye Kernel

Done!

It was the simplest module than can be inserted. Next time I'll try to understand the module structure in more depth and how to work on module licenses.

Now I have to do compiler assignment PA2, I have wasted too much time looking for distros. Wish me luck.

2 comments:

Amir T said...

hi,
im having the same problem you got with the linux/module.h ,
i got 2.6.35-22-generic kernel headers version and im using this MAKEFILE:
obj-m += hello2.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

what can be the problem?

elavarasan said...

Instead of creating Makefile you can also use this command in terminal.


make -C /lib/modules/2.6.20-16-generic/build M=/home/gizmo/mod modules