zoukankan      html  css  js  c++  java
  • 5、异步通知机制

    异步通知,的确是一种很好处理机制,熟练掌握这种手段,对我们写高质量的应用程序很有帮助。下面说说对它的理解:

    异步通知,就是让驱动去告诉应用,底层硬件发生了什么事,而不是应用主动地去查询驱动,这对系统的性能有一个很大的提升。

    首先,在驱动中

    内核首先定义一个结构体struct fasync_struct,这个结构体用来存放对应设备文件的信息(如fd, filp)并交给内核来管理。一但收到信号,内核就会在这个所谓的异步队列头找到相应的文件(fd),并在filp->owner中找到对应的进程PID,这样就确定了向谁发。不过,此时fd, filp都还不确定,这就需要借助于fasync_helper(fd, filp, mode, &dev->async_queue),将fd,filp和定义的结构体传给内核,这样就完成了fd、filp、结构体三者的衔接。

     int test_fasync (int fd, struct file *filp, int mode) ,在后者中完成对fasync_helper的调用,从而完成对异步队列的填充。

    从这个过程中,也可以看到,哪个进程完成对ops成员fasync成员的调用,就会把fd、filp传给异步队列,kill_fasync发出信号就会到这个进程中,这就是驱动层次的理解。

    其次,就是在应用层次

    首先,要用fcntl对此文件进行设置,

    fcntl(fd, F_SETOWN, getpid());设置接收SIGIO信号的进程组

    Oflags = fcntl(fd, F_GETFL);  得到现在文件的标志位

    fcntl(fd, F_SETFL, Oflags | FASYNC);对当前文件的标志位加上一个FASYNC属性,每当FASYNC标志改变时,驱动程序中的 fasync()函数将得以执行。

    然后就是应用程序得到SIGIO信号后,要绑定新的操作函数

    signal(SIGIO, my_signal_fun);

    这样就完成了异步通信的过程,当驱动发送kill_fasync时就会在应用程序中调用my_signal_fun函数去处理。

    应用程序举例:

    1. //信号处理函数  
    2. void my_signal_fun(int signum)  
    3. {  
    4.     unsigned char key_val;  
    5.     read(fd, &key_val, 1);  
    6.     printf("key_val: 0x%x ", key_val);  
    7. }  
    8.   
    9. int main(int argc, char **argv)  
    10. {  
    11.     unsigned char key_val;  
    12.     int ret;  
    13.     int Oflags;  
    14.   
    15.     //在应用程序中捕捉SIGIO信号(由驱动程序发送)  
    16.     signal(SIGIO, my_signal_fun);  
    17.       
    18.     fd = open("/dev/buttons", O_RDWR);  
    19.     if (fd < 0)  
    20.     {  
    21.         printf("can't open! ");  
    22.     }  
    23.   
    24.     //将当前进程PID设置为fd文件所对应驱动程序将要发送SIGIO,SIGUSR信号进程PID  
    25.     fcntl(fd, F_SETOWN, getpid());  
    26.       
    27.     //获取fd的打开方式  
    28.     Oflags = fcntl(fd, F_GETFL);   
    29.   
    30.     //将fd的打开方式设置为FASYNC --- 即 支持异步通知  
    31.     //该行代码执行会触发 驱动程序中 file_operations->fasync 函数 ------fasync函数调用fasync_helper初始化一个fasync_struct结构体,该结构体描述了将要发送信号的进程PID (fasync_struct->fa_file->f_owner->pid)  
    32.     fcntl(fd, F_SETFL, Oflags | FASYNC);  
    33.   
    34.   
    35.     while (1)  
    36.     {  
    37.         sleep(1000);  
    38.     }  
    39.       
    40.     return 0;  
    41. }  

    驱动程序举例:

    1. static int fifth_drv_fasync (int fd, struct file *filp, int on)  
    2. {  
    3.     printk("driver: fifth_drv_fasync ");  
    4.     //初始化/释放 fasync_struct 结构体 (fasync_struct->fa_file->f_owner->pid)  
    5.     return fasync_helper (fd, filp, on, &button_async);  
    1. static irqreturn_t buttons_irq(int irq, void *dev_id)  
    2. {  
    3.     struct pin_desc * pindesc = (struct pin_desc *)dev_id;  
    4.     unsigned int pinval;  
    5.       
    6.     pinval = s3c2410_gpio_getpin(pindesc->pin);  
    7.   
    8.     if (pinval)  
    9.     {  
    10.         /* 松开 */  
    11.         key_val = 0x80 | pindesc->key_val;  
    12.     }  
    13.     else  
    14.     {  
    15.         /* 按下 */  
    16.         key_val = pindesc->key_val;  
    17.     }  
    18.   
    19.     ev_press = 1;                  /* 表示中断发生了 */  
    20.     wake_up_interruptible(&button_waitq);   /* 唤醒休眠的进程 */  
    21.       
    22.         //发送信号SIGIO信号给fasync_struct 结构体所描述的PID,触发应用程序的SIGIO信号处理函数  
    23.     kill_fasync (&button_async, SIGIO, POLL_IN);  
    24.       
    25.     return IRQ_RETVAL(IRQ_HANDLED);  
    26. }  
  • 相关阅读:
    实例属性 类属性 实例域 类域
    研究数据集
    static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
    accessor mothod mutator mothod 更改器方法 访问器方法 类的方法可以访问类的任何一个对象的私有域!
    上钻 下钻 切片 转轴 降采样
    识别会话
    Performance Tuning Using Linux Process Management Commands
    Secure Hash Algorithm 3
    grouped differently across partitions
    spark 划分stage Wide vs Narrow Dependencies 窄依赖 宽依赖 解析 作业 job stage 阶段 RDD有向无环图拆分 任务 Task 网络传输和计算开销 任务集 taskset
  • 原文地址:https://www.cnblogs.com/liusiluandzhangkun/p/8544704.html
Copyright © 2011-2022 走看看