C ++,信号和线程

我很难用线程和信号设计我的应用程序的主要工作流程。

我的目标是有一个主线程,捕获信号和其他n个线程周期性地执行任务(实际上使用树莓派上的传感器,并保存检索到的数据)。 我希望能够以一种干净的方式关闭程序,即等待传感器在关闭之前完成数据写入(如果是信号发生时)。 我正在使用C ++ 11。

现在,我有这个例子:

#include <iostream>
#include <thread>
#include <csignal>
#include <mutex>

#define NUM_THREAD 3;

static volatile int stop = 0;     // If the threads needs to stop
std::mutex m;                     // Mutex

void threadHandle(int tid) {
    while(1) {
        std::cout << "Launched by thread " << tid << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "I have sleep well " << tid << std::endl;

        m.lock();
        if(stop) {
            std::cout << "Thread " << tid << " needs to stop" << std::endl;
            m.unlock();
            break;
        }
        m.unlock();
    }
}

void signalHandler(int signum) {
    m.lock();
    std::cout << "Signal " << signum << " received" << std::endl;
    stop = 1;
    m.unlock();
}

int main() {
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

     //Launch a group of threads
     for (int i = 0; i < NUM_THREAD; i++) {
         t[i] = std::thread(call_from_thread, i);
     }

     std::cout << "Launched from the mainn";

     for (int i = 0; i < NUM_THREAD; i++) {
         t[i].join();
     }

     return 0;
}

我的停止值是易变的,只是因为我在信号处理程序中使用它。 我应该使用std :: atomic_int来确保对我的信号值进行原子调用吗? 互斥锁是否真的有必要? 或者更一般地说,这是实现我想要的一种好方法吗?

我可能遇到的另一个问题是,有些传感器可能需要等待很长时间(例如2或3小时)的测量时间,所以我需要每2或3秒检查一次停止值,而不是感觉真的很喜欢干净的做法。 另一个解决方案,发送信号给线程,让我简单地让我的线程“睡眠”; 但是我再也没有控制来告诉线程在终止之前完成它的动作。

提前致谢 !


信号处理程序不允许在互斥体上进行操作。 您可以将stop变量分为两部分:

  • stop_main ,它在信号处理程序中设置,并在主线程中等待。 因为信号处理程序是在主线程的上下文中执行的,所以将其声明为volatile(或std :: atomic)就足够了。
  • stop_threads ,它在主线程中设置,并由其他人等待。 这个变量的最适合的类型是std :: condition_variable。 这种类型也有助于您等待很长时间。

  • 像这样的东西:

    std::atomic<int> stop_main = 0;
    std::condition_variable stop_threads;
    std::mutex m; // protects 'stop_threads'
    
    void threadHandle(int tid)
    {
        while(1)
        {
            /* .. do something .. */
    
            std::unique_lock<std::mutex> l(m);
            if(stop_threads.wait_for(l, std::chrono::hours(2)) ==
                std::cv_status::no_timeout) break;
        }
    }
    void signalHandler(int signum)
    {
        stop_main.store(1);
    }
    int main()
    {
        std::thread t[NUM_THREAD];
        std::signal(SIGINT, signalHandler);
    
        for (int i = 0; i < NUM_THREAD; i++) {
            t[i] = std::thread(threadHandle, i);
    
    
        while(!stop_main.load())
        {
            /* Some workload may be here */
            sleep(10); // Signals will interrupt this function.
        }
    
        stop_threads.notify_all();
    
        for (int i = 0; i < NUM_THREAD; i++) {
            t[i].join();
    
        return 0;
    }
    

    我不确定c ++是否会向主线程传递信号,而不是其他信号。 否则,您需要阻止其他线程中的信号。

    主线程中的sleep(10)可以用信号可中断的任何函数替换。


    通常的模式是阻塞除了用于信号处理的特殊线程之外的所有工作线程的信号。

    链接地址: http://www.djcxy.com/p/30759.html

    上一篇: C++, signal and threads

    下一篇: How to prevent threads from starvation in C++11