Friday, February 24, 2012

Semaphores in Linux

Another advantage of semaphores is in situations where the developer would need to restrict the number of times an executable can execute or be mapped in memory. Let's see a simple example:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>

#define KEY 0x100

typedef union semun
{
  int val;
  struct semid_ds *st;
  ushort * array;
}semun_t;
int main()
{
  int semid,count;
  struct sembuf op;

  semid = semget((key_t)KEY,10,0666|IPC_CREAT);
  if(semid==-1)
    {
      perror("error in creating semaphore, Reason:");
      exit(-1);
    }
  count = semctl(semid,0,GETVAL);
  if(count>2)
    {
      printf("Cannot execute Process anymore\n");
      _exit(1);
    }
  //get the semaphore and proceed ahead
  op.sem_num = 0; //signifies 0th semaphore
  op.sem_op = 1; //reduce the semaphore count to lock
  op.sem_flg = 0; //wait till we get lock on semaphore
  if( semop(semid,&op,1)==-1)
    {
      perror("semop failed : Reason");
      if(errno==EAGAIN)
    printf("Max allowed process exceeded\n");
    }
  //start the actual work here
  sleep(10);
  return 1;
}

Difference Between Semaphores and Mutex

After reading though the material above, some pretty clear distinctions should have emerged. However, I'd like to reiterate those differences again here, along with some other noticeable differences between semaphore and Mutex.
  1. A semaphore can be a Mutex but a Mutex can never be semaphore. This simply means that a binary semaphore can be used as Mutex, but a Mutex can never exhibit the functionality of semaphore.
  2. Both semaphores and Mutex (at least the on latest kernel) are non-recursive in nature.
  3. No one owns semaphores, whereas Mutex are owned and the owner is held responsible for them. This is an important distinction from a debugging perspective.
  4. In case the of Mutex, the thread that owns the Mutex is responsible for freeing it. However, in the case of semaphores, this condition is not required. Any other thread can signal to free the semaphore by using the sem_post() function.
  5. A Mutex, by definition, is used to serialize access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A semaphore, by definition, restricts the number of simultaneous users of a shared resource up to a maximum number
  6. Another difference that would matter to developers is that semaphores are system-wide and remain in the form of files on the filesystem, unless otherwise cleaned up. Mutex are process-wide and get cleaned up automatically when a process exits.
  7. The nature of semaphores makes it possible to use them in synchronizing related and unrelated process, as well as between threads. Mutex can be used only in synchronizing between threads and at most between related processes (the pthread implementation of the latest kernel comes with a feature that allows Mutex to be used between related process).
  8. According to the kernel documentation, Mutex are lighter when compared to semaphores. What this means is that a program with semaphore usage has a higher memory footprint when compared to a program having Mutex.
  9. From a usage perspective, Mutex has simpler semantics when compared to semaphores.

A Worker-Consumer Problem

The worker-consumer problem is an age old scenario that has been used to justify the importance of semaphores. Let's see a traditional worker-consumer problem and its simple solution. The scenario presented here is not too complex.
There are two processes: Producer and Consumer. The Producer inserts information into the data area; while the Consumer removes information from the same area. There must be enough space for the Producer to insert information into the data area. The Producer's sole function is to insert data into the data area. Similarly, the Consumer's sole function is to remove information from the data area. In short, the Producer relies on the Consumer to make space in the data-area so that it may insert more information, while the Consumer relies on the Producer to insert information into the data area so that it may remove that information.
To develop this scenario, a mechanism is required to allow the Producer and Consumer to communicate, so they know when it is safe to attempt to write or read information from the data area. The mechanism that is used to do this is a semaphore.
In the below sample code , the data area is defined as char buffer[BUFF_SIZE] and buffer size is #define BUFF_SIZE 4. Both Producer and Consumer access this data area. The data area's limit size is 4. POSIX semaphores are being used for signaling.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>

#define BUFF_SIZE 4
#define FULL 0
#define EMPTY 0
char buffer[BUFF_SIZE];
int nextIn = 0;
int nextOut = 0;

sem_t empty_sem_mutex; //producer semaphore
sem_t full_sem_mutex; //consumer semaphore

void Put(char item)
{
  int value;
  sem_wait(&empty_sem_mutex); //get the mutex to fill the buffer

  buffer[nextIn] = item;
  nextIn = (nextIn + 1) % BUFF_SIZE;
  printf("Producing %c ...nextIn %d..Ascii=%d\n",item,nextIn,item);
  if(nextIn==FULL)
    {
      sem_post(&full_sem_mutex);
      sleep(1);
    }
  sem_post(&empty_sem_mutex);

}

