Friday 28 June 2013

[Kernel Programming: #1] Introduction to Kernel Programming

Will share Kernel Programming concepts in couple of days :)

Day 1: Load and remove a simple module to/from Kernel.

A module is a loadable Kernel object - related subroutines, data are grouped together, it has one entry and one exit point. It enables the dynamic insertion/removal of drivers into/from the Kernel on demand in response to the device state.

Linux Kernel supports the insertion and removal a module at runtime based on the requirement or demand.

Module has one entry point and one exit point, these are functions.
The entry point (start function) will be called when the module is loaded into kernel successfully.
The exit point will be used for releasing the resources which are acquired in related subroutines, and exit point is called just before when the module is removed from Kernel.

Entry point: int init_module(void); --> Initialization function: Module execution will be start at this point. This is entry function for modules like main() for C programs.
Exit point: void cleanup_module(void); --> Cleanup function: Modules end by calling this function.

Example: module_1.c

  1 #include<linux/module.h> /* Needed by all modules *MUST* */
  2
  3 int init_module(void) {
  4         printk(KERN_ALERT "1st module program: Module Inserted\n");
  5         return 0;
  6 }
  7
  8 void cleanup_module() {
  9         printk(KERN_ALERT "1st module program: Module Removed\n");
 10 }

We can put our own names for start and cleanup functions, but it requires other macros should be used in the code. I will explain it later.

Start function init_module() will register a handler with Kernel to perform a task.
And, cleanup_module() will release all resources, so that the module can unload safely from Kernel.

Every kernel module must include <linux/module.h>, tells that it is a module.
printk() function is used as logging mechanism for kernel which basically store the information and log any warning/error msgs for debugging purpose.
And, printk() takes the priority of the message and message as arguments.
The priority levels are available in <linux/kernel.h>. So, it is advised to include this macro also in the program.
I set KERN_ALERT as priority (1, highest) for our message, so that printk will print the msg in user console. If the priority is low then it may logged into /var/log/messages.

Compiling the Kernel module:
We use makefiles in order to build the kernel modules.
Will update the makefile details soon.
Makefile to compile our module.

  1 obj-m += module_1.o
  2
  3 KDIR = /usr/src/linux-headers-2.6.32-28-generic
  4
  5 all:
  6         $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
  7
  8 clean:
  9         rm -rf *.o *.ko *.mod.* *.symvers *.order


Since I have named module_1.c for our module, the object file which is generated after compilation will be module_1.o. See 1st line in Makefile.

At line 3, KDIR is the location of our kernel header files directory . You can get these details by using the command "uname -r". After using this command you will get the result like (2.6.32-28-generic). And use "ls /usr/src/", here we find a directory named like linux-headers-2.6.32-28-generic.

At line 5, all used to build the kernel module, we input the location of kernel header files directory in order to build our module.
And, clean is used to remove all executable files after we unload our module from Kernel.

Build the module:
Just run "make", you will see msg like below

make -C /usr/src/linux-headers-2.6.32-28-generic SUBDIRS=/home/***/module_programming/module1 modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-28-generic'
  CC [M]  /home/***/module_programming/module1/module_1.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/***/module_programming/module1/module_1.mod.o
  LD [M]  /home/***/module_programming/module1/module_1.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-28-generic'

So, our module is build without any errors.
Now use below commands to load/unload the module to/from kernel.
Step1. insmod module_name.ko
    --> used to load our module into the kernel
Step2. dmesg
  --> used to see the printk log details.
Step3. rmmod module_name.ko
   --> used to remove our module from kernel

After insmod, enter dmesg then we will see our msg on the terminal, which we added in printk() function. And also again rmmod command, check log using dmesg.

Note: we will see the below error when insmod is used 
>> insmod: error inserting 'module_1.ko': -1 Operation not permitted
Then, use "sudo -s" command to work in root mode, we won't see this error msg again.

If we have multiple files for a module then the makefile looks like below

