timer_create 总是返回timer_id 0

问题描述 投票:0回答:1

C++ 标准:C++17

我在启动计时器时遇到错误:

Invalid argument

当我检查计时器 id 的值时,它为零 (0),但是我的 timer_create() 正在成功执行,因为它返回 0。

可能是什么问题?

代码

标题

#pragma Once

#include <ctime>
#include <csignal>
#include <cstdint>
#include <functional>
//#include <timerLib.h>

class Timer
{
public:
    Timer(bool periodic = false) : periodic(periodic){}
    ~Timer();
    bool create(void);//Create timer only
    bool create(std::uint64_t timeout);//Create timer, set timeout and start timer
    bool update(std::uint64_t timeout);//Stop timer, update set timeout and start timer
    bool start(std::uint64_t timeout);//Set timeout and start timer
    bool start(void);//Starts the timer with the timeout value (refer private timeout variables)
    bool stop(void);//Stops the timer
    bool destroy(void);//Destroys the timer. Can't be reused without calling create
    using callback_timer_t = std::function<void(void)>;
    void registerCallback(callback_timer_t callback);
private:
    bool                periodic;
    std::uint64_t       timeout;// in nano-seconds
    timer_t             timer_id;
    sigset_t            mask;
    long long           freq_nanosecs;
    struct sigevent     sev;
    struct sigaction    sa;
    struct itimerspec   its;
    static void handler(int sig, siginfo_t *si, void *uc);
    callback_timer_t    callback;
};

来源

#include "timer.hpp"
#include <iostream>
#include <cstdio>

//The range of supported real-time signals is defined by the macros SIGRTMIN and SIGRTMAX.
//Programs should never refer to real-time signals using hard-coded numbers, but instead should always refer to 
//real-time signals using the notation SIGRTMIN+n, and include suitable (run-time) checks that SIGRTMIN+n 
//does not exceed SIGRTMAX
//the top priority RT signal is SIGRTMIN; the least (lowest) priority RT signal is SIGRTMAX.
//If different real-time signals are sent to a process, they are delivered starting with the lowest-numbered signal. 
//(i.e., low-numbered signals have highest priority.)
#define SIG SIGRTMIN

Timer::~Timer()
{
    this->destroy();
}

bool Timer::create(void)
{
    int returnValue;

    //Establish handler for timer signal.
    this->sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;

    sigemptyset(&this->sa.sa_mask);

    if (sigaction(SIG, &this->sa, nullptr) == -1)
    {
        //Log Error
        perror("sigaction");
        return false;
    }
    //Block timer signal temporarily.   
    printf("Blocking signal %d\n", SIG);
    sigemptyset(&mask);
    sigaddset(&mask, SIG);
    if (sigprocmask(SIG_SETMASK, &this->mask, nullptr) == -1)
    {
        perror("sigprocmask");
        return false;
    }
    //Create a timer
    this->sev.sigev_notify = SIGEV_SIGNAL; //Upon timer expiration, generate the signal sigev_signo for the process.
    this->sev.sigev_signo = SIG;
    this->sev.sigev_value.sival_ptr = this;
    returnValue = timer_create(CLOCK_REALTIME, &this->sev, &this->timer_id);
    std::cout << "Timer Create Return Value : " << returnValue << std::endl;
    if(returnValue == -1)
    {
        //Log Error
        perror("timer_create");
        return false;
    }
    //# -> Used with o, x or X specifiers the value is preceeded with 0, 0x or 0X respectively for values different than zero.
    //j -> The length sub-specifier modifies the length of the data type : uintmax_t
    std::printf("timer ID is %#jx\n", (uintmax_t) timer_id); //Only for testing

    return true;
}

bool Timer::create(std::uint64_t timeout)
{
    bool return_status = this->create();
    if(return_status == false)
    {
        return false;
    }
    return this->start(timeout);
}

bool Timer::update(std::uint64_t timeout)
{
    bool return_status = this->stop();
    if(return_status == false)
    {
        return false;
    }
    return this->start(timeout);
}

bool Timer::start(std::uint64_t timeout)
{
    this->its.it_value.tv_sec = 0;
    this->its.it_value.tv_nsec = timeout;
    if(periodic == true)
    {
        this->its.it_interval.tv_sec = 0;
        this->its.it_interval.tv_nsec = timeout;
    }
    else
    {
        this->its.it_interval.tv_sec = 0;
        this->its.it_interval.tv_nsec = 0;
    }
    return this->start();
}

bool Timer::start(void)
{
    int return_status = timer_settime(this->timer_id, 0, &this->its, nullptr);
    if(return_status == -1)
    {
        //TODO Log Error
        perror("timer_settime");
        return false;
    }
    //TODO Remove in final code
    std::cout << "Timer Started\n";
    return true;
}

bool Timer::stop(void)
{
    struct itimerspec its;
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = 0;
    int return_status = timer_settime(this->timer_id, 0, &its, nullptr);
    if(return_status == -1)
    {
        //TODO Log Error
        perror("timer_settime");
        return false;
    }
    //TODO Remove in final code
    std::cout << "Timer Stopped\n";
    return true;
}

bool Timer::destroy(void)
{
    int return_status = timer_delete(this->timer_id);
    if(return_status == -1)
    {
        return false;
    }
    else
    {
        return true;
    }
}

void Timer::registerCallback(callback_timer_t callback)
{
    this->callback = callback;
}

void Timer::handler(int sig, siginfo_t *si, void *uc)
{
    Timer *timer = reinterpret_cast<Timer*>(si->si_value.sival_ptr);
    timer->callback();
}

主要

#include "timer.hpp"
#include <iostream>

void timer_callback(void)
{
    std::cout << "Timeout\n";
}

int main(int argc, char *argv[])
{
    Timer t(true);
    t.registerCallback(timer_callback);
    if(t.create(1000000000ul) == false)
    {
        std::cout << "Timer Create Failed.\tExitting Application.\n";
        return -1;
    }
    while (true)
    {
        /* code */
    }
    
    return 0;
}

输出

Blocking signal 34
Timer Create Return Value : 0
timer ID is 0
timer_settime: Invalid argument
Timer Create Failed.    Exitting Application.

CMakeLists.txt

cmake_minimum_required(VERSION 3.6.2)
 
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
 
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

project(timer_lib C CXX ASM)
 
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -g")
 
SET(MY_TARGET ${PROJECT_NAME}.out)
 
add_executable(${MY_TARGET}
    main.cpp
    timer.cpp
)
linux posix
1个回答
1
投票

tv_nsec
struct timespec
的最大值为
999999999
,小于
1000000000ul
。如果您想睡一秒钟以上,请考虑使用
tv_sec

© www.soinside.com 2019 - 2024. All rights reserved.