C 从中断处理程序内部启动线程

C 从中断处理程序内部启动线程,c,multithreading,pthreads,interrupt-handling,C,Multithreading,Pthreads,Interrupt Handling,我正在尝试在中断发生时立即启动线程。然而,我已经意识到我不能从中断处理程序(或任何直接或间接被中断处理程序调用的函数)中启动线程。因此,我决定让处理程序断言一个标志。然后,一个单独的线程持续监视该标志,如果它被断言,它将依次创建(并启动)一个线程。下面是一个伪代码: int interrupt_flag = 0; interrupt_handler(void) { interrupt_flag = 1 } monitoring_thread(void) //this thread is

我正在尝试在中断发生时立即启动线程。然而,我已经意识到我不能从中断处理程序(或任何直接或间接被中断处理程序调用的函数)中启动线程。因此,我决定让处理程序断言一个标志。然后,一个单独的线程持续监视该标志,如果它被断言,它将依次创建(并启动)一个线程。下面是一个伪代码:

int interrupt_flag = 0;

interrupt_handler(void)
{
  interrupt_flag = 1
}

monitoring_thread(void) //this thread is started at the start of the program
{
  while(1)
  {
    if(interrupt_flag)
    {
      interrupt_flag = 0;
      //start the thread here
      sleep(/*some amount of time*/);
    }
  }
}
我真的不喜欢有一个专门的while循环不断地监视一个标志。这样做的问题是,它显著降低了程序中其他线程的速度。因此,我调用sleep函数来提高程序中其他线程的速度

问题:有没有一种方法可以在中断时真正启动线程,而不需要专用的while循环?是否有从中断处理程序中启动线程的变通方法

如果有什么不同的话,我正在使用POSIX库

谢谢

附:这个问题与之前发布在这里的一个问题有些关联:


它可以等到中断处理程序通知应该生成线程,而不是让监视线程在标志上旋转。一种方法是使用信号量:

sem_t interrupt_sem;

void interrupt_handler(void)
{
  sem_post(&interrupt_sem);
}

void monitoring_thread(void)
{
  while(1)
  {
    sem_wait(&interrupt_sem);
    //start the thread here
  }
}
以前,我有一个基于条件变量的解决方案,但如果中断处理程序进行阻塞调用,则系统不可能正常运行。它可能导致死锁或其他未定义的行为,因为系统中的变量在中断发生时可能没有一致的值


正如我和其他人在评论中指出的,您的操作系统应该提供某种接口来明确唤醒等待的任务。在上面的代码中,我们假设监控线程在后台始终处于活动状态。

您也可以使用POSIX信号量

您可以等待一个初始值为0的信号量,该信号量将被等待阻止

并将此信号量发布到信号句柄函数中


然后,上面的线程将被唤醒,并执行您想要的操作(创建线程)

如果中断处理程序正在抢占当前任务,我希望它将调用一些API,以安排其他任务(或回调)运行以执行实际工作。在你的系统中没有类似的事情可以做吗?该任务可能会产生线程。是的,如果这是一个操作系统(还有什么会处理中断?),那么它应该有一种方法来唤醒等待的任务。传统的方法是使用信号量。在中断处理程序中调用任何可能阻塞的方法(如互斥)都会导致最终的灾难。在中断处理程序中调用
pthread\u mutex\u lock()
是不安全的。如果中断在监控线程中持有锁的某个点触发,将导致死锁。@caf:如果中断处理程序以提升的优先级运行,您是对的。我假设监视线程与中断处理程序处于不同的上下文中。在我所处理的每个操作系统中,都不允许从中断处理程序发出潜在的阻塞调用。正如@caf所说,中断处理程序没有线程上下文,不能阻塞。经典的解决方案是由user2569075发布的。@MartinJames:我以为多线程内核会有一个专门的中断处理程序上下文。我已经更新了答案以注意互斥和条件变量解决方案的局限性,并提供了更简单的基于信号量的解决方案。
pthread\u mutex\u lock()
不是异步信号安全的,即不能从信号处理程序调用它。更方便的便携式解决方案是自管道技巧:信号处理程序将一个字节写入管道。另一个线程等待管道的读取端。这是处理中断处理程序/驱动程序和线程之间的通信的传统方法。请注意,如果中断处理程序向信号量发送消息,则它必须采取一些特殊的操作才能有效,而不只是返回中断。有时需要设置操作系统的“标志”,或者可能是“ExitInterruptSchedule”函数调用或实际跳转到操作系统入口点。这允许中断处理程序在中断返回后“立即”使线程就绪/运行,可能会抢占在中断之前运行的其他线程。