问题描述
我想编写一个C ++程序,该程序应等待linux信号(毫秒级分辨率),但是我找不到实现此目的的可能性。
以下测试代码应在500毫秒后终止,但不会终止。
#include <iostream>
#include <csignal>
#include <unistd.h>
#include <chrono>
#include <future>
using namespace std::chrono_literals;
extern "C" void handler(int s) {
}
int main() {
std::signal(SIGUSR1,handler);
bool started = false;
auto f = std::async(std::launch::async,[&] {
auto start = std::chrono::high_resolution_clock::Now();
started = true;
//usleep(1000000);
sleep(1);
//std::this_thread::sleep_for(1s);
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::Now() - start).count() << "ms";
});
std::this_thread::sleep_for(500ms);
std::raise(SIGUSR1);
}
有人知道如何解决此问题吗?
解决方法
执行信号处理程序后,程序返回到其正常操作。睡眠不会终止,因为它与注释中的鲜明注释处理信号的线程不同。
相反,此答案C/C++: How to exit sleep() when an interrupt arrives?建议使用互斥量来阻止操作。使用try_lock_for
还要显示线程ID(显示它们是不同的线程),它可能是:
#include <iostream>
#include <csignal>
#include <unistd.h>
#include <chrono>
#include <future>
using namespace std::chrono_literals;
std::timed_mutex mtx;
extern "C" void handler(int s) {
std::cout << std::this_thread::get_id() << " signal handler"
<< std::endl;
mtx.unlock();
}
int main() {
std::signal(SIGUSR1,handler);
auto start_outer = std::chrono::high_resolution_clock::now();
mtx.lock();
auto f = std::async(std::launch::async,[&] {
auto start = std::chrono::high_resolution_clock::now();
mtx.try_lock_for(std::chrono::milliseconds(1000));
std::cout << std::this_thread::get_id() << " "
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count() << "ms"
<< std::endl;
});
std::this_thread::sleep_for(500ms);
std::cout << std::this_thread::get_id() << " "
<< std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start_outer).count() << "ms"
<< std::endl;
std::raise(SIGUSR1);
}
构建,运行,输出
% g++ -std=c++17 test.cpp && ./a.out
0x112cb9dc0 506ms
0x112cb9dc0 signal handler
0x700009e86000 506ms
,
有了ti7和user4581301的想法,我终于找到了解决方案。
我使用signal_handler中的互斥锁的概念,但仅限于允许的系统调用集,我使用了信号灯。
sem_t *sem_g = nullptr;
extern "C" void handler(int s) {
if (sem_g)
sem_post(sem_g);
}
int main() {
sem_t sem = {};
sem_init(&sem,0);
sem_g = &sem;
std::signal(SIGUSR1,handler);
auto f = std::async(std::launch::async,[&] {
auto start = std::chrono::high_resolution_clock::now();
auto time_point = std::chrono::system_clock::now() + 10s;
auto duration = time_point.time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration);
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - secs);
timespec t{secs.count(),nanos.count()};
auto r = sem_timedwait(&sem,&t);
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start).count() << "ms";
});
std::this_thread::sleep_for(500ms);
std::raise(SIGUSR1);
}