在linux C中的特定时间发送信号

时间:2018-04-16 15:07:31

标签: linux time signals interrupt

我正在为树莓编写一个C程序,我需要在特定的时间做一些事情(在我的情况下是在午夜)。 我不想每次像“轮询”那样检查时间,但我想使用信号生成一个中断软件,让处理程序完成他的工作。 在这个例子中,我能够设置第一个中断,但是在TIMER_FREQUENCY之后它不会发送下一个中断,所以我在处理程序中创建了一个新的计时器,以便连续一个新的计时器在TIMER_FREQUENCY秒后过期。

示例

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/wait.h>

/* 3h = 3 * 60 * 60*/
#define TIMER_FREQUENCY 10800

static int count;

void timer_expired(int sig)
{
    /* Set new timer for next interrupt - 3 hours*/
    struct sigaction act;
    clockid_t clock_id;
    timer_t timer_id;
    struct sigevent clock_sig_event;
    struct itimerspec timer_value;
    int ret;

    /* timestamp */
    time_t now;
    struct tm* tm_info;

    char *temp=(char*)malloc(20*sizeof(char));

    /* Register new action for SIGUSR1 */
    memset(&act, 0, sizeof(struct sigaction));
    act.sa_handler =  timer_expired;
    ret = sigaction(SIGUSR1, &act, NULL);
    assert(ret == 0);

    clock_id = CLOCK_MONOTONIC;
    memset(&clock_sig_event, 0, sizeof( struct sigevent));
    clock_sig_event.sigev_notify = SIGEV_SIGNAL;
    clock_sig_event.sigev_signo = SIGUSR1;
    clock_sig_event.sigev_notify_attributes = NULL;
    /* Creating process interval timer */
    ret = timer_create(clock_id, &clock_sig_event, &timer_id);
    assert(ret == 0);

    /* setitng timer interval values */
    timer_value.it_interval.tv_sec = TIMER_FREQUENCY;
    timer_value.it_interval.tv_nsec = 0;

    /* setting timer initial expiration values*/
    memset(&timer_value, 0, sizeof(struct itimerspec));
    timer_value.it_value.tv_sec = TIMER_FREQUENCY;
    timer_value.it_value.tv_nsec = 0;

    /* Prendo l'orario attuale */
    time(&now);
    tm_info=localtime(&now);
    strftime(temp,20,"%H:%M:%S",tm_info);

    count++;

    // use this handler
    printf("Ricevuto %d° segnale alle ore: %s \n",count,temp);

    printf("Attendo segnale fra 3 ore...\n");

    /* Create timer */
    ret = timer_settime(timer_id, 0, &timer_value, NULL);
    assert(ret == 0);

}