void * Producer()
{
  int i;
  for(i = 0; i < 10; i++)
    {
      Put((char)('A'+ i % 26));
    }
}

void Get()
{
  int item;

  sem_wait(&full_sem_mutex); // gain the mutex to consume from buffer

  item = buffer[nextOut];
  nextOut = (nextOut + 1) % BUFF_SIZE;
  printf("\t...Consuming %c ...nextOut %d..Ascii=%d\n",item,nextOut,item);
  if(nextOut==EMPTY) //its empty
    {
      sleep(1);
    }

  sem_post(&full_sem_mutex);
}

void * Consumer()
{
  int i;
  for(i = 0; i < 10; i++)
    {
      Get();
    }
}

int main()
{
  pthread_t ptid,ctid;
  //initialize the semaphores

  sem_init(&empty_sem_mutex,0,1);
  sem_init(&full_sem_mutex,0,0);

  //creating producer and consumer threads

  if(pthread_create(&ptid, NULL,Producer, NULL))
    {
      printf("\n ERROR creating thread 1");
      exit(1);
    }

  if(pthread_create(&ctid, NULL,Consumer, NULL))
    {
      printf("\n ERROR creating thread 2");
      exit(1);
    }

  if(pthread_join(ptid, NULL)) /* wait for the producer to finish */
    {
      printf("\n ERROR joining thread");
      exit(1);
    }

  if(pthread_join(ctid, NULL)) /* wait for consumer to finish */
    {
      printf("\n ERROR joining thread");
      exit(1);
    }

  sem_destroy(&empty_sem_mutex);
  sem_destroy(&full_sem_mutex);

  //exit the main thread

  pthread_exit(NULL);
  return 1;
}

Conclusions

We've explored the possibilities of different varieties of semaphores, as well as the differences between semaphores and Mutex. This specific knowledge could be helpful to developers in migration between System V and POSIX semaphores and when deciding whether to use Mutex or semaphores. For further details on the APIs used in the above example, refer to relevant the man pages.





http://linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html?page=6

Friday, February 17, 2012

Build Linux Kernel Module

Howto: Build Linux Kernel Module Against Installed Kernel w/o Full Kernel Source Tree


Linux Kernel headers

This is essential because if you just want to compile and install driver for new hardware such as Wireless card or SCSI device etc. With following method, you will save the time, as you are not going to compile entire Linux kernel.
Please note that to work with this hack you just need the Linux kernel headers and not the full kernel source tree. Install the linux-kernel-headers package which provides headers from the Linux kernel. These headers are used by the installed headers for GNU glibc and other system libraries as well as compiling modules. Use following command to install kernel headers:
# apt-get install kernel-headers-2.6.xx.xx.xx
Replace xx.xx with your actual running kernel version (e.g. 2.6.8.-2) and architecture name (e.g. 686/em64t/amd64). Use uname -r command to get actual kernel version name. Please note that above command will only install kernel headers and not the entire kernel source-code tree.
A more generic (recommend) and accurate way is as follows:
# apt-get install kernel-headers-$(uname -r)
All you need to do is change Makefile to use current kernel build directory. You can obtain this directory name by typing following command:
$ ls -d /lib/modules/$(uname -r)/build
Sample output:
/lib/modules/2.6.27-7-generic/build
Let, say you have .c source code file called hello.c. Now create a Makefile as follows in the directory containing hello.c program / file:
$ vi Makefile
Append following text:
obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
Save and close the file. Type the following command to build the hello.ko module:
$ make
To load Linux kernel module type the command:
# modprobe hello

A complete example

Create test directory (you can download following Makefile and .c file here):
$ mkdir ~/test
$ cd ~/test

Create hello.c kernel module file:
#include
<linux/module.h>
#include
<linux/kernel.h>
 
int init_module(void)
{
 printk(KERN_INFO "init_module() called\n");
 return 0;
}
 
void cleanup_module(void)
{
 printk(KERN_INFO "cleanup_module() called\n");
}
 
Create a Makefile:
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) clea
To build kernel module enter:
$ make
Sample output:
make -C /lib/modules/2.6.27-7-generic/build M=/tmp/test2 modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.27-7-generic'
  CC [M]  /tmp/test2/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /tmp/test2/hello.mod.o
  LD [M]  /tmp/test2/hello.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.27-7-generic'
