异步通知

发布时间:2024-07-31  

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

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

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

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

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

   

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

   

实例

driver

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
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_initn");
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
2 #include
3 #include
4 #include
5 #include
6 #include
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%xn", 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! %dn", 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 }

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>