异步通知

发布时间: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 }

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

相关文章

    Linux设备驱动中的异步通知与异步I/O;异步通知概念: 异步通知的意识是,一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件上的“中断”概念,比较......
    Linux驱动之异步通知的应用;前面的按键驱动方式都是应用程序通过主动查询的方式获得按键值的: 1、查询方式 2、中断方式 3、poll机制 下面介绍第四种按键驱动的方式 4、异步通知......
    过回调函数处理这个调用。 典型的异步编程模型比如Node.js 举个通俗的例子:你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下',然后开始查啊查,等查好了(可能是5秒......
    就保证了起始位开始处一定会有一个下跳沿,由此就可以标志一个字符传输的起始。而根据起始位和停止位也就很容易的实现了字符的界定和同步。 显然,采用异步通信时,发送......
    80C51单片机串行通信;一、串行通信基础知识 异步通信和同步通信计算机的数据传输共有两种方式:并行数据传输和串行数据传输。并行数据传输的特点:是各数据位同时传输,传输速度快,效率高。但并......
    底等优点,缺点是速度慢。串行通信分为两种类型:同步通信方式和异步通信方式。 但一般多用异步通信方式,主要因为接受和发送的时钟是可以独立的这样有利于增加发送与接收的灵活性。异步通......
    底等优点,缺点是速度慢。串行通信分为两种类型:同步通信方式和异步通信方式。     但一般多用异步通信方式,主要因为接受和发送的时钟是可以独立的这样有利于增加发送与接收的灵活性。异步通......
    接口。 在同步通讯中,收发设备上方会使用一根信号线传输信号,在时钟信号的驱动下双方进行协调,同步数据。例如,通讯中通常双方会统一规定在时钟信号的上升沿或者下降沿对数据线进行采样。 异步通信 不带时钟同步......
    下图: 串行通信的方式包括异步通信和同步通信。 异步通信 它用一个起始位表示字符的开始,用停止位表示字符的结束。其每帧的格式如下: 在一帧格式中,先是一个起始位0,然后是8个数据位,规定......
    称。 1.串行接口的基本通信方式 串行接口的有异步和同步两种基本通信方式。异步通信采用用异步传送格式,如图1 所示。数据发送和接收均将起始位和停止位作为开始和结束的标志。在异步通信中,起始位占用一位(低电......

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

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

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

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

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

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

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