Interrupt Handling in Linux

What is Interrupt?

An interrupt (also known as an exception or trap) is an event that causes the CPU to stop executing the current program and start executing a special piece of code called an interrupt handler or interrupt service routine (ISR).

There are two different kinds of interrupts:

         •Synchronous interrupt (Exception) produced by the CPU while processing instructions
         •Asynchronous interrupt (Interrupt) issued by other hardware devices
Handling interrupts:
   •Interrupts can occur at any time, the kernel tries to get it out of the way as soon as possible
   •An interrupt can be interrupted by another interrupt
   •There are regions in the kernel which must not be interrupted at all

Two different interrupt levels are defined:
   •Maskable interrupts issued by I/O devices; can be in two states, masked or unmasked. Only   
     unmasked interrupts are getting processed.
   •Nonmaskable interrupts; critical malfunctions (f.e. hardware failure); always processed by the 

Every hardware device has it's own Interrupt Request (IRQ) line. The IRQs are numbered starting from 0. All IRQ lines are connected to a Programmable Interrupt Controller (PIC). The PIC listens on IRQs and assigns them to the CPU. It is also possible to disable a specific IRQ line.

Top Half and Bottom Half:

One of the main problems with interrupt handling is how to perform lengthy tasks within a handler. Often a substantial amount of workmust be done in response to a device interrupt, but interrupt handlers need to finish up quickly and not keep interrupts blocked for long. These two needs (work and speed) conflict with each other,leaving the driver writer in a bit of a bind.

Linux (along with many other systems) resolves this problem by splitting the interrupt handler into two halves. The so-called top half is the routine that actually responds to the interrupt—the one you register with request_irq. The bottom half is a routine that is scheduled by the top half to be executed later, at a safer time. The big difference between the top-half handler and the bottom half is that all interrupts are enabled during execution of the bottom half—that’s why it runs at a safer time.

To implement bottom halves,two methods:
1) task lets
2) work queues

Linux Kernel Modules

Linux kernel modules are pieces of code that can be loaded and unloaded from kernel on demand.

Kernel modules offers an easy way to extend the functionality of the base kernel without having to rebuild or recompile the kernel again. Most of the drivers are implemented as a Linux kernel modules. When those drivers are not needed, we can unload only that specific driver, which will reduce the kernel image size.

Kernel modules will have extension .ko
Kernel modules will operate on kernel space.
All Drivers are modules. Not all modules are drivers.

Kernel Modules Commands:

lsmod: To see list of modules that already loaded on system
insmod: To insert modules into kernel
modinfo: To display modules information
rmmod: To remove modules from kernel

How to Write Kernel Modules:

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h>    // included for KERN_INFO
#include <linux/init.h>      // included for __init and __exit macros

MODULE_DESCRIPTION("Hello World module");

static int __init hello_init(void)
    printk(KERN_INFO "Hello world!\n");
    return 0;    // Non-zero return means that the module couldn't be loaded.

static void __exit hello_cleanup(void)
    printk(KERN_INFO "Cleaning up module.\n");

Makefile to compile module:
obj-m += hello.o

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
When a module is inserted into the kernel, the module_init macro will be invoked, which will call the function hello_init. Similarly, when the module is removed with rmmod, module_exit macro will be invoked, which will call the hello_exit. Using dmesg command, we can see the output from the sample Kernel module.

printk() is used for printing kernel messages

Latest Kernel version

Current stable kernel version: 4.5.1

C program to reverse an array

#include <stdio.h> 
int main() 
      int n, c, d, a[100], b[100]; 
      printf("Enter the number of elements in array\n"); 
      scanf("%d", &n); 
      printf("Enter the array elements\n"); 
      for (c = 0; c < n ; c++) 
           scanf("%d", &a[c]); 
      for (c = n - 1, d = 0; c >= 0; c--, d++) 
           b[d] = a[c]; 
      for (c = 0; c < n; c++) 
           a[c] = b[c]; 
      printf("Reverse array is\n"); 
      for (c = 0; c < n; c++) 
      printf("%d\n", a[c]); return 0; 

This program reverses the array elements. For example if a is an array of integers with three elements such that
a[0] = 1
a[1] = 2
a[2] = 3

Then on reversing the array will be
a[0] = 3
a[1] = 2
a[0] = 1

C++; Singleton Design Pattern

Singleton is a creational design pattern.
Provide one and only instance of an object.

#include using namespace std; 
class MySingleton 
      public: static MySingleton* iInstance; 
      public: static MySingleton* GetInstance(); 
      private: MySingleton(); 
