c - 自问自答,利用系统信号制作Linux单调定时器

标签 c linux timer signals

在使用MONOTONIC_CLOCK的情况下,很难找到MONOTONIC CLOCK定时器。 还有,想使用 setitimer() 系统 API 的人,在大多数系统中都使用 REALTIME_CLOCK

所以,我调查了 timer_create() api 和 timer_settime() api,它是我想要使用的定时器时钟的更底层控制。

下面是系统信号和定时器的使用示例。

在堆栈溢出中,我没有自己的代码存储库空间。 所以,我正在编写示例代码以进行 self 回答。

最佳答案

它正在使用系统MONOTONIC_CLOCK 计时器。

这是一些使用 linux monotonic timer 调用的例子,它是带有系统保留信号的回调。

我希望有能力的人添加另一个通知线程消息或SIGEV_THREAD代码示例。

examples:: alarmtest.c

在大多数 linux 系统上编译。

gcc -o alarmtest alarmtest.c -lrt

-- 示例源代码 --

/*********************************************************************
   Copyright [2015] [KT Ahn, cpplover@daum.net, kts.ahn@gmail.com]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
**********************************************************************/

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

void timer_handler (int signum)
{
        static int count = 0;

        unsigned int    clktime;
        struct timespec res;
        clock_gettime(CLOCK_MONOTONIC, &res);
        clktime = res.tv_sec*1000+res.tv_nsec/1000000;

        printf("%08d:%s]timer expired %d timers\n",clktime,__FUNCTION__, ++count);
}

void timer_handler_0 (int signum)
{
        static int count = 0;
        unsigned int    clktime;
        struct timespec res;
        clock_gettime(CLOCK_MONOTONIC, &res);
        clktime = res.tv_sec*1000+res.tv_nsec/1000000;

        printf("%08d:%s]timer expired %d timers\n",clktime,__FUNCTION__, ++count);
}

void timer_handler_1 (int signum)
{
        static int count = 0;
        unsigned int    clktime;
        struct timespec res;
        clock_gettime(CLOCK_MONOTONIC, &res);
        clktime = res.tv_sec*1000+res.tv_nsec/1000000;

        printf("%08d:%s]timer expired %d timers\n",clktime,__FUNCTION__, ++count);
}

void timer_handler_2 (int signum)
{
        static int count = 0;
        unsigned int    clktime;
        struct timespec res;
        clock_gettime(CLOCK_MONOTONIC, &res);
        clktime = res.tv_sec*1000+res.tv_nsec/1000000;

        printf("%08d:%s]timer expired %d timers\n",clktime,__FUNCTION__, ++count);
}

void timer_handler_3 (int signum)
{
        static int count = 0;
        unsigned int    clktime;
        struct timespec res;
        clock_gettime(CLOCK_MONOTONIC, &res);
        clktime = res.tv_sec*1000+res.tv_nsec/1000000;

        printf("%08d:%s]timer expired %d timers\n",clktime,__FUNCTION__, ++count);
}

timer_t myTimer(int id, void (*handler), int intms)
{
    struct itimerspec its;
    timer_t timerid;
    struct sigevent sev;
    sigset_t mask;
    struct sigaction sa;
    /* Establish handler for timer signal */

    printf("Establishing handler for signal %d\n", SIGRTMIN+id);

    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGRTMIN+id, &sa, NULL) == -1)
    {
        printf("sigaction error\n");
        return (timer_t)-1;
    }

    /* Block timer signal temporarily */

    printf("Blocking signal %d\n", SIGRTMIN+id);
    sigemptyset(&mask);
    sigaddset(&mask, SIGRTMIN+id);
    if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
    {
        printf("sigprocmask error\n");
        return (timer_t)-2;
    }

    /* Create the timer */

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIGRTMIN+id;
    sev.sigev_value.sival_ptr = &timerid;
    if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) == -1)
    {
        printf("timer_create error\n");
        return (timer_t)-3;
    }

    printf("timer ID is 0x%lx\n", (long) timerid);

    printf("Unblocking signal %d\n", SIGRTMIN+id);
    if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
    {
        printf("sigprocmask error\n");
        return (timer_t)-5;
    }

    /* start the timer */
    its.it_value.tv_sec = intms / 1000;
    its.it_value.tv_nsec = (intms%1000) * 1000000;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        printf("timer_start error\n");
        return (timer_t)-3;
    }

    return timerid;
}