Run ls command to see newly build kernel module:
$ ls
Sample output:
hello.c  hello.ko  hello.mod.c hello.mod.o  hello.o  Makefile Module.markers modules.order  Module.symvers
hello.ko is kernel module file. To see information about module, enter:
$ modinfo hello.ko
Sample output:
filename:       hello.ko
srcversion:     4F856ABA1F3290D5F81D961
depends:
vermagic:       2.6.27-7-generic SMP mod_unload modversions 586 
To load kernel module, enter:
$ sudo insmod hello.ko
OR
$ sudo modprobe hello
To list installed Linux kernel module, enter:
$ lsmod
$ lsmod | grep hello

To remove hello Linux kernel module, enter:
$ rmmod hello
This module just logs message to a log file called /var/log/messages (/var/log/syslog), enter:
$ tail -f /var/log/messages
Sample output:
Nov  5 00:36:36 vivek-desktop kernel: [52488.923000] init_module() called
Nov  5 00:36:50 vivek-desktop kernel: [52503.065252] cleanup_module() called

Thursday, February 16, 2012

Recompiling Ubuntu Kernel


I decided to make a post on recompiling your Ubuntu kernel after after taking a look at the instructions on the Ubuntu wiki. Although the instructions were correct it was a big jumbled mess and almost impossible to figure out what was what from the instructions. This post will cover recompiling the kernel that comes with Ubuntu. The reasons for doing this are to keep the current Ubuntu patches and configs and simply add some stuff of your own. This would be useful for adding a patch of some sort or adding support in the kernel .config for a piece of hardware or software which may not be enabled by default.
For this article I will be using Ubuntu 10.10. these instructions should also work for 9.10 and 10.04 but earlier versions had a slightly different process.
Ok so lets get started:
NOTE: I do every thing as root but I will add sudo to the commands for the people that are not comfortable working as root.
1. Install the required packages
sudo apt-get install fakeroot kernel-wedge build-essential makedumpfile kernel-package libncurses5 libncurses5-dev
2. Next issue the following command
1sudo apt-get build-dep --no-install-recommends linux-image-$(uname -r)
3. Next e need to create a working directory and download the Ubuntu image which correspond’s with our running kernel.
1mkdir ~/source
2cd ~/source
3apt-get source linux-image-$(uname -r)
4cd linux-2.6.35
4. Now, since we are just rebuilding the current kernel we can use the current .config file as a starting point.
1cp -vi /boot/config-`uname -r` .config
5. At this point if we have any patch’s we can add those. Generally a patch come in the form of a .patch file and needs to be applied in the top level directory of the source which in this case would be ~/source/linux-2.6.35
1patch -p1 < example.patch
Do this for all patch’s you may need to apply.
6. Next we will open the ncurses editor for the .config file. This is where all the support is defined for the kernel.
1make menuconfig
I’m going to assume you know what kernel options you need. This is also a good chance to remove support for anything you do not need. Smaller kernel with less bloat can greatly improve performance.
7. Save the menu file and exit the interface.
8. At this point you should be in the ~/source/linux-2.6.35 directory again
9. A little trick you can do is to set the CONCURRENCY_LEVEL variable to speed up the compile of the kernel. The number should be the number of processors you have plus one. So in my case I have a dual core processor so I will add one which would be three.
1export CONCURRENCY_LEVEL=3
10. Lets build it! You need to add a custom string to the end to mark your new kernel. In this case I added “-QD” to the end but you can add what ever you want
1make-kpkg clean
2fakeroot make-kpkg --initrd --append-to-version=-QD kernel-image kernel-headers
11. At this point you should go grab some food because the kernel compile can take a while
12. Once the kernel is built it will be one directory up in the ~/source file we were originally working in.
1cd ~/source
2sudo dpkg -i linux-image-2.6.35.(This part will be whatever name you gave it).deb
3sudo dpkg -i linux-headers-2.6.35.(This part will be whatever name you gave it).deb
There will only be these 2 debs so use tab complete to get the correct names. The dpkg commad will do the actual installing of the kernel.
13. Now we need to make a initramfs.
1sudo update-initramfs -c -k 2.6.35+QD
You will need to add your kernel version + the custom string you added on the end.
14. Now lets update grub
1sudo update-grub
15. Reboot and you should be rocking with your new kernel! 






http://www.question-defense.com/2010/09/26/how-to-recompile-your-ubuntu-10-10-kernel-for-patching-or-to-add-support-for-a-specific-device