回调函数的疑惑

jiazhucai 2014-09-09 03:10:21
问题背景:之前的一个项目有用到一款网络摄像机,其中需要调用摄像机SDK获取视频帧的BMP格式的数据,比如回调函数中会把帧数据写到一个全局的内存块。通过设置回调函数来获取帧数据。我发现只要在程序初始化中设置该回调函数,在后面的业务模块中只要是一个循环,我就能从内存块中提取出实时的帧数据,大致流程如下:

// 存放帧数据的数组
char data[1000];

// 回调函数,callback_fun由SDK提供
void callback_fun()
{
...
// 将帧数据写到一个全局数组data中
}

// 初始化工作,在程序一开始时执行
void init()
{
.......
// 设置回调函数,set_callback也是由SDK提供
int flag = set_callback(para1, para2, ..., callback_fun);
......
}

// 主要业务代码
void dowork()
{
while(true)
{
// 从数组data中取当前帧数据
}
}

问题:我在业务代码的循环语句中并没有明确地使用到调用函数,只是在初始化时调用过一次设置回调函数,为什么我从data中获得的是实时的帧数据?是不是set_callback隐藏地开了一个线程,在循环调用,实时地向data数组中写数据?如果是这样还有一个问题,一个线程往data中写数据,而我的业务代码中要读数据,这是一个读者写者问题,可我并没有加锁互斥,但在长时间运行的过程中程序并没有崩溃过和错误结果的现象,这又是为什么?
分不多,还是希望各位大神能回答。
...全文
144 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wanght99 2014-09-09
  • 打赏
  • 举报
回复
引用 6 楼 u011201045 的回复:
引用 3 楼 wanght99 的回复:
底层未必是线程, 有可能是中断, 摄像头采集到一帧数据以后产生一个中断, 程序切换到中断处理去取数据. 你的回调函数被调用的时候数据肯定已经就绪了. set_callback肯定不会去开线程.
思考了一下,你说的是不是这个意思:底层可能会采取一种中断机制,摄像头采集到一帧数据的时候,产生一个中断,从而触发回调函数完成将帧数据写进data数组的功能,这时我业务模块中的while循环就能获取到更新的data数组?
是的.
jiazhucai 2014-09-09
  • 打赏
  • 举报
回复
引用 3 楼 wanght99 的回复:
底层未必是线程, 有可能是中断, 摄像头采集到一帧数据以后产生一个中断, 程序切换到中断处理去取数据. 你的回调函数被调用的时候数据肯定已经就绪了. set_callback肯定不会去开线程.
思考了一下,你说的是不是这个意思:底层可能会采取一种中断机制,摄像头采集到一帧数据的时候,产生一个中断,从而触发回调函数完成将帧数据写进data数组的功能,这时我业务模块中的while循环就能获取到更新的data数组?
wanght99 2014-09-09
  • 打赏
  • 举报
回复
引用 4 楼 u011201045 的回复:
引用 3 楼 wanght99 的回复:
底层未必是线程, 有可能是中断, 摄像头采集到一帧数据以后产生一个中断, 程序切换到中断处理去取数据. 你的回调函数被调用的时候数据肯定已经就绪了. set_callback肯定不会去开线程.
那么请问,底层是不是一个循环调用的机制,我理解不了,我的while死循环中并没有去调用函数往data数组中不停地去更新数组,那么为什么我取到的数据是更新过的呢?谢谢
不是循环调用, 操作系统运行的时候不是一个进程自顾自地跑的, 而是有许多其他的机制. 可以类比一下Ctrl-C, 当运行一个控制台程序的时候, 按Ctrl-C可以中止, 你的主程序里肯定没写捕获Ctrl-C的代码(其实也可以写一个处理函数, 这时候这个函数就相当于回调函数了), 但你的程序可以响应Ctrl-C, 你的采集图像函数道理也一样, 一个事件发生的时候, 操作系统会通知你的程序, 而你的程序里的回调函数就会执行.
jiazhucai 2014-09-09
  • 打赏
  • 举报
回复
引用 3 楼 wanght99 的回复:
底层未必是线程, 有可能是中断, 摄像头采集到一帧数据以后产生一个中断, 程序切换到中断处理去取数据. 你的回调函数被调用的时候数据肯定已经就绪了. set_callback肯定不会去开线程.
那么请问,底层是不是一个循环调用的机制,我理解不了,我的while死循环中并没有去调用函数往data数组中不停地去更新数组,那么为什么我取到的数据是更新过的呢?谢谢
wanght99 2014-09-09
  • 打赏
  • 举报