int main ()
{
        struct sigaction sa, sa1, sa2;
        struct itimerval timer, timer1, timer2;

        /* Install timer_handler as the signal handler for SIGVTALRM. */
        memset (&sa, 0, sizeof (sa));
        sa.sa_handler = &timer_handler;
        sigaction (SIGRTMIN+0, &sa, NULL);

        memset (&sa1, 0, sizeof (sa1));
        sa1.sa_handler = &timer_handler_1;
        sigaction (SIGRTMIN+1, &sa, NULL);
        //sigaction (SIGALRM, &sa1, NULL);

        memset (&sa2, 0, sizeof (sa2));
        sa2.sa_handler = &timer_handler_2;
        sigaction (SIGRTMIN+2, &sa, NULL);
        //sigaction (SIGALRM, &sa2, NULL);

        /* Configure the timer to expire after 250 msec... */
        timer.it_value.tv_sec = 0;
        timer.it_value.tv_usec = 250000;

        /* ... and every 250 msec after that. */
        timer.it_interval.tv_sec = 0;
        timer.it_interval.tv_usec = 250000;

        /* Configure the timer to expire after 900 msec... */
        timer1.it_value.tv_sec = 0;
        timer1.it_value.tv_usec = 900000;

        /* ... and every 900 msec after that. */
        timer1.it_interval.tv_sec = 0;
        timer1.it_interval.tv_usec = 900000;

        /* Configure the timer to expire after 1800 msec... */
        timer2.it_value.tv_sec = 1;
        timer2.it_value.tv_usec = 800000;

        /* ... and every 1800 msec after that. */
        timer2.it_interval.tv_sec = 1;
        timer2.it_interval.tv_usec = 800000;

        /* Start a virtual timer. It counts down whenever this process is executing. */
 //       setitimer (ITIMER_REAL, &timer, NULL);
  //      setitimer (ITIMER_REAL, &timer1, NULL);
   //     setitimer (ITIMER_REAL, &timer2, NULL);

        myTimer(1, timer_handler_0, 600);
        myTimer(2, timer_handler_1, 900);
        myTimer(3, timer_handler_2, 1200);
        myTimer(4, timer_handler_3, 1500);
        /* Do busy work.  */
        while (1);
}

结果::

kt.ahn@Linux:~/work/test_c_code$ ./alarmtest
Establishing handler for signal 35
Blocking signal 35
timer ID is 0xb8b010
Unblocking signal 35
Establishing handler for signal 36
Blocking signal 36
timer ID is 0xb8b030
Unblocking signal 36
Establishing handler for signal 37
Blocking signal 37
timer ID is 0xb8b050
Unblocking signal 37
Establishing handler for signal 38
Blocking signal 38
timer ID is 0xb8b070
Unblocking signal 38
2060673821:timer_handler_0]timer expired 1 timers
2060674121:timer_handler_1]timer expired 1 timers
2060674421:timer_handler_0]timer expired 2 timers
2060674421:timer_handler_0]timer expired 2 timers
2060674421:timer_handler_2]timer expired 1 timers
2060674721:timer_handler_3]timer expired 1 timers
2060675021:timer_handler_0]timer expired 3 timers
2060675021:timer_handler_0]timer expired 3 timers
2060675021:timer_handler_1]timer expired 2 timers
2060675621:timer_handler_0]timer expired 4 timers
2060675621:timer_handler_2]timer expired 2 timers
2060675921:timer_handler_1]timer expired 3 timers
2060676221:timer_handler_0]timer expired 5 timers
2060676221:timer_handler_3]timer expired 2 timers
2060676821:timer_handler_0]timer expired 6 timers
2060676821:timer_handler_0]timer expired 6 timers
2060676821:timer_handler_2]timer expired 3 timers
2060676821:timer_handler_1]timer expired 4 timers
2060677421:timer_handler_0]timer expired 7 timers
^C

关于c - 自问自答,利用系统信号制作Linux单调定时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28213478/

相关文章:

C - 出现段错误(核心已转储)

linux - 在 bash 中实现算法

Linux、符号链接(symbolic link) Dir、Meld 和 git

swift - 毫秒计时器?

c - 将指向多维数组的指针作为参数传递

c - 缩小位图字体的算法

c++ - 如何使用 ld 创建共享库?

Java Swing 计时器不工作

iphone - 如何在 objective-c 中取消调度 NSTimer

c - 为什么 GCC 给我这个 `-Wdiscarded-qualifiers` 警告?