Linux-wait_queue/work_queue
First, we have to understand that all the processes in Linux are managed by the task_struct structure. A TASK_STRUCT structure is assigned when the process is generated, and the process is then managed through this structure. The TASK_STRUCT structure exists in a flat address space, and at any time the Linux kernel can refer to all management information for all processes. The kernel stack is also located in the flat address space. (flat means "independent continuous intervals")
The following are the main members of the tesk_struct:
struct Task_struct {
struct files_struct* files; File descriptor
struct signal_struct* sig; Signal control Signal Handler
struct mm_struct* mm; Memory Management Module
Long Stat //process state
struct List_head runlist; Used to join the run queue
Long priority; Basic priority
Long counter; Change priority
Char comm[]; Command name
struct Thread_struct TSS; Context Save Field
...
};
All we need to know now is the state in it, which has the following States:
Status description
Task_running execution Possible status
Task_interruptible waiting status. Acceptable signal
Task_uninterruptible waiting status. Can't accept the signal.
Task_zombie Zombie State. The status after exit
task_stopped Delay State
Task_stace Tracking Status
I. Waiting queues
The use of waiting queues is divided into the following two parts:
(1) In order for the current process to sleep in a waiting queue, you need to call the Wait_event function (or some equivalent function), and the process adds sleep, releasing control to the scheduler.
(2) At another point in the kernel, the WAKE_UP function (or an equivalent function) must be invoked to wake up the sleep process in the waiting queue. I. 1. Important STRUCTURAL bodies:
1. Waiting queue
struct __wait_queue {
unsigned int flags;
#define Wq_flag_exclusive 0x01
void *private;
wait_queue_func_t func;
struct List_head task_list;
};
typedef struct __WAIT_QUEUE wait_queue_t;
2. Waiting Queue Header
struct __wait_queue_head {
spinlock_t lock;
struct List_head task_list;
};
typedef struct __WAIT_QUEUE_HEAD wait_queue_head_t;
I. 2. Define, initialize wait queue headers and wait queues
1, struct wait_queue_head_t wq; /* Global variable * *
Declare_wait_queue_head (Wq);
2,/* Static declaration and initialization of a wait_queue_t waiting queue * *
#define DEFINE_WAIT_FUNC (name, function) \
wait_queue_t name = {\
. private = Current, \
. Func = function, \
. Task_list = List_head_init ((name). task_list), \
}
#define DEFINE_WAIT (name) define_wait_func (name, autoremove_wake_function)
/* Dynamic allocation of a wait_queue_t instance * *
Init_waitqueue_entry static inline void (wait_queue_t *q, struct task_struct)
98 {
q->flags = 0;
Q->private = p;
Q->func = default_wake_function;
102}
I. 3. Process Sleep
Includes two levels, the first level is to add a wait queue (wait_queue_t) (usually a process) to the wait queue (wait_queue_head_t) list. The second level is to put the current process into sleep.
1, the process is added to a wait queue.
Kernel/wait.c
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);
Where Add_wait_queue joins the wait queue to the tail of the waiting queue list (default) and sets the FLAG flag ~wq_flag_exclusive.
void Add_wait_queue (wait_queue_head_t *q, wait_queue_t *wait)
23 {
unsigned long flags;
25
Wait->flags &= ~wq_flag_exclusive;
Spin_lock_irqsave (&q->lock, flags);
__add_wait_queue (q, wait); /*list_add (&new->task_list, &head->task_list);
Spin_unlock_irqrestore (&q->lock, flags);
30}
Adding a wait queue to the wait queue list another method is prepare_to_wait. In addition to the parameters required for Add_wait_queue, the state of the process is required.
void Prepare_to_wait (wait_queue_head_t *q, wait_queue_t *wait, int state);
void Prepare_to_wait_exclusive (wait_queue_head_t *q, wait_queue_t *wait, int state);
void Finish_wait (wait_queue_head_t *q, wait_queue_t *wait);
void Abort_exclusive_wait (wait_queue_head_t *q, wait_queue_t *wait,
unsigned int mode, void *key);
Prepare_to_wait (wait_queue_head_t *q, wait_queue_t *wait, int state)
69 {
unsigned long flags;
71
Wait->flags &= ~wq_flag_exclusive;
Spin_lock_irqsave (&q->lock, flags);
if (List_empty (&wait->task_list))
__add_wait_queue (q, wait);