zoukankan      html  css  js  c++  java
  • 字符驱动程序之——异步通知

    为了使设备支持异步通知机制,驱动程序中涉及以下 3 项工作:
    1. 支持 F_SETOWN 命令,能在这个控制命令处理中设置 filp->f_owner 为对应进程 ID
    不过此项工作已由内核完成,设备驱动无须处理。
    2. 支持 F_SETFL 命令的处理,每当 FASYNC 标志改变时,驱动程序中的 fasync()函数将得以
    执行。
    驱动中应该实现 fasync()函数。
    3. 在设备资源可获得时,调用 kill_fasync()函数激发相应的信号
    应用程序:
    fcntl(fd, F_SETOWN, getpid()); // 告诉内核,发给谁
    应用程序会调用“fcntl()”这个函数,把进程的 PID 号告诉给驱动程序。
    应用程序还要通过“F_GETFL”读出“flags”,在 flags 上置上“FASYNC”位。
    Oflags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, Oflags | FASYNC); // 改变 fasync 标记, 最终会调用到驱动的 faync >
    fasync_helper:初始化/释放 fasync_struct

    字符驱动之前的方式:
    一,应用程序主动的去查询或 read
    1.查询方式:很占资源。
    2.中断机制:虽然有休眠,但在没有按键按下时 read()会一直等待,永远不会返回。
    3.poll 机制:指定超时时间。
    以上都是“应用程序”主动去读或查询。

    今天学习的方式:
    二,异步通知:
    有按键按下了,驱动程序来提醒(触发)“应用程序”去读键值。用“signal
    进程之间发信号:
    kill -9 pid
    kill 是信号发送者,
    pid 具体进程是信号接收者。
    信号值是“9
    “信号”与“中断”差不多。注册中断处理函数时是用“request_irq(中断号,处理函数)”。
    信号也是有一个“信号”和“处理函数”。
    参数是“信号的值”,和要挂接的“信号处理函数”。

    测试信号应用程序:

    kill -9 pid9 这个信号处理函数就是让这个进程退出来。
    1,先注册“信号处理函数”。
    2,发送信号。
    ①,谁来发信号。
    ②,发给谁。
    ③,怎么发

    三,异步通知功能的驱动函数的应用程序:
    目标:按下按键时,驱动程序通知应用程序。(以前是应用程序主动读取按键值)
    1,应用程序中要注册“信号处理函数”。因为通知它做什么事情,这要一个函数来做。
    2,谁发:是驱动程序发送信号。
    3,发给谁:信号发送给应用程序。应用程序要告诉驱动程序它自已的 PID
    4,如何发:驱动程序中调用某个函数(kill_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>
    
    
    /* fifthdrvtest 
      */
    int fd;
    
    void my_signal_fun(int signum)
    {
        unsigned char key_val;
        read(fd, &key_val, 1);//执行了这个read的前提是有按键按下了
        printf("key_val: 0x%x
    ", 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!
    ");
        }
    
        fcntl(fd, F_SETOWN, getpid());//告诉内核信号发送给谁?通过PID编号体现
        
        Oflags = fcntl(fd, F_GETFL); //应用程序读出标志位Oflags
        
        fcntl(fd, F_SETFL, Oflags | FASYNC);//并把标志位加上异步信息,应用程序调用该函数会触发驱动层去调用我们编写的fifth_drv_fasync函数
    
    
        while (1)
        {
            sleep(1000);
        }
        
        return 0;
    }
  • 相关阅读:
    POJ 3258 (NOIP2015 D2T1跳石头)
    POJ 3122 二分
    POJ 3104 二分
    POJ 1995 快速幂
    409. Longest Palindrome
    389. Find the Difference
    381. Insert Delete GetRandom O(1)
    380. Insert Delete GetRandom O(1)
    355. Design Twitter
    347. Top K Frequent Elements (sort map)
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/8975707.html
Copyright © 2011-2022 走看看