Linux Kernel debugging Techniques – printk

printk(” This is my status here\n\r”);

printk(KERN_INFO, “This path also has chosen by driver xyz\n\r”);

KERN_EMERG	/* system is unusable */
KERN_ALERT	/* action must be taken immediately */
KERN_CRIT	/* critical conditions */
KERN_ERR	/* error conditions */
KERN_WARNING	/* warning conditions */
KERN_NOTICE	/* normal but significant condition */
KERN_INFO	/* informational */
KERN_DEBUG	/* debug-level messages */
KERN_DEFAULT	/* the default kernel loglevel */

C++ Network Libraries

Aggregated List of Libraries

Reactor and Proactor: two I/O multiplexing approaches

Reactor and Proactor: two I/O multiplexing approaches

In general, I/O multiplexing mechanisms rely on an event demultiplexor [13], an object that dispatches I/O events from a limited number of sources to the appropriate read/write event handlers. The developer registers interest in specific events and provides event handlers, or callbacks. The event demultiplexor delivers the requested events to the event handlers.

Two patterns that involve event demultiplexors are called Reactor and Proactor [1]. The Reactor patterns involve synchronous I/O, whereas the Proactor pattern involves asynchronous I/O. In Reactor, the event demultiplexor waits for events that indicate when a file descriptor or socket is ready for a read or write operation. The demultiplexor passes this event to the appropriate handler, which is responsible for performing the actual read or write.

In the Proactor pattern, by contrast, the handler—or the event demultiplexor on behalf of the handler—initiates asynchronous read and write operations. The I/O operation itself is performed by the operating system (OS). The parameters passed to the OS include the addresses of user-defined data buffers from which the OS gets data to write, or to which the OS puts data read. The event demultiplexor waits for events that indicate the completion of the I/O operation, and forwards those events to the appropriate handlers. For example, on Windows a handler could initiate async I/O (overlapped in Microsoft terminology) operations, and the event demultiplexor could wait for IOCompletion events [1]. The implementation of this classic asynchronous pattern is based on an asynchronous OS-level API, and we will call this implementation the “system-level” or “true” async, because the application fully relies on the OS to execute actual I/O.

An example will help you understand the difference between Reactor and Proactor. We will focus on the read operation here, as the write implementation is similar. Here’s a read in Reactor:

  • An event handler declares interest in I/O events that indicate readiness for read on a particular socket
  • The event demultiplexor waits for events
  • An event comes in and wakes-up the demultiplexor, and the demultiplexor calls the appropriate handler
  • The event handler performs the actual read operation, handles the data read, declares renewed interest in I/O events, and returns control to the dispatcher

By comparison, here is a read operation in Proactor (true async):

  • A handler initiates an asynchronous read operation (note: the OS must support asynchronous I/O). In this case, the handler does not care about I/O readiness events, but is instead registers interest in receiving completion events.
  • The event demultiplexor waits until the operation is completed
  • While the event demultiplexor waits, the OS executes the read operation in a parallel kernel thread, puts data into a user-defined buffer, and notifies the event demultiplexor that the read is complete
  • The event demultiplexor calls the appropriate handler;
  • The event handler handles the data from user defined buffer, starts a new asynchronous operation, and returns control to the event demultiplexor.

Type of ‘this’ pointer in C++

thispointer

In C++, this pointer is passed as a hidden argument to all non-static member function calls.

The type of this depends upon function declaration.

If the member function of a class X is declared const, the type of this is const X* (see code 1 below),

if the member function is declared volatile, the type of this is volatile X* (see code 2 below),

and if the member function is declared const volatile, the type of this is const volatile X* (see code 3 below).

Code 1

#include<iostream>
class X {
   void fun() const {
    // this is passed as hidden argument to fun().
    // Type of this is const X*
    }
};

Code 2

#include<iostream>
class X {
   void fun() volatile {
     // this is passed as hidden argument to fun().
     // Type of this is volatile X*
    }
};

Code 3

#include<iostream>
class X {
   void fun() const volatile {
     // this is passed as hidden argument to fun().
     // Type of this is const volatile X*
    }
};

C++ Storage Class Specifier – Mutable

mutable

Storage class specifiers in C

–  Auto

–  Register

–  Static

–  Extern

–  typedef (also considered as storage class specifier in C)

  • In addition to this C++, adds one important storage class specifier whose name is Mutable.

The keyword mutable is mainly used to allow a particular data member of const object to be modified.

mutable is particularly useful if most of the members should be constant but a few need to be updateable.

When we declare a function as const, the this pointer passed to function becomes const. Adding mutable to a variable allows a const pointer to change members.

Data members declared as mutable can be modified even though they are the part of object declared as const.

You cannot use the mutable specifier with names declared as static or const, or reference.

=====================

class Customer
{
int m_tableno;
mutable int m_bill;
public:
Customer (int tableno, int bill);
void ChangeBill(int bill) { m_bill = bill ;}
//
};
int main()
{
const Customer cust( 3, 100); // cust – a constant object
cust.ChangeBill(5); // mutable data member m_bill modified
}

=====================

class Customer
{
int m_tableno;
mutable int m_bill;
public:
Customer (int tableno, int bill);
void ChangeBill(int bill) const { m_bill = bill ;}   // a const function
//
};
int main()
{
Customer cust( 3, 100);
cust.ChangeBill(5); // mutable data member m_bill is modified even though the function is const
}

=====================