MySingleton* MySingleton::iInstance = NULL; 
      cout << "Inside construtor ..." << endl; 
MySingleton* MySingleton::GetInstance() 
      if ( iInstance == NULL ) 
           iInstance = new MySingleton(); 
     return iInstance; 

void main() 
     MySingleton* obj; 
     obj = MySingleton::GetInstance(); 

Useful linux commands

Vi Editor:

    x          Delete character at cursor
    X          Delete character before cursor
    Y or yy  Yank (copy) current line into "unnamed" storage buffer.
    p          Paste unnamed storage buffer after current line.
    P          Paste unnamed storage buffer before current line.
    r           Replace character
    R          Overwrite characters from cursor onward
    s          Substitute one character under cursor continue to insert
    S          Substitute entire line and begin to insert at beginning of line
    J           Join current and following line into one line

  • Use command: ":e filename"
       Start new edit session on specified file name without closing current vi /        vim editor process.
  • Find/Replace:Example:
       :%s/fff/rrrrr/  -   For all lines in a file, find string "fff" and replace with                                   string "rrrrr" for the first instance on a line.
       :%s/fff/rrrrr/g -  For all lines in a file, find string "fff" and replace with                                   string "rrrrr" for each instance on a line.
       :%s/fff/rrrrr/gc - For all lines in a file, find string "fff" and replace with                                   string "rrrrr" for each instance on a line. Ask for                                           confirmation
       :%s/fff/rrrrr/gi - For all lines in a file, find string "fff" and replace with                                   string "rrrrr" for each instance on a line. Case                                               insensitive.

Extract or Unpack a tar File:

  • To extract tar file of type:
       tar -xvf <filename>.tar
  • To extract .tar.gz (gzip) file

    tar -xzvf <file name>.tar.gz
  • To extract .tar.bz2 (bzip2) file
       tar -xjvf file.tar.bz2

  • To extarct single file from tar file
        tar -xvf file.tar foo.txt 
        tar -xzvf file.tar.gz foo.txt 
        tar -xjvf file.tar.bz2 foo.txt

-x : Extract a tar ball.
-v : Verbose output or show progress while extracting files.
-f : Specify an archive or a tarball filename.
-j : Decompress and extract the contents of the compressed archive created by bzip2 program (tar.bz2 extension).
-z : Decompress and extract the contents of the compressed archive created by gzip program (tar.gz extension).

C++ Tips

  • Class is collection of data members and member fn.
  • Object is a instance of a class
  • Abstraction is hiding unessential things and reveal the essential things.
  • Encapsulation is wrapping up data and functions into a single unit Abstraction implies encapsulation.(Relationship between Abstraction and Encapsulation)
  • Inheritance is a process of crating new class form existing class.  The new class is called Derived class and the old class is called Base class Inheritance is mainly used to code reusability.In multiple inheritance occur an ambiguity error. But multilevel inheritance not occur an ambiguity error.
  • Composite is a opposite of Inheritance. It’s used to related between two distinct classes (unrelated classes).
  • Function overloading  function having same name with different signature in same class.
  • Operator overloading means to work on a different operand.
  • Function overriding function having same name with same signature in different class.
  • Polymorphism is ability to assure  several distinct forms(tasks). There are two type of polymorphism is available

                        i. static or compile time Polymorphism 
                      (Operator overloading and   function overloading)
ii.Dynamic or run time Polymorphism ( Virtual function)

  • Virtual functions work in overridden technique. Virtual fn is mainly used to, base class pointer can access derived class functions.
  • Abstract class means, a class which contain at least one pure virtual function. In abstract class cannot create an object.
  • Pure virtual function is a virtual function with expression equal to zero in declaration part.
  • Macro is a single line replacement of set of statements.
  • Inline is a keyword , its appear before function name. This function is faster than normal function. Inline function is a single line replacement of set of statements.

        Both (macro and inline function) functions are replaced a set of   
        statement. The statements are replaced in Pre-compilation Time 
        (Before compilation).

  • Inline functions are used in Type checking like normal function.  But macro won’t (Difference)
  • In structure , the default access specifies is Public.  But class , is Private (Difference)
  •  In structure,  the data members are associated in separate memory.  But Union, data members are shared in common memory. The size of union = Largest data member size in union (Difference).
  • New is operator, it’s overloaded, it’s call constructor automatically.  But malloc() is not overloaded and it’s cannot call constructor. But both are allocate memory.(Difference)
  • Malloc() and calloc() both are allocate memory. But malloc() allocate memory and store(initialize) the garbage value. But calloc() allocate memory, its allocate integer type then initialize zero its string initialize NULL value. (Difference)
  • Delete statement delete the all elements in an array, but the destructor call only the first element.delete[] statement delete the all element in an array, the destructor call each and every element in an array.(Difference)
  • Delete is a operator, it can be overload. Its call destructor call automatically. Delete operator mainly used to de-allocate memory. 
  • New is a operator , its overload operator. Its call constructor automatically. New operator mainly used to allocate memory.
  • Constructor is call automatically, whenever an object is created then the constructor is call.  Constructor is overload, it cannot return a value, and return type. 
  • Destructor is a call automatically, whenever an object is destroyed then the destructor will call.Its can’t overloaded, its cannot return a value and return type.
  • this pointer is a constant pointer. Its can use only non static member function. Its cannot used in static member function, because the static function share in all object but the this pointer points the current object.

      Explain this:

