A blocking operation is when a device operation is performed, and if no resources are available, the process is suspended until the operational conditions are met . The suspended process goes into hibernation and is removed from the running queue of the scheduler, knowing that the waiting conditions are met. A non-blocking process does not hang when it is unable to operate the device, it either discards or keeps querying until it can be manipulated.
In Linux drivers, you can use the wait queue (wait queues) to wake up a blocking process.
1. Wait for the queue header
A wait queue has a "Wait queue header" to manage, wait_queue_head_t defined in Linux/wait.h, implemented in KERNEL/WAIT.C.
struct __wait_queue_head { spinlock_t lock; struct List_head struct __wait_queue_head wait_queue_head_t;
Declare_wait_queue_head (name); // Static wait_queue_head_t my_queue;init_waitqueue_head (&my_queue);
2. Defining the wait queue
typedefstruct__wait_queue wait_queue_t;typedefint(*wait_queue_func_t) (wait_queue_t *wait, unsigned mode,intFlagsvoid*key);intDefault_wake_function (wait_queue_t *wait, unsigned mode,intFlagsvoid*key);struct__wait_queue {unsignedintflags;#defineWq_flag_exclusive 0x01void*Private; wait_queue_func_t func; structlist_head task_list;};
Declare_wait_queue (name, tsk);
This macro is used to define and initialize a wait queue named name.
#define __waitqueue_initializer (name, tsk) { \ . Private = tsk, . Func = default_wake_function, . task_list = {null, NULL}} #define declare_waitqueue (name, tsk) \ = __waitqueue_initializer (name, tsk)
3. Removing and adding the wait queue
extern void add_wait_queue (wait_queue_head_t *q, wait_queue_t *wait); extern void add_wait_queue_exclusive (wait_queue_head_t *q, wait_queue_t *wait); extern void remove_wait_queue (wait_queue_head_t *q, wait_queue_t *wait);
4. Wait for the event
#define #define #define wait_event_interruptible (Wq, condition)#define
/**/
Waits for the first parameter, Wq, to be awakened as the waiting queue header , and the 2nd parameter condition must be satisfied, otherwise it continues to block.
Timeout is in jiffy units.
5. Wake-up queue
void wake_up (wait_queue_head_t *queue); void wake_up_interruptible (wait_queue_head_t *queue);
6. Sleep on the waiting queue
extern void sleep_on (wait_queue_head_t *q); extern Long Long timeout); extern void interruptible_sleep_on (wait_queue_head_t *q); extern Long long timeout);
Adds the current process to the wait queue, thus sleeping on the waiting queue. When the time-out occurs, the process is awakened.
Reference:
1. Waiting queue
Linux kernel blocking IO