回复
底层未必是线程, 有可能是中断, 摄像头采集到一帧数据以后产生一个中断, 程序切换到中断处理去取数据. 你的回调函数被调用的时候数据肯定已经就绪了. set_callback肯定不会去开线程.
sg_knight 2014-09-09
  • 打赏
  • 举报
回复
回调函数是用来让系统或其它程序调用的。自己不调用。
赵4老师 2014-09-09
  • 打赏
  • 举报
回复
仅供参考
#pragma comment(lib,"user32")
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <windows.h>
char datestr[16];
char timestr[16];
char mss[4];
void log(char *s) {
    struct tm *now;
    struct timeb tb;

    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,s);
}
VOID CALLBACK myTimerProc1(
  HWND hwnd, // handle of window for timer messages
  UINT uMsg, // WM_TIMER message
  UINT idEvent, // timer identifier
  DWORD dwTime // current system time
) {
 log("In myTimerProc1\n");
}
VOID CALLBACK myTimerProc2(
  HWND hwnd, // handle of window for timer messages
  UINT uMsg, // WM_TIMER message
  UINT idEvent, // timer identifier
  DWORD dwTime // current system time
) {
 log("In myTimerProc2\n");
}
int main() {
    int i;
    MSG msg;

    SetTimer(NULL,0,1000,myTimerProc1);
    SetTimer(NULL,0,2000,myTimerProc2);
    for (i=0;i<20;i++) {
        Sleep(500);
        log("In main\n");
        if (GetMessage(&msg,NULL,0,0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

    }
    return 0;
}
//2012-07-26 17:29:06.375 In main
//2012-07-26 17:29:06.875 In myTimerProc1
//2012-07-26 17:29:07.375 In main
//2012-07-26 17:29:07.875 In myTimerProc2
//2012-07-26 17:29:08.375 In main
//2012-07-26 17:29:08.375 In myTimerProc1
//2012-07-26 17:29:08.875 In main
//2012-07-26 17:29:08.875 In myTimerProc1
//2012-07-26 17:29:09.375 In main
//2012-07-26 17:29:09.890 In myTimerProc2
//2012-07-26 17:29:10.390 In main
//2012-07-26 17:29:10.390 In myTimerProc1
//2012-07-26 17:29:10.890 In main
//2012-07-26 17:29:10.890 In myTimerProc1
//2012-07-26 17:29:11.390 In main
//2012-07-26 17:29:11.890 In myTimerProc2
//2012-07-26 17:29:12.390 In main
//2012-07-26 17:29:12.390 In myTimerProc1
//2012-07-26 17:29:12.890 In main
//2012-07-26 17:29:12.890 In myTimerProc1
//2012-07-26 17:29:13.390 In main
//2012-07-26 17:29:13.890 In myTimerProc2
//2012-07-26 17:29:14.390 In main
//2012-07-26 17:29:14.390 In myTimerProc1
//2012-07-26 17:29:14.890 In main
//2012-07-26 17:29:14.890 In myTimerProc1
//2012-07-26 17:29:15.390 In main
//2012-07-26 17:29:15.890 In myTimerProc2
//2012-07-26 17:29:16.390 In main
//2012-07-26 17:29:16.390 In myTimerProc1
//2012-07-26 17:29:16.890 In main
//2012-07-26 17:29:16.890 In myTimerProc1
//2012-07-26 17:29:17.390 In main
//2012-07-26 17:29:17.890 In myTimerProc2
//2012-07-26 17:29:18.390 In main
//2012-07-26 17:29:18.390 In myTimerProc1
//2012-07-26 17:29:18.890 In main
//2012-07-26 17:29:18.890 In myTimerProc1
//2012-07-26 17:29:19.390 In main
//2012-07-26 17:29:19.890 In myTimerProc2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
    #include <windows.h>
    #include <io.h>
    #include <process.h>
    #define  MYVOID             void
#else
    #include <unistd.h>
    #include <sys/time.h>
    #include <pthread.h>
    #define  CRITICAL_SECTION   pthread_mutex_t
    #define  _vsnprintf         vsnprintf
    #define  MYVOID             void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
char logstr[16000];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
    EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
    LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
    Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
    pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
    pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
    usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
    struct tm *now;
    struct timeb tb;


    if (NULL==pszFmt||0==pszFmt[0]) return;
    if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0;
    ftime(&tb);
    now=localtime(&tb.time);
    sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
    sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );
    sprintf(mss,"%03d",tb.millitm);
    printf("%s %s.%s %s",datestr,timestr,mss,logstr);
    flog=fopen(logfilename1,"a");
    if (NULL!=flog) {
        fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
        if (ftell(flog)>MAXLOGSIZE) {
            fclose(flog);
            if (rename(logfilename1,logfilename2)) {
                remove(logfilename2);
                rename(logfilename1,logfilename2);
            }
            flog=fopen(logfilename1,"a");
            if (NULL==flog) return;
        }
        fclose(flog);
    }
}
void Log(const char *pszFmt,...) {
    va_list argp;

    Lock(&cs_log);
    va_start(argp,pszFmt);
    LogV(pszFmt,argp);
    va_end(argp);
    Unlock(&cs_log);
}
//Log}
int No_Loop=0;
MYVOID testThread(void *pcn) {
    int n,i;

    n=(int)pcn;
    i=0;
    while (1) {
        sleep_ms(1000);
        Log("in testThread %d:i==%ds\n",n,++i);
        if (i>=5) No_Loop=1;
    }
}
int main(int argc,char * argv[]) {
    int i;
#ifdef WIN32
    InitializeCriticalSection(&cs_log);
#else
    pthread_mutex_init(&cs_log,NULL);
    pthread_t threads[1];
    int threadsN;
    int rc;
#endif
    Log("=========BEGIN==================\n");
#ifdef WIN32
    _beginthread((void(__cdecl *)(void *))testThread,0,(void *)1);
#else
    threadsN=0;
    rc=pthread_create(&(threads[threadsN++]),NULL,testThread,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif
    i=0;
    while (1) {
        sleep_ms(100);
        Log("in main:i==%d\n",++i);
        if (No_Loop==1) break;//
    }
    Log("=========END====================\n");
#ifdef WIN32
    DeleteCriticalSection(&cs_log);
#else
    pthread_mutex_destroy(&cs_log);
#endif
    return 0;
}
//2012-06-14 16:27:21.500 =========BEGIN==================
//2012-06-14 16:27:21.609 in main:i==1
//2012-06-14 16:27:21.718 in main:i==2
//2012-06-14 16:27:21.828 in main:i==3
//2012-06-14 16:27:21.937 in main:i==4
//2012-06-14 16:27:22.046 in main:i==5
//2012-06-14 16:27:22.156 in main:i==6
//2012-06-14 16:27:22.265 in main:i==7
//2012-06-14 16:27:22.375 in main:i==8
//2012-06-14 16:27:22.484 in main:i==9
//2012-06-14 16:27:22.500 in testThread 1:i==1s
//2012-06-14 16:27:22.593 in main:i==10
//2012-06-14 16:27:22.703 in main:i==11
//2012-06-14 16:27:22.812 in main:i==12
//2012-06-14 16:27:22.921 in main:i==13
//2012-06-14 16:27:23.031 in main:i==14
//2012-06-14 16:27:23.140 in main:i==15
//2012-06-14 16:27:23.250 in main:i==16
//2012-06-14 16:27:23.359 in main:i==17
//2012-06-14 16:27:23.468 in main:i==18
//2012-06-14 16:27:23.500 in testThread 1:i==2s
//2012-06-14 16:27:23.578 in main:i==19
//2012-06-14 16:27:23.687 in main:i==20
//2012-06-14 16:27:23.796 in main:i==21
//2012-06-14 16:27:23.906 in main:i==22
//2012-06-14 16:27:24.015 in main:i==23
//2012-06-14 16:27:24.125 in main:i==24
//2012-06-14 16:27:24.234 in main:i==25
//2012-06-14 16:27:24.343 in main:i==26
//2012-06-14 16:27:24.453 in main:i==27
//2012-06-14 16:27:24.500 in testThread 1:i==3s
//2012-06-14 16:27:24.562 in main:i==28
//2012-06-14 16:27:24.671 in main:i==29
//2012-06-14 16:27:24.781 in main:i==30
//2012-06-14 16:27:24.890 in main:i==31
//2012-06-14 16:27:25.000 in main:i==32
//2012-06-14 16:27:25.109 in main:i==33
//2012-06-14 16:27:25.218 in main:i==34
//2012-06-14 16:27:25.328 in main:i==35
//2012-06-14 16:27:25.437 in main:i==36
//2012-06-14 16:27:25.500 in testThread 1:i==4s
//2012-06-14 16:27:25.546 in main:i==37
//2012-06-14 16:27:25.656 in main:i==38
//2012-06-14 16:27:25.765 in main:i==39
//2012-06-14 16:27:25.875 in main:i==40
//2012-06-14 16:27:25.984 in main:i==41
//2012-06-14 16:27:26.093 in main:i==42
//2012-06-14 16:27:26.203 in main:i==43
//2012-06-14 16:27:26.312 in main:i==44
//2012-06-14 16:27:26.421 in main:i==45
//2012-06-14 16:27:26.500 in testThread 1:i==5s
//2012-06-14 16:27:26.531 in main:i==46
//2012-06-14 16:27:26.531 =========END====================

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