obj-m += module_temporary_name.o
module_temporary_name-objs := module_1.o module_2.o

all and clean are same as mentioned above.

Thursday 27 June 2013

[C: Facts#1] Test our C skills

I will share some facts about C language those I encountered when I used macros in my assignments and today also I found one interesting thing about macros definition.
If we are not define macro in proper way then our program will end up with unexpected results.
A Simple macro definition is

#define square(x) (x * x)
This macro replaces the square(x) with (x * x) in the program.
Example:


  1. #include<stdio.h>
  2. #define square(x) (x * x)

  3. void main()
  4. {
  5.    int val = 5;

  6.     printf("Before square: val = %d\n", val);
  7.  printf("Square of val++ is: %d \n", square(val++));
  8.  printf("After square: val = %d\n", val);
  9. }

Output:
Before square: val = 5
Square of val++ is: 25
After square: val = 7

Explanation: 
The intention our programmer would be square of 6 (if val = 5, val++ is 6). But, square(val++) at line no 9 will be replaced by (val++ * val++) after compilation. Now, the val is replaced in the expression (val++ * val++) and it looks like (5 * 5) and finally, the ans will be 25.
When the expression (val++ * val++) is evaluated, the val value is 5 and the increment type is post increment, so, this increment is not reflected on val at this moment. So, 5 is assigned at val++ positions, and leads to (5 * 5).
And, after this expression the val value becomes 7, as val is incremented twice.

Experiment_2:
Even if we replace square(i++) by square(i+1), then also we see problem.
Since, square(i+1) will be replaced by (i+1 * i+1), and in turn it leads to (i + (1 * i) + 1) since multiplication has more priority over addition.
So, that output is 5 + (1 * 5) + 1 = 11.
Solution: Use pair of brackets for each macro parameter.
i.e. ((i + 1), (i + 1)) ==> ((5 + 1), (5 + 1)) = ((5 + 1) * (5 + 1)) = (6 * 6) = 36

Experiment_3:
If we declare multiple statements for a macro then it is advised to use/call the macro within braces.
For example, if code snippet looks like below
#define macro_1(value) printf("value: %x\n", value); printf("blah blah\n");

if (value < 1)
     macro_1(value);

After compilation, the code will look like below
if(value < 1)
     printf("value: %x\n", value);
printf("blah blah\n");
So, the 2nd printf will be executed for all cases.
Solution: To avoid this type of behavior, please use braces around macros.
if (value < 1) {
     macro_1(value);
}
or use braces in the macro definition.
macro_1(value) { printf("value: %x\n", value); printf("blah blah\n"); }

This will helpful even in case of the macros which having if else conditional statements. Example,
macro_2(value) if (value != 0) printf("value: %x\n", value); else printf("blah blah\n");

I hope this post will make us to think twice before we use macros in our code.
Please post your suggestions on any useful info regarding macro use.
If you find anything is wrong here then please add your comments.
Thank you.

Tuesday 18 June 2013

Why I created this PracticePeople Blog ?

The first question comes into our mind "why this guy created this blog, named it as <practicepeople> ?"

The answer is simple - would like to share my ideas, skill sets, findings, experience, useful info and learning new things in my daily life.
Anyways, the best answer will be --> Sharing of Knowledge

One of my best friends call me as Practice. So I named my first blog as "practicepeople".

Before getting started, the main purpose of this blog is to share interesting/useful findings including technical/non-technical stuff and also would like to improve my skills. Yes, I am selfish guy.

I wanted to create this blog in my B.E., but I could n't find free time as I was busy with my studies.
And, finally I created a blog with full of happiness and I am too enthusiastic about this blog.

At this point of time, I am not sure how this blog capture the attention of people. I will put my efforts to make this blog very interesting.

I referred the below website to create my blog. Thanks to wikihow.
http://www.wikihow.com/Start-a-Blog

You might also like

Related Posts Plugin for WordPress, Blogger...