简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:在阅读内核源码时,发现内核代码写的回调函数竟然都没有任何的修饰,随即分享给大家。
2.回调函数介绍
- 回调函数(Callback Function)是计算机编程中的一个常用概念,特别是在面向对象编程和函数式编程中。简单来说,回调函数是一种将函数作为参数传递给另一个函数,并在适当的时候执行该函数的机制。回调函数通常用于实现事件驱动编程、异步编程和装饰器模式等。
- 回调函数的概念最早可以追溯到20世纪50年代的函数式编程语言。在函数式编程中,回调函数被广泛使用,因为它使得函数的组合变得容易。在1980年代,回调函数开始在面向对象编程语言中得到应用,特别是在设计模式中。
- 回调函数的应用场景非常广泛。例如,在图形用户界面编程中,当用户执行某个操作(如点击按钮)时,相应的回调函数会被调用。在网络编程中,当网络请求完成时,回调函数会被用于处理响应数据。在并发编程中,回调函数可以用于处理异步操作的结果。
- 回调函数有多种形式,以下是几种常见的回调函数类型:
- 函数指针回调:这是最简单的回调函数形式。在这种形式中,将函数的指针作为参数传递给另一个函数。例如,在C语言中,可以使用函数指针来实现回调。
- 对象方法回调:在这种形式中,将对象的方法作为参数传递给另一个函数。在面向对象编程语言中,如Java和C#,这种回调函数形式非常常见。
- 匿名函数回调:在一些语言中,可以使用匿名函数作为回调函数。例如,在JavaScript中,匿名函数经常被用作回调函数。
- lambda表达式回调:在一些函数式编程语言中,如Scala和Java 8及以上版本,可以使用lambda表达式来创建回调函数。
回调函数有一些优点和缺点。优点包括: - 灵活性:回调函数可以使代码更加灵活,因为它允许在运行时动态地选择和传递函数。
- 代码解耦:回调函数可以将逻辑分离到不同的模块中,从而降低代码之间的耦合度。
- 事件驱动编程:回调函数使得事件驱动编程变得容易实现,因为事件处理器可以作为回调函数来处理事件。
然而,回调函数也有一些缺点: - callback hell:当回调函数的数量和层次过多时,代码可能会变得难以维护和理解,这种情况被称为“callback hell”。
- 性能问题:过多的回调函数可能会导致性能问题,因为函数调用需要消耗时间和资源。
- 错误处理:回调函数中的错误处理可能比较困难,因为错误可能需要在多个层次上传递。
- 总之,回调函数是一种非常有用的编程概念,它可以在多种场景下提高代码的灵活性和可维护性。然而,在使用回调函数时,需要注意避免“callback hell”和性能问题,并妥善处理错误。
3.Linux内核代码使用回调函数实例
static int do_dentry_open(struct file *f,
struct inode *inode,
int (*open)(struct inode *, struct file *))
{
static const struct file_operations empty_fops = {};
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))
f->f_mode |= FMODE_ATOMIC_POS;
/* normally all 3 are set; ->open() can clear them if needed */
f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
if (!open)
open = f->f_op->open;
if (open) {
error = open(inode, f);
}
return error;
}
do_dentry_open函数的第三个参数就是一个回调函数定义,然后使用open(inode, f)传入参数调用。
便于大家理解,下面写一个类似的Linux内核回调函数的用法实例。
4.代码实例
<1>.v1.0
#include <iostream>
#include <string>
#include <string_view>
using namespace std;
//定义finish_open函数,接受一个函数指针作为参数
void finish(int (*open)(string name, int mode)) {
//调用回调函数
open("/dev/binder", 777);
}
int open_file(string name, int mode) {
printf("xxx--------------->line = %d, name = %s, mode = %d\n",__LINE__,name.c_str(),mode);
return 0;
}
int main() {
finish(open_file);
return 0;
}
打印
xxx--------------->line = 13, name = /dev/binder, mode = 777