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

异步通知:linux

     驱动程序的所谓异步通知,就是说并非应用程序来对驱动程序操做的,而是驱动程序查询到有事件发生或者有数据发生变化的时候通知应用程序。角色发生了变化,应用程序由主动改成被动执行。异步

好比按键驱动:async

一、有不断进行查询引脚状态的,CPU资源消耗很是的打;函数

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

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

四、异步通知,也即咱们本次讲的,让驱动程序本身告诉咱们事件发生,咱们采起执行。blog

为了使设备支持异步通知机制,驱动程序中涉及如下3项工做:
1. 支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID。
不过此项工做已由内核完成,设备驱动无须处理。
2. 支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。
驱动中应该实现fasync()函数。

3. 在设备资源可得到时,调用kill_fasync()函数激发相应的信号进程


应用程序:
fcntl(fd, F_SETOWN, getpid()); // 告诉内核,发给谁事件

Oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, Oflags | FASYNC); // 改变fasync标记,最终会调用到驱动的faync > fasync_helper:初始化/释放fasync_struct资源

相关参考代码以下:

fifth_drv.c


#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>


/* fifthdrvtest
*/
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);

fd = open("/dev/buttons", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}

/* 接收驱动程序消息 */
fcntl(fd, F_SETOWN, getpid());

Oflags = fcntl(fd, F_GETFL);

fcntl(fd, F_SETFL, Oflags | FASYNC);


while (1)
{
sleep(1000);
}

return 0;
}

 

Makefile

KERN_DIR = /work/system/linux-2.6.22.6

all:
    make -C $(KERN_DIR) M=`pwd` modules 

clean:
    make -C $(KERN_DIR) M=`pwd` modules clean
    rm -rf modules.order

obj-m    += fifth_drv.o

 

fifthdrvtest.c

#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>


/* fifthdrvtest 
  */
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);
    
    fd = open("/dev/buttons", O_RDWR);
    if (fd < 0)
    {
        printf("can't open!\n");
    }

    fcntl(fd, F_SETOWN, getpid());
    
    Oflags = fcntl(fd, F_GETFL); 
    
    fcntl(fd, F_SETFL, Oflags | FASYNC);


    while (1)
    {
        sleep(1000);
    }
    
    return 0;
}
相关文章
相关标签/搜索