EmbLogic's Blog

CHARACTER DRIVER(BLOCKING I/O)

Linux has the wait_queue_head_t data structure for implementing blocking I/O operations. A process that wants to wait for a condition can call either of the following wait_event_xxx() functions:

  • wait_event()
  • wait_event_interruptible()
  • wait_event_timeout()
  • wait_event_interruptible_timeout()
  • wait_event_interruptible_exclusive()

The first four API’s will result in a non-exclusive wait. The last API will result in a exclusive wait.

There are some interesting facts to be noted about the corresponding wake_up_xxx() functions.

  1. The wake_up(queue) and wake_up_interruptible(queue) functions will wake up all the non exclusive processes + one exclusive process waiting on the queue and whose wait condition is satisfied.
  2. The wake_up_nr(queue, nr) and wake_up_interruptible(queue, nr) functions will wake up all the non exclusive processes + upto ‘nr’ exclusive processes waiting on the queue and whose wait conditions are satisfied.
  3. The wake_up_all(queue) and wake_up_interruptible_all(queue) functions will wake up all the non exclusive processes + all exclusive processes waiting on the queue and whose wait conditions are satisfied.

Considering that we are not interested in ‘exclusive’ wait, let us analyze following two programs:

Program 1: Using wake_up() calls without delays

example_wake_up.c is a program that implements the following functionality:

  • read() function that is blocked for data using the wait_event_interruptible() call.
  • write() function that copies some data and then calls the wake_up_interruptible() call.

In order to test this program, perform the following operations:

  • Insert the example_wake_up.ko module into the kernel using the insmod utility.
  • Create a /dev/simple_char_dev entry using the mknod utility.
  • Open a terminal and execute ‘cat /dev/simple_char_dev‘.
  • Open another terminal and execute ‘cat /dev/simple_char_dev‘.
  • Now in another terminal, execute the ‘echo “hello world for wake up testing” > /dev/simple_char_dev‘.
  • You will notice that only one of the ‘cat’ programs will get the data. The other ‘cat’ program waits for data.

Program 2: Using wake_up() calls with delay

example_wake_up_delay.c is a program that implements the following functionality:

  • read() function that is blocked for data using the wait_event_interruptible() call.
  • write() function that copies some data and then calls the wake_up_interruptible() call.
  • On wake up, the read() functions sleeps for one second before resetting the ‘wait condition’.

In order to test this program, perform the following operations:

  • Insert the example_wake_up.ko module into the kernel using the insmod utility.
  • Create a /dev/simple_char_dev entry using the mknod utility.
  • Open a terminal and execute ‘cat /dev/simple_char_dev‘.
  • Open another terminal and execute ‘cat /dev/simple_char_dev‘.
  • Now in another terminal, execute the ‘echo “hello world for wake up testing” > /dev/simple_char_dev‘.
  • You will notice that both the ‘cat’ programs will get the data.

Reason:

The above behavior is due the following facts about the wake_up() functions:

  1. The ‘cat’ program is waiting in the read() function.
  2. The ‘echo’ program provides some data and calls the wake_up() function.
  3. As a result of the wake_up() function, a sleeping process can move to executing state and can get executed before the wake_up() function returns.
  4. Without the delay, the first ‘cat’ program to wake up consumes the data and resets the condition.
  5. When the wake_up() function continues to execute, it finds that the condition is already false. Hence it does not wake up any more processes.
  6. With the delay before resetting the condition, the wake_up() function call will wake up all the processes.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>