Monday, 19 May 2014

How to write a simple Kernel module

After a long break, I am starting this simple post on how to write a kernel module.

I will demonstrate with code, how to write a module that prints message on loading and unloading and nothing more. This will give a good hands on understanding the Makefile and kernel modules.

SOURCE

Consider the following simple .c file

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

#include<linux/stat.h>

MODULE_AUTHOR("GOMATHI KUMAR");
MODULE_LICENSE("GPL");

static int abc=5;
static char *name="sweets";
module_param(abc,int,S_IRUGO | S_IWUSR);

module_param(name,charp,S_IRUGO | S_IWUSR);

static int init_mod()
{
        printk(KERN_ERR "%s: %s : HI.. Good day...\nLoading your module\nabc = %d and name = %s\n", __FILE__, __FUNCTION__, abc, name);
        return 0;
}
static int exit_mod()
{
        printk(KERN_ERR "%s: %s : End of module\n\nBye! Bye!!\nabc = %d and name = %s\n", __FILE__, __FUNCTION__, abc, name);
        return 0;
}

module_init(init_mod);

module_exit(exit_mod);


This c file shows two simple functions that will be executed during init and exit of the module. 

Points to be considered in the above c file : 
a) Module_init and module_exit functions define which function is to be called during loading and unloading of the module
b) printk is the kernel function equivalent of printf that is used in user space. The printks can be used in different log levels such as KERN_ERR, KERN_WARN etc based on the level of importance. This can be used for kernel debugging, though using printk is not an efficient way of kernel debugging. 
c) __FILE__ and __FUNCTION__ are predefined macros, that will print the name of the file and function. There are other such macros, which will give useful information. 
d) The details that are displayed when we do modinfo is from MODULE_AUTHOR, MODULE_LICENSE etc that are defined in the above c file.
e) module_param will help in passing parameters to the module during runtime. This will create entries in sysfs as follows
/sys/module/<YOUR MODULE>/paramaeter/<MODULE_PARAM_YOU_DEFINED>
For the definition of module_param function, moduleparam.h has to be included.
The permissions for reading and writing can be controlled by the third parameter in module_param. The permissions S_IRUGO, S_IWUSR etc are defined in stat.h
Once write permission is given, we can change sysfs entry and from then on that value will be retained.
If not through sysfs, these parameters can be passed during runtime along with insmod as follows
insmod abc.ko <MODULE_PARAM_YOU_DEFINED>=value

MAKEFILE

To compile this as a module, the following simple makefile can be used. 

obj-m := abc.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

Points to be considered in the above Makefile : 
a) obj-m defines that the source will be compiled as a module. In Kernel Makefiles, we can find obj-CONFIG_<SOMETHING> This will define whether to build as module or as part of kernel image, based on the kernel configuration. 
b) all and clean are targets. When we say make clean, only the command beneath "clean:" will be executed. 
c) The above makefile builds based on a single source file. To compile multiple source files into one module, we can use as follows

abcdef-objs := abc.o def.o

d) This makefile shows building of modules for the build machine itself. If we are compiling for a different platform, cross compilation would come into picture. 

Building and Loading of Module

a) To build this, just entering make will do. In the build dir, we will get 

abc.c  abc.ko  abc.mod.c  abc.mod.o  abc.o  Makefile  modules.order  Module.symvers

b) To load the module, insmod <module name> will work. If an error pops as "Operation not permitted", try with sudo. For more clarity on why this error occurs, refer to my previous post 

The messages printed will not come on console always. You might have to check it in dmesg. 

NOTE: If the kernel logs coming on the console are to be turned off, echo 0 > /proc/sys/kernel/printk

c) To unload a module, do a rmmod'

d) To do a modprobe, the module has to be added in /lib/modules/`uname -r`/modules.dep and the module should be available in /lib/modules/`uname -r`. So It is acceptable if upon doing modprobe ./abc.ko shows FATAL : Module not found. 

Hope this was helpful. 

Thanks,
Gomathi

Tuesday, 10 December 2013

Android on vmware

Yippee!! I deployed my virtual machine with android.

It might sound "What is there in it?" But this is my first time I tried it and it was successful. I would like to summarize it here for all those first-handers wondering how to do the same.

1. The first and foremost thing needed to deploy you need the iso. It is mostly observed that android-x86-4.0-RC2-eeepc.iso is well suited for vmware and 4.2 is well suited for virtualbox. The iso can be downloaded from
                               http://www.android-x86.org/download

In this post I will be covering in detail installation in vmware (and hence 4.0). The iso is a 179Mb file. 

2. Once the iso is downloaded, the vm can be created. Start vmware and perform the following. 
a) 

b) Select Typical configuration, which is enabled by default. 

c) Choose installer Disc image file and give path of iso. 

d) Give the name of the virtual machine and path. 

