Linux设备驱动中的异步通知与异步I/O

发布时间:2024-08-21  

异步通知概念: 异步通知的意识是,一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件上的“中断”概念,比较准确的称谓是“信号驱动的异步IO”,信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求是一样的。信号是异步的,一个进进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。


异步通知与设备访问: 阻塞IO意味着一直等待设备可访问后访问;非阻塞IO使用poll意味着查询设备是否可以访问;而异步通知则意味着设备通知自身可访问,实现了异步I/O。


用kill -l 命令可以查看Linux可用的信号

信号的接收

          signal()函数来设置对应信号的处理函数。

       void (*signal(int signum,void(*handler))(int)))(int);

  //第一个参数指定信号的值;第二个参数指定针对前面信号值的处理函数,若位SIN_IGN,表示忽略该信号;若位SIG_DFL,表示采用系统默认方式处理信号;若位用户自定义

   函数,则信号被捕获到后,该函数将被执行

  //该函数原型比较难理解,可以分解为:typedef void(*sighandler_t)(int);  sighandler_t signal(int signum,sighandler_t handler));

 如果signal调用成功,它返回最后一次信号signum绑定的处理函数handler值,失败则返回SIG_ERR.

          sigaction()函数可用于改变进程接收到特定信号后的行为。

      int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));

  //该函数的第一个参数是信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号;第二个参数是指向结构体sigaction的一个实例的指针,在sigaction的实例中

指定了对特定信号的处理函数,若为空,则进程会以缺省方式对信号处理;第三个参数oldact指向的对象用来保存原来对相应信号的处理函数,可指定oldact为NULL.

 如果把第二和第三个参数都设为NULL,那么该函数用来检测信号的有效性。

 使用信号实现异步通知的应用程序实例:

      #include

      #include

      #include

      #include

      #include

      #include

      #define MAX_LEN 100

      void input handler(int num)

      {

        char data[MAX_LEN];

        int len;

        len=read(STDIN_FILENO,&data,MAX_LEN);  //读取并输出STDIN_FILENO上的输入。

        data[len]=0;

        printf('input available:%sn',data);

      }

      main()

      {

        int oflags;

        //启动信号驱动机制

        signal(SIGIO,input_handler);  //为SIGIO信号安装input_handler()作为处理函数

        fcntl(STDIN_FILENO,F_SETOWN,getpid());//这里的getpid()是获得当前进程,注意,没有这一步,内核不知道应该将信号发给哪个进程。

在 Linux 中,实现文件上锁的函数有lock和fcntl,其中flock用于对文件施加建议性锁,而fcntl不仅可以施加建议性锁,还可以施加强制锁。同时,fcntl还能对文件的某一记录进行上锁,也就是记录锁。

记录锁又可分为读取锁和写入锁,其中读取锁又称为共享锁,它能够使多个进程都能在文件的同一部分建立读取锁。而写入锁又称为排斥锁,在任何时刻只能有一个进程在文件的某个部分上建立写入锁。当然,在文件的同一部分不能同时建立读取锁和写入锁。

注意:

fcntl是一个非常通用的函数,它还可以改变文件进程各方面的属性,在本节中,主要介绍它建立记录锁的方法,关于它其他用户感兴趣的读者可以参看fcntl手册。

       oflags=fcntl(STDIN_FILENO,F_GETFL); //为了启动一步通知机制,还需对设备设置FASYNC标志


       fcntl(STDIN_FILENO,F_SETFL,oflags|FASYNC);


       //最后进入一个死循环,仅为保持进程不终止,如果程序中没有死循环会立即执行完毕


       while(1);


      }


信号释放:

在设备驱动程序与应用程序的异步通知交互中,应用程序捕获信号,驱动程序释放信号。


为了使设备支持异步通知机制,驱动程序中涉及3项工作。


(1)支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID。不过此项工作已由内核完成,设备驱动无需处理。


(2)支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。因此,驱动中应该实现fasync()函数。


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


