gpt4 book ai didi

C++、信号和线程

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:52:40 24 4
gpt4 key购买 nike

我在使用线程和信号设计我的应用程序的主要工作流程时遇到了一些困难。

我的目标是有一个主线程,捕捉信号,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 main\n";

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

return 0;
}

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

我可能遇到的另一个问题是,某些传感器在两次测量之间的等待时间可能非常长(例如 2 或 3 小时),因此我需要每 2 或 3 秒检查一次停止值......并且它感觉不太像干净的方法。另一种解决方案是向线程发送信号,让我可以简单地让我的线程“休眠”;但同样,我无法控制线程在终止前完成其操作。

提前致谢!

最佳答案

在信号处理程序中不允许对互斥锁进行操作。您可以将 stop 变量分成两个:

  1. stop_main,在signal handler中设置,在主线程等待。因为信号处理程序是在主线程的上下文中执行的,所以将其声明为volatile(或std::atomic)就足够了。
  2. 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) 可以替换为任何可被信号中断的函数。

关于C++、信号和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30002609/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com