int main(void)
{
    struct sigaction act;
    clockid_t clock_id;
    timer_t timer_id;
    struct sigevent clock_sig_event;
    struct itimerspec timer_value;
    int ret;


    char *giorno=(char*)malloc(3*sizeof(char));
    char *ora=(char*)malloc(3*sizeof(char));
    char *minuti=(char*)malloc(3*sizeof(char));
    char *secondi=(char*)malloc(3*sizeof(char));

    time_t fine, now;
    struct tm* tm_info;

    char *temp=(char*)malloc(20*sizeof(char));

    double seconds=0.0;
    long int intervallo=0;
    float ore=0.0;

    count=0;

    /* Here i get seconds from now until 23:59:59 to set first timer */

    time(&now);
    time(&fine);
    tm_info=localtime(&now);

    strftime(giorno,3,"%d",tm_info);
    strftime(ora,3,"%H",tm_info);
    strftime(minuti,3,"%M",tm_info);
    strftime(secondi,3,"%S",tm_info);

    sprintf(temp,"%d:%d:%d",23,59,59);
    strptime(temp,"%H:%M:%S",tm_info);
    fine=mktime(tm_info);

    time(&now);

    // get seconds until fine
    seconds=difftime(fine,now);

    intervallo=(long int)seconds;
    ore=intervallo/3600;
    printf("Secondi restanti fino alle 23:59:59 : %lis = %f ore \n",intervallo, ore);

    count=0;
    /* Register new action for SIGUSR1 */
    memset(&act, 0, sizeof(struct sigaction));
    act.sa_handler =  timer_expired;
    ret = sigaction(SIGUSR1, &act, NULL);
    assert(ret == 0);

    clock_id = CLOCK_MONOTONIC;
    memset(&clock_sig_event, 0, sizeof( struct sigevent));
    clock_sig_event.sigev_notify = SIGEV_SIGNAL;
    clock_sig_event.sigev_signo = SIGUSR1;
    clock_sig_event.sigev_notify_attributes = NULL;

    /* Creating process interval timer */
    ret = timer_create(clock_id, &clock_sig_event, &timer_id);
    assert(ret == 0);

    /* setitng timer interval values */
    timer_value.it_interval.tv_sec = intervallo;
    timer_value.it_interval.tv_nsec = 0;

    /* setting timer initial expiration values*/
    memset(&timer_value, 0, sizeof(struct itimerspec));
    timer_value.it_value.tv_sec = intervallo;
    timer_value.it_value.tv_nsec = 0;

    /* Create timer */
    ret = timer_settime(timer_id, 0, &timer_value, NULL);
    assert(ret == 0);

    /* Now we have a timer with following features:
     * It will expire after 24 hours and excute fucntion timer_expired
     * upon expiration */

    /* I've used sleep into while because I just want to wait and handle the interrupt using less CPU as possible */
    while(1){
        sleep(500);  
    }

    /*
     * Do something here
     *
     * To test, sleep()  for 5 sec and set timer expiry as 1 sec i.e.
     * TIMER_FREQUENCY as 1.
     * In this case first timer will expire after 1 sec and sleep will
     * come out, also timer_expired() will be executed. Later time will expire after every 1 sec.
     *
     * We can also use SIGEV_THREAD instead of SIGEV_SIGNAL in clock_sig_event.sigev_notify
     * while creating timer_id using timer_create().In that case we need to check for other parameter
     * as well.
     */

    exit(EXIT_SUCCESS);
}

这是输出:

pi@raspberrypi:~/Desktop/TastoW/rtc $ ./rtc
Secondi restanti fino alle 23:59:59 : 22200s = 6.000000 ore 
Ricevuto 1° segnale alle ore: 23:59:59 
Attendo segnale fra 3 ore...
Ricevuto 2° segnale alle ore: 02:59:59 
Attendo segnale fra 3 ore...
Ricevuto 3° segnale alle ore: 05:59:59 
Attendo segnale fra 3 ore...
Ricevuto 4° segnale alle ore: 08:59:59 
Attendo segnale fra 3 ore...

1 个答案:

答案 0 :(得分:1)

Register an alarm using timer_create() and timer_settime().

Also register SIGALRM handler using sigaction() so that when timer expires signal handler will be executed. Now you can use handler to do the stuffs.

Please note that always use async-signal-safe functions function in signal handler.

Example

const stringRequired = string => !!string.length
const numberRequired = number => Number.isInteger(number)

const validadeInput = (value, initial, validade) => (
  validade(value) ? value : initial
)

const input = (obj, key, initial, validade) => (
  typeof obj[key] !== 'undefined' ?
  validadeInput(obj[key], initial, validade) :
  initial
);

const addValue = (obj, key, value) => {
  const prop = {}
  prop[key] = value
  return Object.assign(obj, prop)
}

const addFilter = (obj, key, value, validate) => (
  validate(value) ? addValue(obj, key, value)
  : obj
)

const selector = (query = {}) => {
  const limit = input(query, 'limit', 10, numberRequired);
  const name = input(query, 'name', '', stringRequired);

  let select = {}

  select = addFilter(select, 'name', name, stringRequired);
  select = addFilter(select, 'limit', limit, numberRequired);

  return select
}

console.log(selector()); 
// { limit: 10 }
console.log(selector({ name: 'David Costa' })); 
// { limit: 10, name: 'David Costa' }
console.log(selector({ limit: 50 }));
// { limit: 50 }