操作系统回调如何工作

时间:2009-08-05 15:21:31

标签: c++ c unix posix

跟进问题: This question

如链接问题中所述,我们有一个API,它使用事件外观轮询select()来处理用户定义的回调。

我有一个类使用它的类:

class example{
 public:
    example(){
        Timer* theTimer1 =  Timer::Event::create(timeInterval,&example::FunctionName);
        Timer* theTimer2 =  Timer::Event::create(timeInterval,&example::FunctionName);
        start();
       cout<<pthread_self()<<endl;
    }
  private:
     void start(){
        while(true){
           if(condition)
              FunctionName();
           sleep(1);
        }
     }
     void FunctionName(){
         cout<<pthread_self()<<endl;
         //Do stuff
     }
};

这背后的想法是,如果条件为真或计时器启动,您希望同时调用FunctionName。不是一个复杂的概念。我想知道的是,如果在start()函数和回调函数中同时调用FunctionName?这可能会导致我的内存损坏,因为它们访问非线程安全的共享内存。

我的测试告诉我他们确实在不同的线程中运行(仅在我使用事件时才会损坏),即使:cout<<pthread_self()<<endl;表示它们具有相同的线程ID。

有人可以向我解释这些回调是如何分开的吗?他们得到了什么样的顺序?他们运行什么线程?我假设它们在执行select()的线程中运行,但是什么时候它们获得相同的线程ID?

2 个答案:

答案 0 :(得分:3)

真正的答案取决于Timer的实现,但如果您从同一个线程运行回调,则最有可能使用signalsposix timers。无论哪种方式,都不会涉及select()

使用信号和posix定时器,你几乎无法从信号处理程序安全地做到。只允许使用某些特定的信号安全呼叫,例如read()write() NOT fread()和fwrite(),甚至是new和cout)。通常,将执行的是write()到pipeeventfd,然后在另一个线程中,或运行select()的主事件循环,请注意此通知并处理它。这使您可以安全地处理信号。

答案 1 :(得分:1)

您编写的代码将无法编译,更不用说运行了。示例:: FunctionName需要是静态的,并且需要将对象引用用作回调函数。

如果定时器在不同的线程中运行,则可以通过三个不同的线程调用此函数。