e) Give the Maximum disk size. 

f) In the next window, unselect "Power on this virtual machine after creation"
And click finish. The vm will be created. 

g) once this is done, go back to the path that was set in point (d). There will be virtual machine configuration file (vmx file)

Open this file with notead. 

There will be an entity, ethernet0.virtualDev = "e1000"
Change this to ethernet0.virtualDev = "vlance"

save this file. 

h) Go back to vm and power it on.

i) Select Install android-x86 to hard disk

j) Partition related menu will appear. Select create/Modify partitions option. 

k) This will open a cfdisk utility
Select New

Then select Primary in the next set of options. Then input the size. Then select the bootable flag. 

Then select "write"
Select "Quit"to come back to ""Choose partition"window as shown in point (j). The only difference will now be that the partition you added will now be available in that window. 

l) Format the partition with ext3 file system. 
There will be questions like "Do you want to format?"etc. Please select yes. 
For setting read/write permission, select yes. 

m) After this, select reboot in below screen. 

This finishes deployment. 

But for usage, some more customization are to be done, which are listed below. 
a) The following screen will appear after deployment. 

Click on "Start"

b) Press "Next"for the date and time setup. 
c) Make sure you do not sign in to google account as yet.
d) Give a name to the owner of the tablet and click next
e) Agree to the google terms and services and click next
f) Click finish

Your vm is up and ready with android. 


Network Setup:

1. Open terminal emulator
2. Do su and give root access to terminal emulator.
3. Open /etc/init.sh file and append the following line
             setprop net.dns1 8.8.8.8
4. Reboot the machine.  

Now your android on VM is set and you can even access web pages. 

Hope this was useful. 

Thanks, 
Gomathi

Saturday, 26 October 2013

Linux Test Project - LTP - A Brief

LTP

LTP is an open source project used for testing a linux kernel. The test suites can be written in c, shell or perl. In this post, I will try to explain my understanding of LTP and a sample test case that I will write and execute using LTP.

Download the source from
http://sourceforge.net/projects/ltp/files/LTP%20Source/ltp-20130904/
Upon going to the parent directory of this, You can find out more recen sources of LTP. As of now the above link is the latest suite.

WHAT LTP CONTAINS
There are test cases inside LTP and a test driver called as "pan".
Once the source is extracted, LTP can be viewed as follows.
SCRIPTS
a) IDcheck.sh -> Creates the groups and users required for running LTP
b) runltp -> main script that is used for executing LTP. It  has ability to execute tests related to Sub systems of linux kernel, commands, system calls.
c) Networktest.sh -> To verify features related to network
d) diskio.sh -> verifies disk IO related tests.

DIRECTORIES
a) scenario_groups ->has files which has groups of SCENARIOS to be tested like fs, mm, io, commands, syscalls etc.
b) runtest -> For each scenario described in scenario_groups, these is a corresponding file inside runtest directory which has the Test cases. The format of this file is <TEST CASE TAG> <TEST EXECUTABLE NAME> <Arguments if any>
c) testcases/bin -> This directory consists of each <TEST EXECUTABLE> defined in previous point.
d) testscripts -> contains the scripts that can be used for usage of runltp. Eg : ltpstress.sh etc.

COMPILE AND INSTALL LTP
Once the source is downloaded, perform the following.
1. untar
2. ./configure
3. make
4. sudo make install (will be installed in /opt/ltp)

EXECUTING DEFAULT TEST CASES
1. cd /opt/ltp
2. ./IDcheck.sh
3. sudo ./runltp -p -o output.log -f commands

Point 3 illustrates a sample execution of a particular sub sytem/feature in LTP.

WRITING CUSTOM TEST CASE AND EXECUTION





This is a sample program.
The customized test script can be added in /opt/ltp/testcases/bin/ folder
To execute this script it has to be added in one of the run test files Eg : runtest/commands and the format of this file is

Then this runtest can be executed using
         sudo ./runltp -p -o output.log -f commands

The output will be as shown below

and the output log will be of the following format

In Similar way .c file also can be compiled, added and executed.

Thanks,
Gomathi

KMEMLEAK

KMEMLEAK

Kmemleak is a feature of kernel, that helps in finding the memory leaks in kernel. It only reports the list of memory leaks in the kernel. There is a similar tool to find out memory leaks in user space which is called as Valgrind.

Memory leaks happen when some memory is allocated but not freed. In precise, there is no way to de-reference a particular portion of memory or there is no pointer pointing to that memory using which it can freed.

REQUIREMENTS

To use this particular tool, the kernel has to be built with kmemleak support. In this post, the steps to enable a kernel and ways of identifying and analyzing a leak will be discussed by writing a module that intentionally introduces kernel memory leak.

