异步通知

轮询:应用程序不断read;驱动程序不断read,占用大量的cpu资源。

中断:应用程序阻塞在read;驱动程序休眠,只有发生中断时,驱动程序唤醒,读取键值,返回给应用程序;应用程序执行下一步。

poll:应用程序在一定的时间内(用户定义),不断检测用户设置的flag,超时执行下一步;驱动程序在发生中断时,标记用户设置的flag。

async:应用程序不会阻塞,不影响当前进程的其他任务的执行,只有在接收到驱动程序发送过来的信号,才去读取键值;在发生中断时,驱动程序发送信

号给应用程序(通过进程号),通知应用程序读取键值。

   

当按键中断发生时,发送信号给应用程序,应用程序再去读取键值,避免进程阻塞在read()函数,提高系统运用效率。

   

实例

driver

1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/fs.h>
4 #include <linux/init.h>
5 #include <linux/delay.h>
6 #include <linux/irq.h>
7 #include <asm/uaccess.h>
8 #include <asm/irq.h>
9 #include <asm/io.h>
10 #include <asm/arch/regs-gpio.h>
11 #include <asm/hardware.h>
12
13
14 static int major;
15
16 static struct class *myKey_class;
17 static struct class_device *myKey_class_dev;
18
19 volatile unsigned long *gpfcon;
20 volatile unsigned long *gpfdat;
21
22 volatile unsigned long *gpgcon;
23 volatile unsigned long *gpgdat;
24
25 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
26 static volatile int ev_press = 0;
27
28 static struct fasync_struct *button_fasyncq;
29
30 //normal:1; press:0;
31 static unsigned char keyVal = 0;
32
33 struct pin_desc {
34         unsigned int pin;
35         unsigned int key_val;
36 };
37
38 /*
39 * 按键按下键值为0x01,...; 松开键值为0x81,...
40 */
41 struct pin_desc pins_desc[3] = {
42         {S3C2410_GPF0, 0x01},
43         {S3C2410_GPF2, 0x02},        
44         {S3C2410_GPG11, 0x03},        
45 };
46
47
48 static int myKey_open(struct inode *inode, struct file *file);
49 static int myKey_close(struct inode *inode, struct file *file);
50 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
51 static int myKey_fasync(int fd, struct file *filp, int on);
52
53
54 static struct file_operations myKey_fops = {
55         .open = myKey_open,
56         .read = myKey_read,
57         .owner = THIS_MODULE,
58         .release = myKey_close,
59         .fasync = myKey_fasync,
60 };
61
62
63 static irqreturn_t handle_buttons(int irq, void *dev)
64 {
65         unsigned int kval;
66         struct pin_desc *pinDesc = dev;
67
68         kval = s3c2410_gpio_getpin(pinDesc->pin);
69         if (kval)        //松开
70         {
71                 keyVal = 0x80 | pinDesc->key_val;
72         }
73         else {                //按下
74                 keyVal = pinDesc->key_val;
75         }
76
77         //唤醒休眠进程
78         ev_press = 1;        //中断发生标志
79         wake_up_interruptible(&button_waitq);
80
81         kill_fasync(&button_fasyncq, SIGIO, POLL_IN);
82
83         return IRQ_RETVAL(IRQ_HANDLED);
84 }
85
86
87 static int myKey_open(struct inode *inode, struct file *file)
88 {
89         request_irq(IRQ_EINT0, handle_buttons, IRQT_BOTHEDGE, "S2", &pins_desc[0]);
90         request_irq(IRQ_EINT2, handle_buttons, IRQT_BOTHEDGE, "S3", &pins_desc[1]);
91         request_irq(IRQ_EINT19, handle_buttons, IRQT_BOTHEDGE, "S5", &pins_desc[2]);
92         
93         return 0;
94 }
95
96
97 static int myKey_close(struct inode *inode, struct file *file)
98 {
99         free_irq(IRQ_EINT0, &pins_desc[0]);
100         free_irq(IRQ_EINT2, &pins_desc[1]);
101         free_irq(IRQ_EINT19, &pins_desc[2]);
102
103         return 0;
104 }
105
106 int myKey_fasync(int fd, struct file *filp, int on)
107 {        
108         printk("driver: fasync_init ");
109         fasync_helper(fd, filp, on, &button_fasyncq);
110
111         return 0;
112 }
113
114 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
115 {
116         //无中断进入休眠
117         wait_event_interruptible(button_waitq, ev_press);
118
119         ev_press = 0;        //清除中断发生标志
120         copy_to_user(buf, &keyVal, 1);
121         return 0;
122 }
123
124 static int __init myKey_init(void)
125 {
126         /* 物理地址映射成虚拟地址 */
127         gpfcon = (volatile unsigned long*)ioremap(0x56000050, 16);
128         gpfdat = gpfcon + 1;
129
130         gpgcon = (volatile unsigned long*)ioremap(0x56000060, 16);
131         gpgdat = gpgcon + 1;
132
133         major = register_chrdev(0, "myKey", &myKey_fops);
134         
135         myKey_class = class_create(THIS_MODULE, "myKeyclass");
136         myKey_class_dev = class_device_create(myKey_class, NULL, MKDEV(major, 0), NULL, "myKey");
137
138         return 0;
139 }
140
141 static void __exit myKey_exit(void)
142 {
143         /* 释放虚拟地址映射 */
144         iounmap(0x56000050);
145         iounmap(0x56000060);
146
147         unregister_chrdev(major, "myKey");
148
149         class_device_unregister(myKey_class_dev);
150         class_destroy(myKey_class);
151         return;
152 }
153
154 module_init(myKey_init);
155 module_exit(myKey_exit);

   

   

app

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <signal.h>
6 #include <unistd.h>
7
8 int fd;
9
10 void handle_signal(int signum)
11 {
12         unsigned char keyVal;
13
14         read(fd, &keyVal, 1);
15         printf("keyVal: 0x%x ", keyVal);
16
17         return;
18 }
19
20
21 int main (void)
22 {
23         int oflag = 0;
24
25         printf("test app! ");
26
27         fd = open("/dev/myKey", O_RDWR);
28         if(fd < 0)
29         {
30                 printf("open failed! %d ", fd);
31                 return -1;
32         }
33
34         signal(SIGIO, handle_signal);
35         
36         fcntl(fd, F_SETOWN, getpid());
37         oflag = fcntl(fd, F_GETFL);
38         fcntl(fd, F_SETFL, oflag | O_ASYNC);
39         
40         while(1)
41         {
42                 sleep(5);
43         }
44         return 0;        
45 }

   

   

Makefile

1 KERN_DIR = /work/system/linux-2.6.22.6
2
3 all:
4         make -C $(KERN_DIR) M=`pwd` modules
5

6 clean:
7         make -C $(KERN_DIR) M=`pwd` modules clean
8
        rm -rf modules.order

9
10 obj-m += myKey_signal.o

原文地址:https://www.cnblogs.com/lilto/p/11878548.html