字符设备驱动程序之异步通知

异步通知:

     驱动程序的所谓异步通知,指的是应用程序不是主动对驱动程序进行操作,而是驱动程序查询到有事件发生或者有数据发生变化的时候通知应用程序。角色发生了变化,应用程序由主动改为被动执行。

比如按键驱动:

1、要不断进行查询引脚状态的,CPU资源消耗非常的大;

2、有中断操作的,发生按键事件后采取执行相关事件处理函数,需要应用程序不断执行read函数,使得不能去干其它事情;

3、poll机制,改善了中断方式操作,在应用程序上当没有事件发生时,会跳去read函数继续执行其它的任务,知道有事件发生才返回;

4、异步通知,也即我们本次讲的,让驱动程序自己告诉我们事件发生,我们采取执行。

 

目标:按下按键时,驱动程序通知应用程序。(以前是应用程序主动读取按键值)
1,应用程序中要注册“信号处理函数”。因为通知它做什么事情,这要一个函数来做。
2,谁发:是驱动程序发送信号。
3,发给谁:信号发送给应用程序。应用程序要告诉驱动程序它自已的 PID,
4,如何发:驱动程序中调用某个函数(kill_fasync())
 

操作步骤

在驱动程序里:

1.首先声明一个“fasync_struct”结构变量
例:static struct fasync_struct *button_async;

2.初始化button_async结构变量

  - 在file_operations多定义一个成员函数 例:.fasync     =  fifth_drv_fasync

  - 定义这个函数

static int fifth_drv_fasync (int fd, struct file *filp, int on)
{
    return fasync_helper (fd, filp, on, &button_async);
}

所以显然是应用程序要调用“.fasync”来设置那个“发给谁”
 

3.在中断函数中调用kill_fasync (&button_async, SIGIO, POLL_IN)来发送信号

 有按键按下了就发一个信号给应用程序。其中要定义一个结构,取名为“button_async” .
以上便可以发送信号出去了

 

在应用程序里:

1.定义信号signal(SIGIO, my_signal_fun);

定义my_signal_fun(int signum)// 驱动程序发送信号后,应用程序接收到信号做相应处理 读取硬件数据 

2. fcntl(fd, F_SETOWN, getpid()); // 告诉内核,发给谁

  应用程序会调用“fcntl()”这个函数,把进程的 PID 号告诉给驱动程序。

3. Oflags = fcntl(fd, F_GETFL); //应用程序通过“F_GETFL”读出“flags”

4. fcntl(fd, F_SETFL, Oflags | FASYNC);

改变 fasync 标记,最终会调用到驱动的 faync > fasync_helpe()r:初始化 fasync_struct
 

如上面“fcntl(fd, F_SETFL, Oflags | FASYNC);”接口被调用时,在函数中的“fasync_helper()”就会被调用
 

static int fifth_drv_fasync (int fd, struct file *filp, int on) //  初始化 “button_async

{

    return fasync_helper (fd, filp, on, &button_async);

}


 

 

 

你可能感兴趣的:(linux字符驱动)