异步通知处理过程中用户空间和设备驱动的交互。

    异步通知变成主要用到一项数据结构和两个函数。数据结构是fasync_struct结构体,两个函数是fasync_helper,kill_fasync。


       int fasync_helper(int fd,struct file *filp,int mode,struct fasync_struct **fa);  //处理FASYNC标志变更


      void kill_fasync(struct fasync_struct **fa,int sig,int band);  //释放信号


      支持异步通知的设备结构体模板


                              struct xxx_dev{


                                    struct cdev cdev;  //cdev结构体


                                    ...


                                    struct fasync_struct *async_queue;          //异步结构体指针


                                   };


      支持异步通知的设备驱动fasync()函数模板


                              static int xxx_fasync(int fd,struct file *filp,int mode)


                                   {


                                      struct xxx_dev *dev=filp->private_data;


                                      return fasync_helper(fd,filp,mode,&dev->async_queue);


                                   }


      在设备资源可以获得时,应该调用kill_fasync()释放SIGIO信号,可读时第三个参数设置为POLL_IN,可写时第三个参数设置为POLL_OUT.


      支持异步通知的设备驱动信号释放范例:


                                    static ssize_t xxx_write(struct file *filp,const char_user *buf,size_t count,loff_t *f_pos)


                                            {


                                               struct xx_dev *dev=filp->private_data;


                                               ...


                                              //产生异步读信号


                                               if(dev->async_queue)


                                                  kill_fasync(&dev->async_queue,SIGIO,POLL_IN);


                                                   ...


                                         }


 最后在关闭文件时候,即在release函数中,应该将文件从异步通知的列表中删除。


          static int xxx_release(struct inode *inode,struct file *filp)


      {


           //将文件从异步通知列表中删除


            xxx_fasync(-1,filp,0);


             ...


             return 0;


        }


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    函数提供了一系列与硬件相关的服务,例如文件系统访问、进程管理、网络通信等。应用程序通过系统调用接口来调用这些函数,以便实现各种功能。本文引用地址:在系统中,系统调用是一种非常重要的机制。它允......
    虚拟设备的getDeviceCapability()接口获取设备支持能力,按需选择具体的能力。具体是调用enableVirtualDevice来使能所需使能的设备和能力,支持同时传入多个能力。应用使能的结果......
    如何模拟实现应用在数据采集系统中的89C51单片机I/O口串行通信?;目前普遍采用的MCS51 和PIC 系列单片机通常只有一个(或没有)UART异步串行通信接口,在应用系统中若需要多个串行接口......
    container_of(2023-06-15)
    作用是首先使用typeof获取结构体域变量member3的类型为 type3,然后定义了一个type3指针类型的临时变量__mptr,并将实际结构体变量中的域变量的指针memp的值赋给临时变量__mptr。(char......
    详细介绍了基于80C51单片机和USB总线通用接口芯片CH375的LPT-USB打印机驱动器设计及C语言实现。经测试表明,利用该设计能够实现并口仪器数据直接经USB打印机打印出来,打印结果正确无误。该设......
    概念就比较复杂,需要附加一些其他的变量。 最流行的I/O模型是阻塞式I/O(blocking I/O) 模型,默认情况下,所有的套接字都是阻塞的。阻塞调用是指调用结果返回之前,当前线程会被挂起(线程......
    “CalendarClk.h” /* 从串行口获取数据函数,数据包括:year1,month1,dayofweek1, dayofmonth1,hour1,min1。如果获取到正确数据则返回1,否则返回0......
    communication)所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由*调用者*主动等待这个*调用*的结果。 而异步则是相反,*调用......
    系统,STM32F407开发板作为 TCP client,网络调试助手作为TCP server,利用串口获取两者的连接状态。在用原子的lwip工程移植到自己的STM32F407开发板时,可以正常获取DHCP分配......
    迁移能力增强,支持调用接口来动态打开和关闭迁移能力。应用可动态选择迁移成功后是否迁移页面栈,以及源端是否退出。 ▌ArkUI 基础组件增加或增强 新增UIExtension组件,用于......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>