poll机制:
在读取按键电平状态的时候,查询法是在应用程序的死循环中不断调用read函数去读取键值,这将占用几乎所有的CPU资源。
中断方法解决了在死循环中不断读取按键电平的问题,具体做法是:在read函数中判断,如果没有中断发生,就在read函数中就地休眠,当按键按下或松开时,触发中断,进入中断服务函数,在中断服务函数中读取引脚电平,然后在退出终端服务函数之前唤醒进程,让进程就地苏醒,在read函数中继续执行。
在中断法中,ev_press变量只有在中断服务函数中才能被置1,在read函数中的休眠函数之后(也就是被唤醒后要执行的代码)来置0,以等待下一个中断来临。
中断法有一个弊端,即一旦在read函数中休眠,而且也没有中断发生时,我们将无法获得任何信息,让我们感觉系统与我们失去联系了一样,如果能够定时打印一个信息来提示我们系统还在工作就好了,但如果单纯的用一个变量来计数,来定时打印信息,就会变得和查询法一样,耗费大量的CPU资源。
如果额外设置这样一个“计数”闹钟比较耗费CPU资源的话,那我们就让进程自己具备一个“生物钟”,到点了自己醒来打印一句信息。
有一种解决思路是加入Poll机制,具体做法如下:
在应用程序的死循环中调用Poll函数,该函数概括来说,完成了这样一些工作:使用poll_wait函数,
poll(应用程序中的poll) > sys_poll > do_sys_poll > poll_initwait,poll_initwait函数注册一下回调函数__pollwait,它就是我们的驱动程序执行poll_wait时,真正被调用的函数。
do_poll > do_pollfd > file->f_op->poll(也就是我们驱动程序中自己实现的那个poll),在驱动poll函数中调用poll_wait,poll_wait的作用,把进程挂入buttons_waitq队列,
这个队列也是我们驱动自己定义好了的,所以poll_wait函数只是为了让驱动程序能找到要唤醒的进程。
如果未发生中断,根据do_pollfd函数的返回值会调用schedule_timeout(__timeout)函数进行休眠。
进程被唤醒的条件有2:一是上面说的“一定时间(__timeout)”到了,二是被驱动程序唤醒。驱动程序发现条件就绪时,就在中断服务函数中把buttons_waitq队列上挂着的进程唤醒,这个队列,就是前面通过poll_wait把本进程挂过去的队列。
如果休眠了__timeout这段时间,应用程序中的poll函数会返回0,如果没有休眠或在休眠期间被唤醒,则返回非零,根据这一点判断是否要打印信息,判断完后继续调用poll函数。
如果休眠了__timeout这段时间,应用程序中的poll函数会返回0,如果没有休眠或在休眠期间被唤醒,则返回非零,根据这一点判断是否要打印信息,判断完后继续调用poll函数。
如果驱动程序没有去唤醒进程,那么schedule_timeout(__timeou)超时后,会重复调用do_pollfd,如果依然没有发生中断,则继续休眠,不断重复,直到应用程序的poll调用传入的时间到达。
如果超时后,应用程序poll函数返回0,我们打印超时信息,如果没有超时,返回非0,说明此前刚刚发生了中断,我们打印此时按键电平状态。
在读取按键电平状态的时候,查询法是在应用程序的死循环中不断调用read函数去读取键值,这将占用几乎所有的CPU资源。
中断方法解决了在死循环中不断读取按键电平的问题,具体做法是:在read函数中判断,如果没有中断发生,就在read函数中就地休眠,当按键按下或松开时,触发中断,进入中断服务函数,在中断服务函数中读取引脚电平,然后在退出终端服务函数之前唤醒进程,让进程就地苏醒,在read函数中继续执行。
在中断法中,ev_press变量只有在中断服务函数中才能被置1,在read函数中的休眠函数之后(也就是被唤醒后要执行的代码)来置0,以等待下一个中断来临。
中断法有一个弊端,即一旦在read函数中休眠,而且也没有中断发生时,我们将无法获得任何信息,让我们感觉系统与我们失去联系了一样,如果能够定时打印一个信息来提示我们系统还在工作就好了,但如果单纯的用一个变量来计数,来定时打印信息,就会变得和查询法一样,耗费大量的CPU资源。
如果额外设置这样一个“计数”闹钟比较耗费CPU资源的话,那我们就让进程自己具备一个“生物钟”,到点了自己醒来打印一句信息。
有一种解决思路是加入Poll机制,具体做法如下:
在应用程序的死循环中调用Poll函数,该函数概括来说,完成了这样一些工作:使用poll_wait函数,
poll(应用程序中的poll) > sys_poll > do_sys_poll > poll_initwait,poll_initwait函数注册一下回调函数__pollwait,它就是我们的驱动程序执行poll_wait时,真正被调用的函数。
do_poll > do_pollfd > file->f_op->poll(也就是我们驱动程序中自己实现的那个poll),在驱动poll函数中调用poll_wait,poll_wait的作用,把进程挂入buttons_waitq队列,
这个队列也是我们驱动自己定义好了的,所以poll_wait函数只是为了让驱动程序能找到要唤醒的进程。
如果未发生中断,根据do_pollfd函数的返回值会调用schedule_timeout(__timeout)函数进行休眠。
进程被唤醒的条件有2:一是上面说的“一定时间(__timeout)”到了,二是被驱动程序唤醒。驱动程序发现条件就绪时,就在中断服务函数中把buttons_waitq队列上挂着的进程唤醒,这个队列,就是前面通过poll_wait把本进程挂过去的队列。
如果休眠了__timeout这段时间,应用程序中的poll函数会返回0,如果没有休眠或在休眠期间被唤醒,则返回非零,根据这一点判断是否要打印信息,判断完后继续调用poll函数。
如果休眠了__timeout这段时间,应用程序中的poll函数会返回0,如果没有休眠或在休眠期间被唤醒,则返回非零,根据这一点判断是否要打印信息,判断完后继续调用poll函数。
如果驱动程序没有去唤醒进程,那么schedule_timeout(__timeou)超时后,会重复调用do_pollfd,如果依然没有发生中断,则继续休眠,不断重复,直到应用程序的poll调用传入的时间到达。
如果超时后,应用程序poll函数返回0,我们打印超时信息,如果没有超时,返回非0,说明此前刚刚发生了中断,我们打印此时按键电平状态。