字符设备驱动程序之异步通知
2014-09-21 20:48
176 查看
前面已经讲了3种读取键值的方法,分别是:① 查询方式,缺点--耗资源;② 中断方式,缺点--read()方法会一直等待按键按下,否则不会返回;③ poll机制,优点---在指定时间内返回。
它们都有一个共同点,就是---都是应用程序主动去读取键值,那有没有一种方法是当按键按下时驱动主动提醒应用程序去读取键值呢?
答案是肯定的,这种方式就叫做异步通知,它通过发信号来实现。
扩展知识:进程间如何发送信号?
先用一个小例子来演示一下:
可以用命令:#kill -信号 应用程序PID
用#ps 命令可以看到这个应用程序的PID是833,所以执行:# kill -10 833 就会打印程序中设定的字符串。
这节要达到的目标---按下按键时,驱动程序通知应用程序读取按键值。
问1: 怎么实现这个基于信号处理的驱动呢?
答:要确定并完成以下几点,
① 应用程序---注册信号处理函数;
② 谁来发信号?驱动发
③ 信号发给谁?发给应用程序,应用程序要告诉驱动它的PID
④ 怎么发出信号?用 kill_fasync()
下面,我们就从代码上来看看这个驱动怎么写》
1. 定义一个 fasync_struct 结构
static struct fasync_struct *button_async;
2. 定义一个函数来初始化fasync_struct 结构
3. 将 fifth_drv_fasync 加入到 file_operations 结构
下面看看应用测试程序怎么写:
为了使设备支持异步通知机制,驱动程序中涉及以下3项工作:
1. 支持 F_SETOWN命令,能在这个控制命令处理中设置 flip->f_owner 为对应进程ID。
不过此项工作已由内核完成,设备驱动无须处理。
2. 支持 F_SETGL 命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。
所以 在应用程序中要执行这三步:
fcntl(fd,F_SETOWN,pid);
Oflags=fcntl(fd,F_GETFL);
fcntl(fd,F_SETGL,oflags | FASYNC); //当执行这步时,驱动中 file_operations .fasync 就执行。
应用程序代码:
当不知道某个系统函数怎么用的时,如应包含什么头文件等,可以在linux中执行命令:#man 函数名 查看,就会看到它应包含什么头文件。
它们都有一个共同点,就是---都是应用程序主动去读取键值,那有没有一种方法是当按键按下时驱动主动提醒应用程序去读取键值呢?
答案是肯定的,这种方式就叫做异步通知,它通过发信号来实现。
扩展知识:进程间如何发送信号?
先用一个小例子来演示一下:
#include <stdio.h> #include <signal.h> void my_signal_fun(int signum){ static int cnt=0; printf("signal = %d,%d times\n",signum,cnt); } int main(int argc,char **argv){ signal(SIGUSR1,my_signal_fun); while(1){ sleep(1000); } return 0; }然后,编译运行这个应用程序。那怎么给这个应用程序发信号呢?
可以用命令:#kill -信号 应用程序PID
用#ps 命令可以看到这个应用程序的PID是833,所以执行:# kill -10 833 就会打印程序中设定的字符串。
这节要达到的目标---按下按键时,驱动程序通知应用程序读取按键值。
问1: 怎么实现这个基于信号处理的驱动呢?
答:要确定并完成以下几点,
① 应用程序---注册信号处理函数;
② 谁来发信号?驱动发
③ 信号发给谁?发给应用程序,应用程序要告诉驱动它的PID
④ 怎么发出信号?用 kill_fasync()
下面,我们就从代码上来看看这个驱动怎么写》
1. 定义一个 fasync_struct 结构
static struct fasync_struct *button_async;
2. 定义一个函数来初始化fasync_struct 结构
static int fifth_drv_fasync (int fd, struct file *filp, int on) { printk("driver: fifth_drv_fasync\n"); return fasync_helper (fd, filp, on, &button_async); }这个函数在什么时候执行呢,当应用程序调用 .fasync 时执行。
3. 将 fifth_drv_fasync 加入到 file_operations 结构
static struct file_operations sencod_drv_fops = { .owner = THIS_MODULE, .open = fifth_drv_open, .read = fifth_drv_read, .release = fifth_drv_close, .poll = fifth_drv_poll, .fasync = fifth_drv_fasync, };4. 在中断处理函数中 发送信号
static irqreturn_t buttons_irq(int irq, void *dev_id) { struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } ev_press = 1; /* 表示中断发生了 */ wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ kill_fasync (&button_async, SIGIO, POLL_IN); //发送这个信号 return IRQ_RETVAL(IRQ_HANDLED); }只要改以上几步,一个简单的驱动就可以用了。
下面看看应用测试程序怎么写:
为了使设备支持异步通知机制,驱动程序中涉及以下3项工作:
1. 支持 F_SETOWN命令,能在这个控制命令处理中设置 flip->f_owner 为对应进程ID。
不过此项工作已由内核完成,设备驱动无须处理。
2. 支持 F_SETGL 命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。
所以 在应用程序中要执行这三步:
fcntl(fd,F_SETOWN,pid);
Oflags=fcntl(fd,F_GETFL);
fcntl(fd,F_SETGL,oflags | FASYNC); //当执行这步时,驱动中 file_operations .fasync 就执行。
应用程序代码:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <poll.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> int fd; void my_signal_fun(int signum) { unsigned char key_val; read(fd, &key_val, 1); printf("key_val: 0x%x\n", key_val); } int main(int argc, char **argv) { unsigned char key_val; int ret; int Oflags; signal(SIGIO, my_signal_fun); //一般用 SIGIO信号,表示IO口有数据 fd = open("/dev/buttons", O_RDWR); if (fd < 0) { printf("can't open!\n"); } fcntl(fd, F_SETOWN, getpid()); //把 PID告诉内核 Oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, Oflags | FASYNC); //改变fasyc标识,最终会调用到faync-->fasync_helper while (1) { sleep(1000); } return 0; }小知识:
当不知道某个系统函数怎么用的时,如应包含什么头文件等,可以在linux中执行命令:#man 函数名 查看,就会看到它应包含什么头文件。
相关文章推荐
- 字符设备驱动程序之异步通知
- 字符设备驱动程序——异步通知
- 字符设备驱动程序之异步通知
- Linux设备驱动程序学习(6)-高级字符驱动程序操作[(4)异步通知fasync]
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- 韦东山驱动视频笔记——4.字符设备驱动程序之异步通知
- Linux设备驱动之六----异步通知的驱动程序
- Linux字符设备驱动之异步通知
- Linux的异步通知字符设备驱动
- linux字符设备驱动-异步通知笔记
- Linux字符设备驱动之异步通知
- 字符设备驱动第八课----异步通知(信号驱动IO)
- 字符设备驱动学习笔记----异步通知机制
- 字符设备驱动笔记——异步通知(八)
- 【Linux设备驱动程序(第三版)】----异步通知
- 字符设备驱动-异步通知
- 高级字符驱动程序操作之异步通知IO(实践篇)基于内核2.6.35-30
- 【Linux 驱动】第六章 高级字符驱动程序操作----异步通知
- Linux设备驱动程序第三版学习(8)- 高级字符驱动程序操作(续3)- 异步通知 .
- Linux设备驱动程序第三版学习(8)- 高级字符驱动程序操作(续3)- 异步通知