跟进问题: 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?这可能会导致一些内存损坏,因为它们访问了一 block 非线程安全的共享内存。
我的测试告诉我它们确实在不同的线程中运行(只有当我使用事件时才会损坏),即使:cout<<pthread_self()<<endl;
说他们有相同的线程ID。
有人可以向我解释这些回调是如何 fork 的吗?他们执行什么命令?他们在什么线程中运行?我假设它们在执行 select() 的线程中运行,但是它们什么时候获得相同的线程 ID?
最佳答案
真正的答案将取决于 Timer 的实现,但如果您从同一线程获得回调,则很可能使用 signals或 posix timers .无论哪种方式,select()根本不参与。
对于信号和 posix 计时器,您几乎无法从信号处理程序中安全地执行操作。只有某些特定的信号安全调用,例如 read()和 write() (NOT fread() 和 fwrite(),甚至 new 和 cout)被允许使用。通常会做的是 write() 到 pipe或 eventfd ,然后在另一个线程或运行 select() 的主事件循环中,注意此通知并处理它。这使您能够以安全的方式处理信号。
关于c++ - 操作系统回调如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1233963/