异步信号通知: 当有数据到时候,驱动会发送信号(SIGIO)给应用,就可以异步去读写数据,不用主动去读写。之前的几种方式都需要应用去主动检测状态来确认是否有事件发生。
一. 异步信号的应用方法
a,应用--处理信号,主要是读写数据
void catch_signale(int signo)
{
if(signo == SIGIO)
{
printf("we got sigal SIGIO");
// 读取数据
read(fd, &event, sizeof(struct key_event));
if(event.code == KEY_ENTER)
{
if(event.value)
{
printf("APP__ key enter pressed\n");
}else
{
printf("APP__ key enter up\n");
}
}
}
}
// 1,设置信号处理方法
signal(SIGIO,catch_signale);
// 2,将当前进程设置成SIGIO的属主进程
fcntl(fd, F_SETOWN, getpid());
// 3,将io模式设置成异步模式
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC );
b,驱动--发送信号
1,需要和进程进行关联--记录信号该发送给谁
实现一个fasync的接口
int key_drv_fasync(int fd, struct file *filp, int on)
{
//只需要调用一个函数记录信号该发送给谁
return fasync_helper(fd, filp, on, &key_dev->faysnc);
}
2,在某个特定的时候去发送信号,在有数据的时候
//发送信号
kill_fasync(&key_dev->faysnc, SIGIO, POLLIN);
二.代码实例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
struct key_event{
int code; // 表示按键的类型: home, esc, Q,W,E,R,T, ENTER
int value; // 表示按下还是抬起 1 / 0
};
#define KEY_ENTER 28
static int fd;
static struct key_event event;
void catch_signale(int signo)
{
if(signo == SIGIO)
{
printf("we got sigal SIGIO\n");
// 读取数据
read(fd, &event, sizeof(struct key_event));
if(event.code == KEY_ENTER)
{
if(event.value)
{
printf("APP__ key enter pressed\n");
}else
{
printf("APP__ key enter up\n");
}
}
}
}
int main(int argc, char *argv[])
{
int ret;
fd = open("/dev/key0", O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
// 1,设置信号处理方法
signal(SIGIO,catch_signale);
// 2,将当前进程设置成SIGIO的属主进程
fcntl(fd, F_SETOWN, getpid());
// 3,将io模式设置成异步模式
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | FASYNC );
while(1)
{
// 可以做其他的事情
printf("I am waiting......\n");
sleep(1);
}
close(fd);
return 0;
}
应用中直接设置好处理好函数之后,就可以做其他事情去了,不用再一直等待检测。