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;
    }
  • 相关阅读:
    ASP.NET MVC Core的ViewComponent
    docker学习笔记
    C#调用RabbitMQ实现消息队列(转)
    在Gerrit中修改project.config
    Linux设备模型:6、Bus
    Linux设备模型:5、device和device driver
    Linux设备模型:4、sysfs
    Linux设备模型:3、Uevent
    Linux设备模型:2、基本对象 Kobject、Kset、Ktype
    Linux设备模型:1、设计思想
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/8975707.html
Copyright © 2011-2022 走看看