我有一个std::线程,它监听来自Linux内核的netlink事件,它有一个无限while循环和一个阻塞函数,阻塞函数会阻塞到下一个事件。我想在程序工作流中强制停止线程,当我不再需要它的时候。
以下是我目前的解决方案:
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <thread>
#include <signal.h>
void thread_func() {
while(true) {
std::cout << "Processing events.." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10)); // simulating a blocking function that blocks until next events
std::cout << "Events received.." << std::endl;
}
}
int main() {
std::thread eventListener(thread_func);
std::this_thread::sleep_for(std::chrono::seconds(3)); // doing some work in main thread
pthread_cancel(eventListener.native_handle()); // I don't want the eventListener anymore
eventListener.join();
std::cout << "eventListener killed" << std::endl;
return 0;
}
我的程序只能编译到Linux平台。
它是来自libnl的实际阻塞函数nl_recvmsgs_default(nl_sock * sock)
- 问题**:
1.这是C++中正确的做法吗?还是我遗漏了一些小细节?
1.有没有其他更好的方法来实现这一目标?
1.如果我改变上面的代码,用pthread_kill
而不是pthread_cancel
来终止线程,那么我在输出中看不到打印的"eventListener killed"
,我不知道为什么?
- 更新:**设置一个标志对我来说不起作用,因为我甚至不知道函数会被阻塞多久,如果我没有从内核接收到任何新事件,那么函数永远不会恢复,在这种情况下,我只需要在将标志设置为true后等待(直到下一次while循环对来自内核的新netlink事件的迭代)。
2条答案
按热度按时间ulydmbyx1#
重新设计,使您的线程不使用阻塞操作。
Netlink是作为套接字I/O实现的,因此您可以使用
nl_socket_set_nonblocking
,然后使用poll
或select
等“可中断”I/O多路复用来等待活动。添加一个简单的
pipe
,这样你的循环线程在netlink套接字和管道的 read 端都是输入复用的。当需要结束循环时,让其他线程关闭 write 端-read端将立即显示为可读(对于EOF),你的循环线程将知道它的工作已经完成。您可以使用一个简单的多线程程序(例如,阻塞在stdin上的程序)而不是netlink套接字来原型化这种方法。
krcsximq2#
您可能希望为阻塞函数使用一个时间间隔,这样它将返回并再次检查循环条件,以查看是否需要继续侦听。然后,您可以使用一个标志将线程从循环中释放。