Ø   int (*p)[10]         ------     Pointer to array , first preference in pointer
Ø   int  *p[10]           ------     Array of pointer to int value , first      preference in array
Ø   int *f()                ------     function pointer
Ø   int (*f)()              ------     pointer to function

Which is the best sorting method?

There is no sorting method that is universally superior to all others. The programmer must carefully examine the problem and the desired results before deciding the particular sorting method. Some of the sorting methods are given below:

Bubble sort : When a file containing records is to be sorted then Bubble sort is the best sorting method when sorting by address is used.
Bsort : It can be recommended if the input to the file is known to be nearly sorted.
Meansort : It can be recommended only for input known to be very nearly sorted.
Quick Sort : In the virtual memory environment, where pages of data are constantly being swapped back and forth between external and internal storage. In practical situations, quick sort is often the fastest available because of its low overhead and its average behavior.
Heap sort : Generally used for sorting of complete binary tree. Simple insertion sort and straight selection sort : Both are more efficient than bubble sort. Selection sort is recommended for small files when records are large and for reverse situation insertion sort is recommended. The heap sort and quick sort are both more efficient than insertion or selection for large number of data.
Shell sort :  It is recommended for moderately sized files of several hundred elements.
Radix sort : It is reasonably efficient if the number of digits in the keys is not too large.

Is it possible that one try block can have multiple catch blocks?

There can be more than one exception handler (or catch block) for one try block, because it might so happen that in one single try block there can be different types of exceptions that can be thrown. 

This is shown in the following code snippet:
// statement that throws divide-by-zero exception
// statement that throws array out-of-bound exception
catch ( divide_error id1 ){ // code }
catch ( out_of_bound_error id2 ){ // code } 

Is it possible to throw an exception through a constructor?

Yes, we can! We cannot return any error value from the constructor, as the constructor doesn’t have any return type. In such situation, by throwing an exception we can pass value to catch block. 

This is shown in the following example:
#include <iostream.h>
class sample
           sample ( int i )
                 if ( i == 0 ) throw "error"; 
void main( )
          sample s ( 0 );
     catch ( char * str ) 
          cout << str; 

How can we copy the contents of one file to another in one shot?

#include <fstream.h>
void main( )
     char source [ 67 ], target [ 67 ];
     char ch;
     cout << endl << "Enter source filename";
     cin >> source;
     cout << endl << "Enter target filename";
     cin >> target;
     ifstream infile ( source );
     ofstream outfile ( target );
     outfile << infile.rdbuf( );
Here all the copying is done through the single statement
outfile << infile.rdbuf( );

The function rdbuf( ) returns the address of the strstreambuf where the values are stored. 

How to allocate memory for a multidimensional array dynamically?

Many times we need to allocate memory for a multidimensional array dynamically. Because of complexity of pointers many find this difficult.

Following program allocates memory for a 3 x 3 array dynamically, copies contents of a 3 x 3 array in it and prints the contents using the pointer.

#include <iostream.h>
#include <new.h>
int a[ ][3] = {
                      1, 2, 3,
                      4, 5, 6,
                      7, 8, 9
void main( )
     int **p;
     p = new int *[3] ;
     for ( int i = 0 ; i < 3 ; i++ )
            p[i] = new int[3];
     for ( i = 0 ; i < 3 ; i++ )
       for ( int j = 0 ; j < 3 ; j++ )
            p[i][j] = a[i][j] ; 
     for ( i = 0 ; i < 3 ; i++ )
       for ( j = 0 ; j < 3 ; j++ )
            cout << p[i][j] ;
      cout << "\n" ;