Tuesday, June 26, 2007

3 more features for a basic module

Just learned few things which are useful.

1. Licensing and Documentation
2. Passing Arguments to a module and
3. Writing a driver on more than one file.

I am still working on it. All are tested though, I am experimenting them on different situations.
I'll be posting sample codes and outputs soon.

Here's a sample module info of the modified hello.c

filename: hello.ko
description: A sample driver
author: Raihan Hasnain
license: GPL
srcversion: 76F9BD32BB1DECDFF563E8E
depends:
vermagic: 2.6.20-16-generic SMP mod_unload 586



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. Structure of Kernel Module

Kernel modules can be developed for two types of devices.

Block Devices

As the name says, Kernel accesses block devices by blocks (usually 1kb). It is generally used for hosting file systems.

Character Devices
Kernel accesses char devices like a file. Parallel port, Serial ports are char devices.

Kernel modules can be loaded or unloaded into kernel dynamically in runtime. So kernel module has a generic structure*.

struct module
{
unsigned long size_of_struct;
struct module *next;
const char *name;
unsigned long size;
long usecount;
unsigned long flags;
unsigned int nsyms;
unsigned int ndeps;
struct module_symbol *syms;
struct module_ref *deps;
struct module_ref *refs;
int (*init)(void);
void (*cleanup)(void);
const struct exception_table_entry *ex_table_start;
const struct exception_table_entry *ex_table_end;
#ifdef __alpha__
unsigned long gp;
#endif
};


Return Values

On success, zero is returned. On error, -1 is returned
and errno is set appropriately.


I still don't know how this structure works. I only know about two methods (marked blue). First one initializes a module to be inserted, second one does the job of removing.

I'll study abouth the other methods eventually.

*courtesy: module structure, http://www.freeos.com/articles/2677/

1. What is Device Driver?

In short, device driver is a software program which talks to the computer and controls the device. If you really want a bookish definition, you better check this site CLICK HERE. I'd rather post a simple definition which makes sense.

NOTE: From next time, whenever you see me mentioning 'drivers' or 'dd', consider it as device drivers.

Before getting into device drivers, I should mention that OS has a vital role here. One of the most important features of OS is resource management, which includes I/O operation with devices. Devices are connected with I/O ports. Interfacing does the physical connection, OS can send the requests to the device. Here comes the role of drivers. Driver is the OS of the device itself, it can talk to the computers OS and thus computers OS recognizes the device. Later drivers can control the device, which is essentially the I/O instructions by the computers OS.


Lets narrow down a bit more. OS is a huge entity to consider. By OS here we mean the kernel of an OS. Kernel is the core of the OS. Drivers has to either be inside the kernel to recognize devices or has to be somewhere near the kernel so that it can easily communicate with the kernel.

Check out the diagram*.



So here comes the kernel. I just mentioned that the driver can be inside the kernel, that is known as monolithic kernel, which actually has to come with the kernel package. There is another way of implementing drivers, that is by kernel modules.

My concern is now with kernel modules only.

Kernel modules are pieces of codes. Which can be loaded and unloaded upon demand. Letting us not worry about rebuilding the kernel again and again.

On my next post, I'll show the structure of the kernel module.


*Image courtesy: http://www.linuxjournal.com/article/2476

Thursday, June 21, 2007

Summary of Week 1-2

Before I could start anything, I grabbed this book (Linux Device Drivers, by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman) as my reference. There is not many books available on the market. So, this book seemed to be blessing. More to add it has a web version to browse and pdf version to download for totally free.
http://lwn.net/Kernel/LDD3/


On first week, I was assigned to do 3 jobs
  1. Learn how device driver works
  2. Learn the 'structure' of device driver module
  3. Simulate a device driver
I will be posting separate threads for my 3 jobs as they are lengthy when describing.

Pre-thesis

I study Computer Science and Engineering (CSE) in BRAC University (www.bracuniversity.ac.bd). Now I am a level-4 student. We have to do a thesis to complete our graduation, before deciding what to do on the thesis we have to go through a pre-thesis. Which is very helpful for the thesis.

My pre-thesis is on Device Drivers and my advisor is Dr. Mumit Khan.

My initial approach is just to know what is device drivers and how does it work. As Linux gives the opportunity to play with these things. I am using Linux as my platform.

Intro [You can always skip this part!]

"I am a huge fan of Operating Systems" - I know it sounds odd. Most of my friends reacts like "Cool! ... but what is it?" or "OS? You mean Windows?". Well I am not going into that story, but I have used and seen a lot of OS's since 1992.

My first experience of OS was with DOS in 1992. I did not use it rather seen my uncle using it. Then my dad got his computer at office in 1994. I got introduced with Windows 3.1 ... which was a new experience for me. In 1997 my best friend got a computer with Windows 95, which actually let me know there are different windows. At last I got a PC of my own in mid 98, with windows 95 loaded. That was just the beginning. Later I have used Windows 98, 98se, ME. In year 2000, I got introduced with another OS, which was totally different - BeOS5. Then I got QNX. I learned that there are other things rather than windows. Rad Hat 6.0 was a break through. I never knew there was a substitute of Windows, but RH was a bit complicated. In 2004, I bought a new computer with better specification, I installed Fedora Core 3, and that seemed to be a lot better. In 2005, Ubuntu 5.04 was a complete breakthrough for me. I used to start using linux beside windows XP. Then Ubuntu 6.06 was enough to convince me I do not need windows anymore. Meanwhile I tried Fedora Core 5,6,7, Mandriva 2007 and openSuSe 10.1. All are good, specially for general users. But in this year Ubuntu Fiesty Fawn 7.04 let me use quit windows completely. I play games, I compose musics, I watch DVDs, I use MSN messenger, I transfer songs into iPod, I use bluetooth to transfer stuffs from my cellphone. Everything is nice - without crashes, scan disks and blue screens of panic. Windows Vista seemed to be a lot better than the previous versions, but it is most resource hunger OS in the universe. Finally, I always tried to use Mac OSX. But I don't have a mac. Just a little information ... I use a MacOSX transformation pack on windows, which made my windows look like MacOSX, including the command prompt.

As a Computer Science and Engineering student. I always wanted to do something with Operating Systems. I have no intention to develop an OS from scratch, which is useless unless I make a open source MacOSX substitute for x86. I rather chosen an important sector of OS which made OS's this much usability. Yes, that is Device Drivers.

P.S.: I have earned an 'A' on my OS course! :D