In the kernel CONFIG_DEBUG_KMEMLEAK is to be enabled. This can be done by doing following.
    From the source directory,
            make menuconfig


Once this configuration is enabled, Set the early log values in Maximum kmemleak early log entries. By default this value is set to 400. But this might not be sufficient in some cases and hence kmemleak might not work as expected. It is better to set this value to a safe 4000.

After setting these kernel configurations, save and quit. In order to detect kernel memory leak, we can write a small piece of code with a memory allocated but not freed. For reference, please use mm/kmemleak-test.c

Then the kernel can be built and booted by using the following steps.
    a) make
    b) make modules
    c) make modules_install
    d) make install
    e) update menu.lst or grub.cfg if make install doesn't automatically do it.
    f) Boot your machine with this particular kernel.

Once the board comes  up you can verify that this is your kernel by the following,
    a) uname -r (You can check the kernel version, if you have used source of a different version)
    b) zcat /proc/config.gz | grep KMEMLEAK (can be verified to check if kmemleak is enabled or not)
    c) If /proc/config.gz is not available you can check cat /boot/config-<kernel version> | grep KMEMLEAK
    d) dmesg | grep -i kmem

After confirming that the deployed kernel is kmemleak enabled, we can start our kmemleak testing and analysis.

To begin with we need to mount debugfs file system. (mount -t debugfs nodev /sys/kernel/debug). KMEMLEAK enabling in kernel will by default do this step and the mount can be done if it is not done automatically. /sys/kernel/debug/kmemleak file will be automatically created which will be our single point of reference for testing and detecting kernel memory leaks.
Multiple options can be passed to this particular file. But most commonly used ones are "scan"and "clear".
Upon doing echo clear > /sys/kernel/debug/kmemleak, all the data will be cleared off. echo scan > /sys/kernel/debug/kmemleak will scan the entire memory and will give information of the kernel memory leaks.
After a scan is performed, cat /sys/kernel/debug/kmemleak will list all the kernel memory leaks at that system state. It also gives a back trace which helps the programmer identify the point where leak happens and helps in fixing the same.
This gives following information
    a)The insmod created memory leak.
    b) The unreference object (leaked memory) is at 0xffff880012f20480
    c) The back trace shows that the leak happens in init function of the module that was inserted.
    d) The kmem_cache_alloc_trace in the bbacktrace shows that a memory is being allocated using one of the malloc variants and is not freed.
This gives all necessary information to fix this leak.

The scan will be performed every 10 minutes by default. But this value of 10 minutes can be modified using echo scan=<secs> > /sys/kernel/debug/kmemleak. All other options supported are
  off           - disable kmemleak (irreversible)
  stack=on      - enable the task stacks scanning (default)
  stack=off     - disable the tasks stacks scanning
  scan=on       - start the automatic memory scanning thread (default)
  scan=off      - stop the automatic memory scanning thread
  scan=<secs>   - set the automatic memory scanning period in seconds
                  (default 600, 0 to stop the automatic scanning)
  scan          - trigger a memory scan
  clear         - clear list of current memory leak suspects, done by
                  marking all current reported unreferenced objects grey
  dump=<addr>   - dump information about the object found at <addr>

To disable kmemleak during boot up, kmemleak=off should be passed in the kernel command line parameter. 

HOW IT DETECTS

The following things happen when kmemleak is enabled in the kernel. 
Whenever a kernel memory is allocated, the pointers are added to a prio search tree and when free is performed this is removed. During a scan, the memory is verified if there is any pointer is available that can free it. If not the memory is considered to be orphan or leaked. 

The best place to get reference is Documentation/kmemleak.txt inside the kernel source.

Thanks,
Gomathi

Thursday, 24 October 2013

Interview Experience - PART II

Questions in C

1. What are static variables and static functions?
2. How to use a function in a file which is defined as a static function in a different file? (Function pointer)
3. A header file is written and included in two .c files. What is the problem in it? - Multiple definition of functions.
How can this be resolved?? (There are no problems when stdio.h is included multiple times. How is that possible?)
4. Given a string, find the number of occurrences of a sub string and print only those words that contain this sub string.
5. Write a program for pre-order traversal of a binary tree using recursion.
6. write a program for binary search in a tree.
7. Assign all the alternate bits of an unsigned short to an unsigned char.
8. What is the different stages of compilation of a c file?
9. What is the content of a .o file?
10. How to pass a command line argument to change a macro?
11. What is the difference between a MACRO and inline function?

Questions in LINUX

1. Write a simple Makefile
2. What all files will be packed in run time rpm, devel rpm.
3. How to add run time rpm as dependency to devel rpm in rpm spec file?
4. Why and when use cross compiler?
5. What is the difference between printf and write? (between library functions and system calls)

Thursday, 19 September 2013

Interview Experience

I am sharing here some of the interview questions that I faced in this post.

