在嵌入式开发软件中,回调函数是一种通常会接触到的软件设计方法,例如事件处理机制基本上都会使用到回调函数。
让我们来稍微讲解一下回调函数:
回调函数在C语言中与函数指针调用在语法上并没有太大的区别,但是它得名于其功能:它会被“返回来调用”。
这里的“返回”涉及到一个方向性问题——是从哪里来的,也要知道去哪里。在软件中,这通常与“分层设计思想”有关。
分层设计方式在软件设计领域是极其普及的,嵌入式中最简单的分层方式是两层,即驱动层和应用层。
当函数功能上进行分层以后不应该直接在底层驱动中直接调用应用层函数等,比如应用程序通过调用驱动层接口获得物理量数据,我们常规的做法大部分都是不断的轮询相应的API接口返回数据,这样可能会导致不断的IO操作,效率相对比较低下。
那么应用程序是否可以化主动为被动呢,一直舔狗实在是太累了?既然你现在不想搭理我,那等你准备好了,再来告诉我吧,到时候调用我给你的函数就可以了,这个函数已经放在了传给你的函数指针里了,那么这里应用程序所给的函数就是回调函数。
比如我们经常会在应用程序中查询按键是否被按下,然后得编写一大堆的时序等等,还与应用逻辑耦合在一起。
其实按键是是如何检测被按下的过程对于应用程序它并关心,底层程序查询确定好状态给应用程序一个是否按下的通知或者状态即可。
此时底层按键检测程序要通知应用程序,就可以通过相应的回调函数来通知应用层并处理即可。
如果还有点难理解,可以看看stm32使用hal库,你会发现在中断中有大量的回调函数指针被调用,其实回调函数的效果与中断服务函数的执行效果是类似的,hal库中使用回调函数的方式把中断的相关事件服务处理交给了用户自身来注册。
把中断看成一种事件类型,那么回调函数的使用其实就类似于一种事件驱动机制。
同步与异步调用
首先要理清楚这两种方式需要理解什么是同步和异步。
同步调用表示当调用一个底层接口,必须回调函数被执行完毕,不然该接口会一直处于堵塞状态没办法返回结果,且程序无法往下执行。
异步调用表示当调用一个底层接口以后,不需要等待回调函数执行完毕,便可以直接返回继续做下面的事情,最终底层准备好以后便会执行回调函数处理应用层事务,所以我们也称这种回调函数为异步回调函数。
而异步调用的好处在于调用函数不需要阻塞可以继续执行,从而大大提高程序运行效率,但由于异步回调函数在时间上是无序的,导致当我们需要异步调用函数能够顺序执行时便会存在难度,使得业务逻辑比较复杂,难以理解。
为了保证回调的有序性,就需要以上一次回调的结果作为本次异步调用的条件,导致代码一层嵌套一层非常的冗长,类似于ifelse里面再嵌套ifelse之势,所以也很多人称这种方式为 Callback hell(回调地狱)。
为了改善这种结构,通常会采用协程的概念去处理异步回调来规避该问题。
对于异步调用常与多线程进行结合,在另外一个线程中执行异步操作,然后调用回调函数返回结果并继续处理。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !