异步通知
①轮询:应用程序不断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\n");
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\n", keyVal);
16
17 return;
18 }
19
20
21 int main (void)
22 {
23 int oflag = 0;
24
25 printf("test app!\n");
26
27 fd = open("/dev/myKey", O_RDWR);
28 if(fd < 0)
29 {
30 printf("open failed! %d\n", 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