宝玛科技网
您的当前位置:首页函数指针与回调函数详解

函数指针与回调函数详解

来源:宝玛科技网

函数指针与回调函数详解

1.什么是函数指针?

080483c4 <rfun>:
 80483c4:       55                      push   %ebp
 80483c5:        e5                   mov    %esp,%ebp
 80483c7:       83 ec 28                sub    $0x28,%esp
 ······
 80483f3:       e8 cc ff ff ff          call   80483c4 <rfun>
 ······

2.函数指针的使用

2.1调用函数

我们就用函数指针调用刚才的rfun函数。

int rfun(unsigned x);//函数的声明
int (*pfun)(unsigned);//函数指针的定义
pfun = rfun;//函数指针的初始化

pfun就是指针变量,可以直接用函数名rfun赋值给pfun这个指针。函数指针在调用时和函数调用一致,只是用指针代替了函数名。

pfun(x);//函数指针的调用

函数指针不能做自增和自减操作,否则程序会崩溃。

2.2作为函数的参数

函数指针作为A函数的参数,A函数称为回调函数。A函数的定义为:

int rfun_call(int (*pfun)(unsigned), unsigned x)
{
    return pfun(x);
}

这个函数的第一个参数是一个返回值为int类型,参数为一个且是unsigned类型函数的指针,第二个参数是 unsigned类型。

3.什么是回调函数?

先说明两个Linux系统函数,一个是alarm函数,一个是signal函数

①alarm函数,也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号。

#include <unistd.h>//alarm的头文件
unsigned int alarm(unsigned int seconds);//alarm的函数原型

②signal函数,执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。

#include <signal.h>//signal函数的头文件

typedef void (*sighandler_t)(int);//sighandler_t是一个指向返回值为void,参数为int的函数指针
sighandler_t signal(int signum, sighandler_t handler);//signal函数的原型

描述一个场景:
你要睡觉,只睡2秒,所以你定了一个2秒的闹钟,到第3秒时,闹钟给你发信号,说时间到了

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void fun(int signum)
{
     printf("时间到了,起床!\n");
}

int main()
{
    int i;

    alarm(3);//定2秒闹钟,第3秒会响铃,也就是发信号
    signal(SIGALRM, fun);//接收闹铃的信号,去执行fun()
    for(i = 0; i < 3; i++){
            sleep(1);//描述时间的流逝
            printf("%d秒过去了\n", i+1);
    }
    printf("睡觉结束");

    return 0;
}

执行结果如下:

[root@menwen-linux test]# ./callback
1秒过去了
2秒过去了
时间到了,起床!
3秒过去了
睡觉结束

在时间到第三秒的时候,signal函数执行了fun函数,执行完fun函数,就会继续执行“睡觉结束”。
如果不设置闹铃(注释alarm(3)),程序就会一直按顺序执行,直到程序结束,永远不会执行回调函数。
signal函数就是一个回调函数,接收一个函数指针,和一个信号量SIGALRM,在Linux内核代码中,SIGALRM等信号其实是一堆宏定义,都对应一个数值

#define SIGHUP           1
#define SIGINT           2
#define SIGQUIT          3
#define SIGILL           4
......
#define SIGPIPE         13
#define SIGALRM         14
#define SIGTERM         15
#define SIGSTKFLT       16
#define SIGCHLD         17
等等.....

或者命令行输入kill -l 也会对应出现这个信号量。

[menwen@menwen-linux 6th_day]$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
......
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  ) SIGRTMAX    

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。我们实现了fun函数,而我们不调用该函数,而是去睡觉(或者干其他事),等到时间到,回调函数就会去响应,这是一种系统异步处理的机制。

最后留下一句话在网上看到的话,如果你看懂了上面这些,这句话你就懂了!

告诉我一些关于你的事情,在需要的时候我能够找到你。

因篇幅问题不能全部显示,请点此查看更多更全内容