C
1. What is volatile and why is it used?
2. What is the necessity for a const qualifier?
3. What is little Endian and big Endian? Write a code to convert little endian to big endian and vice versa.
4. Write a single line macro to do the above conversion
5. Declare a structure.
6. Structure has been declared with int; char; int; char members in same order. What is the size allocated for it in memory? Is there a way to optimise it?
7. Implement a stack using linked list.
8. String copy without using default functions from string.h
9. How to toggle a bit in a number?
10. Convert decimal to binary
11. Verify if a linked list is a palindrome or not.
12. What will happen if there is
main()
{
printf("Hello");
while(1);
}
13. What is the difference between char * const ptr, char const * ptr and const char * ptr??
14. What are preprocessor macros?
15. What is compilation and linking?
16. Is a global variable extern?
17. Can a static variable be made extern?
18. What are static variables and static functions?
19. Is a MACRO advantageous or a function?
20. What is difference between macro and inline function?
21. Reverse a linked list.
22. Find the middle element of linked list in a single traversal.
23. What are the differences between malloc and calloc?
24. Where are static and global variables stored in the memory?
25. How can a multi threaded application be written?

Linux
1. What is a kernel?
2. What is difference between user space and kernel space?
3. Why kernel mode of operation is required?
4. What happens when a system call is made?
5. How a kernel can be live patched? (Ksplice)
6. sed related, awk related question
7. how to write a module?
8. How to write a system call? steps
9. How the boot time of an embedded machine can be reduced?
10. How are embedded distribution different from regular distributions?
11. rpm and all its options
12. patch and all its options
13. How to debug a shell script/binary?
14. what are different mechanisms of inter process communications?
15. What is procfs and sysfs?
16. The ways to set ip for an interface.
17. What all kind of tests LTP covers?
18. What is the need of asmlinkage?
19. How many arguments can be passed to a system call?
20. yocto related questions.

Agile
1. TDD
2. Iterative model

I have added all the questions that I could remember. As and when I remember, I will update the post.

Thanks,
Gomathi

Wednesday, 18 September 2013

Linux Boot Process - Step by Step

Linux Boot process is the process that happens right from power on until a shell appears for an user to start working on. Here I try to explain the process step by step.

1. Once the system is powered on, the control is taken by BIOS(Basic Input Output System).
2. This system triggers POST. POST is Power On System Test. It verifies that all hardware that are connected to the system are working fine.
3. If the verification succeeds, a bootable device is searched for. The bootable device could be a USB stick, a partition in hard drive, a CD ROM, via network etc.
4. When the bootable disk is identified, MBR is loaded from it. MBR is nothing but the Master Boot Record, which occupies the first sector (512 bytes) of the bootable device. Out of these 512 bytes, first 446 bytes consist of the primary boot loader information, next 64 bytes store the partition table information and the last 2 bytes store the magic for validating the MBR.
5. The MBR loads itself to the RAM and starts searching for the active partition. It also verifies no other partition is active at that point of time. It loads this in the RAM. In nut-shell it transfers control to GRUB.
6. The Grub (or earlier days it was lilo) uses /etc/grub/grub.cfg  file. It opens a boot menu, which lists the set of available distributions for deployment based on grub.cfg. If nothing is selected in this menu, the distribution which is specified as ddefault in grub.cfg will be deployed on the system.
7. After the decision of which distribution is to be deployed, an attempt is made to search for the kernel in the predetermined path. It will be zImage (Compressed, less than 512 Kb) or a bzImage(Big compressed, more than 512 Kb).
8. The head of this image itself will have some code that can
           a) Setup hardware
           b) Decompress the kernel image
           c) Copy the kernel to the memory.
9. Once the kernel is loaded into the memory,
           a) It initializes the memory and configures hardware that are connected to the system
           b) It finds the Initrd, decompresses it and mounts the Initrd.
           c) It then loads the kernel modules/device drivers.
           d) Initializes virtual devices.
After all this the smaller Initrd, which was used for bringing up the board is unmounted and the actual initrd is pivot_root ed. Some times it is possible to embed a small Initrd which contains only the bare essentials to bring up the board inside the kernel itself.
10. With this stage, The kernel is loaded and initialised. Now the control is transferred to user space.
           a) The first thing started in user space is /sbin/init. It runs with a PID 1
           b) Then /etc/rc.d/rc.sysinit script is executed.
           c) The /etc/inittab is executed. This is a special file, which spawns/starts services (like for console logging, syslog etc). Here the run level can also be mentioned.
           d) Then all the services i /etc/rc.d/rc<RUN LEVEL>.d is started.
           e) The last step is execution of /etc/rc.d/rc.local. This script can be very useful if we need to customise the start up procedure.

Once all this is done, Shell is available for the user to start using the system.

Thanks,
Gomathi