回调函数(结合Linux信号机制)

回调函数是一种将函数作为参数传递给另一个函数的技术,常用于实现多态性和自定义功能。例如,Linux的sort函数允许用户通过回调函数实现自定义排序方式,或者在接收到特定信号时执行用户定义的操作。回调函数在系统接口和驱动程序中广泛应用,允许用户按需定制系统行为,如改变默认的信号处理方式。回调函数的概念在C++中也有体现,如仿函数,简化了函数指针的使用。

什么是回调函数?

如果一个函数作为另一个函数的参数传入,这种函数就可以称为回调函数(这句话并不严谨,但为了说明问题可以这么理解)。C语言里面,一般就是一个函数的参数列表中有函数指针,函数指针指向的函数就是一个回调函数。

为什么要有回调函数?

那为什么不直接在函数体内调用,而非要把函数指针作为参数呢?

举一个例子:系统提供一个排序函数sort(int a[ ]),排序函数默认升序,但如果我们想要降序排列呢?那系统还要提供一个降序版本

显然,系统可以提供这样一个接口sort(int a[ ], void(*p)(int*) ),后者是一个指向排序方法的函数指针。用户可以自行定义排序方法。即,我们可以认为,回调函数有以下的功能:

  • 一个接口,可以实现不同的功能。这种思想不就是多态吗?本质上还是为了实现地址的晚绑定。C++中的仿函数,其实是对函数指针做了某种程度的简化,使用户使用更简单罢了,使用到的思想是一样的。
  • 通过回调函数可以修改一个黑盒子内部默认的功能,这也是业务上经常用的。

Linux操作系统用到了大量回调的思想,比如对于不同厂家提供的驱动,厂家按照Linux提供的接口标准编写自己的方法,而Linux接口的参数列表中就有指向对应方法的函数指针,这样尽管厂家不同,Linux也可以使用。

再举一个例子,默认情况下,当我们按下CTRL + C时,进程会终止。那我们想改变这样的默认行为怎么办,linux提供了signal这样一个接口。

 #include <signal.h>
  void (*signal(int sig, void (*func)(int)))(int);

第一个参数是信号的编号,此处的ctrl + C对应的是2号信号,第二个参数就是一个函数指针,指向用户自己提供的方法。

如下面的这段代码:

#include <stdio.h>    
#include <unistd.h>    
#include <signal.h>    
void mysignal(int signo)    
{    
  printf("catch a signal! %d\n", signo);    
}    
    
int main()    
{    
  signal(2, mysignal);    
  while(1)    
  {    
    printf("hello world!\n");                       
    sleep(1);    
  }    
  return 0;    
}    

这段代码中,使用signal函数注册了一个新的方法,当按下ctrl + C时,不再默认终止进程,而是输出catch a signal! 2。效果如下:

image-20211204153007188

也就是说,系统提供接口用到了回调函数,用户定义该函数,实现了用户所需要的功能。这也是回调函数的主要应用方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值