Waiting queues are used in the Linux kernel to block or wake up a process, to synchronize access to system resources, and to implement latency functions
Wait Queue interface function Introduction:
#include <linux/wait.h>//header file contains 1. Define, initialize wait queue (point to wait queue list)
Define a wait queue header
wait_queue_head_t My_queue;
Initial a wait queue header
Init_waitqueue_head (&my_queue);
Define and initialize a wait queue header
Declare_wait_queue_head (My_queue); 2. The process of sleep operation--conditional sleep
Determines whether the current process is pushed into the wait queue by condition conditions
Wait_event (wait_queue_head_t wq, int condition);
Wait_event_interruptible/* Can be interrupted by system messages.
(wait_queue_head_t wq,int condition);
Wait_event_timeout (wait_queue_head_t wq, int
condition, long timeout);
Wait_event_interruptiblble_timeout (wait_queue_head_t Wq,
int condition, long timeout);
Parameter Wq: Indicates waiting queue header
Parameter condition: Blocking condition, False (0) then go to hibernation until wake_up and condition are true conditions to exit
Parameter timeout: Indicates the length of sleep specified (clock tick, eg. delay 2 seconds =2*hz), automatically into wake state
Sleep operation of a process--unconditional sleep
Pushes the current process into the wait queue to sleep, wake_up wake up
sleep_on (wait_queue_head_t *q);
interruptible_sleep_on (wait_queue_head_t *q);
Long Sleep_on_timeout (wait_queue_head_t *q, long timeout);
Long Interruptible_sleep_on_timeout (wait_queue_head_t *q, long timeout);
Parameter Wq: Indicates waiting queue header
Parameter timeout: Indicates that when the sleep specifies a long time, it automatically goes to wake State
3. Process Wake function
WAKE_UP (wait_queue_head_t *wq);
Wake_up_interruptible (wait_queue_head_t *wq);
Precautions:
1. Wake function and cause sleep function to pair use, if cause sleep function to use with interruptible, then wake function also use interruptible.
2. Assign the value of the condition variable in wait_event to True before using the WAKE_UP wakeup process, or the process will immediately re-enter the sleep wait Queue application instance once it is awakened:
Code instance: Application-Layer code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main ()
{
char *devname = "/dev/key1_eint";
int FD;
unsigned char key;
FD = open (Devname, O_RDWR);
while (1) {
read (fd, &key, sizeof (key));
printf ("The key =%d\n", key);
}
Close (FD);
}
Drive layer:
#include <linux/device.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux /kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include < linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/ gpio.h> #include <mach/regs-gpio.h> #define EINT_DEVICE_ID 1 #define DRIVER_NAME "Key1_eint" #define ERR ( msg) PRINTK (kern_err "%s:" msg "\ n", driver_name) #define __DEBUG (FMT, arg ...) PRINTK (Kern_debug fmt, # #arg) #define GPH3CON (unsigned long) (s5pv210_gph3_base+ 0x00) #define GPH3DAT (unsigned
Long) (s5pv210_gph3_base + 0x04) #define GPH2UP (unsigned long) (s5pv210_gph2_base + 0x08) static int major = 0;
static int minor = 0;
struct class *key_class;
static struct device *key_device;
/* Defines the wait queue header, which belongs to the driver */static wait_queue_head_t wait_queue;
static unsigned char key; Irqreturn_t Buttons_interrUPT (int irq, void *dev_id) {key = (unsigned int) dev_id; Wake_up_interruptible (&wait_queue);
Wake wait queue return irq_handled;
static void Key_io_port_init (void) {unsigned long reg_val;
Reg_val = Readl (Gph3con); Reg_val &= ~ (0x0f<<0) |
(0x0f<<4)); Reg_val |= (0x01<<0) |
(0x01<<4));
Writel (Reg_val, Gph3con);
Reg_val = Readl (Gph3dat); Reg_val &= ~ (0x01<<0) |
(0x01<<1));
Writel (Reg_val, Gph3dat);
Reg_val = Readl (gph2up);
Reg_val &= ~ (0x03<<8);
Reg_val |= 0x02<<8;
Writel (Reg_val, gph2up);
Static ssize_t key_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) {int key_num;
int Cpy_len;
int retval;
/* The function body defines the struct wait_queue struct variable and adds the current process * to the queue to sleep (wait_queue_head_t is the head of the waiting queue list, struct * wait_queue records the linked list node information).
INTERRUPTIBLE_SLEEP_ON (&wait_queue); Key_num = key;
Read key value Cpy_len = min (sizeof (key_num), count);
retval = Copy_to_user (buf, &key_num, Cpy_len); RetUrn (cpy_len-retval); }/* Driver Operation structure/static struct file_operations Key_fops = {. Owner = This_module,. Read = Key_read,}
;
static int __init key_eint_init (void) {int retval;
Key_io_port_init (); Init_waitqueue_head (&wait_queue);
Initialize Wait queue header retval = Set_irq_type (Irq_eint (), irq_type_edge_falling);
if (retval) {err ("irq_eint20 set IRQ type failed");
Goto error;
} retval = Request_irq (irq_eint), Buttons_interrupt, irqf_disabled, "KEY1", (void *) eint_device_id);
if (retval) {err ("request eint20 failed");
Goto error;
} major = Register_chrdev (major, Driver_name, &key_fops);
if (Major < 0) {err ("Register char Device Fail");
retval = major;
Goto Error_register;
} key_class=class_create (This_module,driver_name);
if (Is_err (Key_class)) {ERR ("class Create failed!");
retval = Ptr_err (Key_class);
Goto Error_class;
} key_device=device_create (Key_class,null, Mkdev (major, minor), null,driver_name); if (is_err(Key_device))
{ERR ("Device Create failed!");
retval = Ptr_err (Key_device);
Goto Error_device; } __debug ("Register Mydriver ok!
Major =%d\n ", Major);
return 0;
Error_device:class_destroy (Key_class);
Error_class:unregister_chrdev (Major, Driver_name);
ERROR_REGISTER:FREE_IRQ (Irq_eint), (void *) eint_device_id);
Error:return retval;
} static void __exit key_eint_exit (void) {FREE_IRQ (irq_eint), (void *) eint_device_id);
Unregister_chrdev (Major, Driver_name);
Device_destroy (Key_class,mkdev (major, minor));
Class_destroy (Key_class);
Return
} module_init (Key_eint_init);
Module_exit (Key_eint_exit);
Module_license ("GPL"); Module_author ("Eric");