通过信号中断睡眠 我想编写一个C++程序,它应该等待Linux信号(毫秒分辨率),但我无法找到实现这个目的的可能。

通过信号中断睡眠 我想编写一个C++程序,它应该等待Linux信号(毫秒分辨率),但我无法找到实现这个目的的可能。,c++,linux,c++17,system-calls,usleep,C++,Linux,C++17,System Calls,Usleep,以下测试代码应在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() {

以下测试代码应在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);
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std::chrono_文本;
外部“C”无效处理程序(int s){
}
int main(){
std::信号(SIGUSR1,处理器);
bool start=false;
自动f=std::async(std::launch::async,[&]{
自动启动=标准::时钟::高分辨率时钟::现在();
开始=真;
//美国LEEP(1000000);
睡眠(1);
//std::this_线程::sleep_for(1s);

std::cout程序在执行信号处理程序后返回正常操作。睡眠不会终止,因为它与注释中处理信号的线程不同

相反,这个答案建议使用互斥来阻止操作

同时显示线程ID(显示它们是不同的线程),可以改为:

#包括
#包括
#包括
#包括
#包括
使用名称空间std::chrono_文本;
std::timed_mutex mtx;
外部“C”无效处理程序(int s){

std::cout程序在执行信号处理程序后返回正常操作。睡眠不会终止,因为它与注释中处理信号的线程不同

相反,这个答案建议使用互斥来阻止操作

同时显示线程ID(显示它们是不同的线程),可以改为:

#包括
#包括
#包括
#包括
#包括
使用名称空间std::chrono_文本;
std::timed_mutex mtx;
外部“C”无效处理程序(int s){

有了ti7和user4581301的想法,我终于找到了一个解决方案

在signal_处理程序中使用互斥体,但仅限于允许的系统调用集,我使用信号量

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, 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);
}
sem_t*sem_g=nullptr;
外部“C”无效处理程序(int s){
if(sem_g)
sem_post(sem_g);
}
int main(){
sem_t sem={};
sem_init(&sem,0,0);
sem_g=&sem;
std::信号(SIGUSR1,处理器);
自动f=std::async(std::launch::async,[&]{
自动启动=标准::时钟::高分辨率时钟::现在();
自动时间点=标准::计时::系统时钟::现在()+10s;
自动持续时间=时间\u点。自\u epoch()起的时间\u;
自动秒=std::chrono::duration\u cast(持续时间);
自动nanos=std::chrono::持续时间(持续时间-秒);
timespec t{secs.count(),nanos.count()};
自动r=sem\u timedwait(&sem,&t);

有了ti7和user4581301的想法,我终于找到了一个解决方案

在signal_处理程序中使用互斥体,但仅限于允许的系统调用集,我使用信号量

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, 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);
}
sem_t*sem_g=nullptr;
外部“C”无效处理程序(int s){
if(sem_g)
sem_post(sem_g);
}
int main(){
sem_t sem={};
sem_init(&sem,0,0);
sem_g=&sem;
std::信号(SIGUSR1,处理器);
自动f=std::async(std::launch::async,[&]{
自动启动=标准::时钟::高分辨率时钟::现在();
自动时间点=标准::计时::系统时钟::现在()+10s;
自动持续时间=时间\u点。自\u epoch()起的时间\u;
自动秒=std::chrono::duration\u cast(持续时间);
自动nanos=std::chrono::持续时间(持续时间-秒);
timespec t{secs.count(),nanos.count()};
自动r=sem\u timedwait(&sem,&t);

这是正确的,但是睡眠应该被信号中止,这样它才能完成faster@gerum低级系统调用可能会被信号中断,但
的高级
sleep\u不会中断。例如,您可以看到libstdc++的实现处理
EINTR
并在剩余时间内继续休眠LD更倾向于不使用未定义的行为,我在代码中看到了两个可能的UB源。首先,您在MealAlxHand中解锁互斥体,但我不确定它是否与主线程相同,必须解锁互斥体。在信号处理程序中使用互斥体,但我不认为,在外部“C”中使用C++类。函数定义得很好。@MilesBudnek是的,我认为这个线程sleep只是为了完整性而添加的,我真的不希望它能工作,但是带有sleep或usleep的版本应该可以工作。旁注:在信号处理程序中有一些危险的东西。@gerum只是从不同的上下文中锁定解锁,但是除了在信号处理程序,至少在*nix系统中是这样。这是正确的,但是睡眠应该被信号中止,这样它才能完成faster@gerum低级系统调用可能会被信号中断,但
的高级
sleep\u不会中断。例如,您可以看到libstdc++的实现处理
EINTR
并继续执行在剩下的时间里,我不想使用未定义的行为,我在代码中看到了UB的两个可能来源。首先,你在signal_处理程序中解锁互斥体,但我不确定这是否与主线程相同,在主线程中,你必须解锁互斥体。你在signal处理程序中使用互斥体,但我不认为,使用外部C语言中的C++类函数定义得很好。@MilesBudnek是的,我认为这个线程sleep只是为了完整性而添加的,我真的不希望它能工作,但是带有sleep或usleep的版本应该可以工作。旁注:在信号处理程序中有一些危险的东西。@gerum只是从不同的上下文中锁定解锁,但是除了在信号处理程序,至少在*nix系统中是这样。使用信号和计时器文件描述符很容易做到这一点,但这是一个相当高级的主题。从Linux手册页面开始,了解timerfd和signalfd系统调用,然后从那里开始工作。这是吗