Sunday, October 26, 2008

"Hello World" kernel module

An Environment notes:
My kernel's module test environment is fedora core 9 with kernel version of 2.6.25.9-76.
In order to compile my module I had to download the development package of this kernel version and install it on my build/debug machine : http://kojipkgs.fedoraproject.org/packages/kernel/2.6.25.9/76.fc9/i686/

Now, the module source code :

// Start of code

#include <linux/init.h>

#include <linux/module.h>

// The following macro's can be found at the kernel include file linux/module.h
// with some other as MODULE_INFO, MODULE_ALIAS, MODULE_VERSION ....

MODULE_LICENSE("DUAL BSD/GPL"); // license applies to its code
MODULE_AUTHOR("Ofer Koren"); // Code author
MODULE_DESCRIPTION("hello-world module"); // Module description

// My “started” print function

void hello_func(void)
{
printk (KERN_ALERT "Hello World strated :-]\n");
}

// Module's initialization function
// The __init mean that this function can be dropped from the memory
// after the module is loaded

static int __init start_hello(void)
{
hello_func();
return 0;
}

// Module's exit function
// The __exit mean that this code should be called upon module exit only
static void __exit stop_hello(void)
{
printk(KERN_ALERT "Hello-world was terminated\n");
}

// The next two macros are mandatory, this way we declare
// our init and exit functions
module_init(start_hello);
module_exit(stop_hello);

// End of code


Some notes regarding printk:

printk is actually the “printf” of the kernel space (which we cannot use since the kernel ir running without the C libs), For each printk calling we can declare the output priority using the following defines in the kernel.h header:

#define KERN_EMERG      "<0>"   /* system is unusable                   */

#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
In order to compile the above code, Here's the Makefile:

#Start of Makefile

# The sourc file to compile
obj-m += hello.o
# The kernel header files
KERNELDIR=/usr/src/kernels/2.6.25.9-76.fc9.i686
# Current directory
PWD= $(shell pwd)
# Make command
MAKE=make

all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean

# Since the make start by changing the current directory to the KERNELDIR
# path, The M option cause the makefile to move back to our directory before
# its trying to build out module.

#End of Makefile


Module installation:

Since the only thing our module is (currently) doing is to print its message, we will try to install it and capture its outputs, this can be done using the dmesg function or going directly to the /var/log/messages file (I'm usually running the “tail -f /var/log/messages” command on separate console) , now when we will install the module (go to the file location and type “insmod hello.ko”), We will see the following output :
Hello World strated :-]

and while removing the module (“rmmod hello”):
Hello-world was terminated


Tuesday, August 19, 2008

How to extract iso file with bash shell script

Hi,
Few days ago, I faced a problem, I needed to extract an iso file but did't have the appropriate permission for "looping" it :
mkdir -p /mnt/disk
mount -o loop disk1.iso /mnt/disk

So , I had to write a shell script which extract the iso file to a destination directory.
(There might be an easiest way to do this, But this was my way)

Please let me introduce you the "isoinfo" command.
I will use only two options of it:
isoinfo -R -l : List all the iso files in hierarchic way , For example:

#> isoinfo -R -l -i RHEL4-U4-i386-ES-disc5.iso
Will reproduce:
....
Directory listing of /RedHat/
drwxrwxr-x 3 0 0 2048 Aug 3 2006 [ 29 02] .
drwxrwxr-x 3 0 0 2048 Aug 3 2006 [ 28 02] ..
drwxrwxr-x 2 0 0 20480 Aug 3 2006 [ 30 02] RPMS
-r--r--r-- 1 0 0 216 Aug 3 2006 [ 65 00] TRANS.TBL

Directory listing of /RedHat/RPMS/
drwxrwxr-x 2 0 0 20480 Aug 3 2006 [ 30 02] .
drwxrwxr-x 3 0 0 2048 Aug 3 2006 [ 29 02] ..
-r--r--r-- 1 0 0 25312 Aug 3 2006 [ 66 00] TRANS.TBL
-rw-r--r-- 63 0 0 2423867 Jul 28 2006 [ 79 00] evolution-devel-2.0.2-27.rhel4.6.i386.rpm
-rw-r--r-- 193 0 0 27768 Jun 7 2005 [ 1263 00] gedit-devel-2.8.1-4.i386.rpm
-rw-r--r-- 196 0 0 24491673 Jan 5 2005 [ 1277 00] gimp-print-cups-4.2.7-2.i386.rpm
-rw-r--r-- 197 0 0 565998 Jan 5 2005 [ 13236 00] gimp-print-devel-4.2.7-2.i386.rpm
-rw-r--r-- 196 0 0 12706 Jan 5 2005 [ 13513 00] gnome-python2-applet-2.6.0-3.i386.rpm
-rw-r--r-- 196 0 0 23924 Jan 5 2005 [ 13520 00] gnome-python2-gconf-2.6.0-3.i386.rpm
.....

And to extract a specific file from the iso:
isoinfo -R -i -x

Now, Lets go to the script:

First, the interpreter :
#!/bin/bash

# Now, Some global defines
ISO_FILE="disk1.iso"
ISO_INFO="isoinfo"
OUT_DIR="./kickstart"
TMP_FILES="./files.tmp"
DIR_PREFIX="Directory listing of "

# Save all the files tree in tmp log file
${ISO_INFO} -R -l -i ${ISO_FILE} > ${TMP_FILES}

# If the output dir already exist, remove it
if [ -e ${OUT_DIR} ]
then
\rm -rf ${OUT_DIR}
fi

# Read the file tree line by line
exec< ${TMP_FILES}
while read node
do
# If line not empty
if [ -n "$node" ]
then
# If line starts with "Directory listing of", Its a directory, see output sample above
if [[ $node == "${DIR_PREFIX}"* ]]
then
# Remove the "Directory listing of " prefix
dir=`echo $node | sed s/"${DIR_PREFIX}"//g`
# And create the directory under the OUT_DIR directory
# mkdir -p = make parent directories as needed (from the man page)
mkdir -p ${OUT_DIR}/$dir
else
# As you can see in the output sample above, both files and directories are listed together,
# the directories can be identified by the first letter in its attribute columns "d", So I will ignore
# them since we handled directories in the previous case
if [[ $node != "d"* ]]
then
# File
file=`echo $node | cut -d" " -f12`
# Actually, I don't need to recheck again the "." and ".." directory, But, Just in case
if [ $file != "." -a $file != ".." ]
then
# Create full file path
filepath=$dir$file
# Create the file
touch ${OUT_DIR}/${filepath}
# Extract the file to its location
${ISO_INFO} -R -i ${ISO_FILE} -x ${filepath} > ${OUT_DIR}/${filepath}
fi
fi
fi
fi
done

# If exist, remove the temporary files list
if [ -f ${TMP_FILES} ]
then
\rm -rf ${TMP_FILES}
fi

Well, There are much more things to add for this script (for example : status checking here and there), But the main functionality is here.

Ofer.

Monday, August 18, 2008

The Grand opening :-)

Hi,
I have just created the Blog, Wanted to see what is all about, Now, I need to start gathering materials for this .......