【问题标题】:How to have signal handler print time elapsed?如何让信号处理程序打印时间过去?
【发布时间】:2017-03-08 19:34:11
【问题描述】:

我正在编写一个具有 sigaction 处理程序的 C 程序。它还有一个 ittimerval,以防 SIGALRM 有一段时间没有出现。

处理程序应该

  1. 打印完成的无限循环总数
  2. 打印经过的时间
  3. 退出(1);

我注意到信号处理程序不接受自定义参数,所以我有一个全局循环计数器。
我的问题是:我如何获得经过的时间?我可以从计时器中获得这些信息吗?我不完全了解计时器的用法。
此外,代码在终止之前的 fprintf 调用之后打印 1 个额外的整数(来自循环)。如何解决?

代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

int count = 0;

void handler (int code) {
    fprintf(stderr, "Reads completed: %d \n", count);
    exit(1);
}

int main(int argc, char const *argv[])
{
    if (argc != 3) {
        fprintf(stderr, "Usage: time_reads FILENAME TIMER\n");
        exit(1);
    }

    FILE *fp;
    fp = fopen(argv[1], "rb");
    if (fp == NULL) {
        fprintf(stderr, "Fail to open file\n");
        exit(1);
    }

    int i;
    srand(time(NULL));

    struct sigaction sa;
    sa.sa_handler = handler;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM, &sa, NULL);

    struct itimerval timer;
    timer.it_value.tv_sec = strtol(argv[2], NULL, 10    );
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;

    if (setitimer(0, &timer, NULL) < 0) {
        fprintf(stderr, "Fail to set timer\n");
        exit(1);    
    }

    while(1) {
        fseek(fp, (rand() % 100) * sizeof(int), SEEK_SET);
        fread(&i, sizeof(int), 1, fp);
        printf("%d\n", i);
        count++;
    }

    fclose(fp);

    return 0;
}

【问题讨论】:

  • 注意:您不应该从信号处理程序调用 printf()(和朋友)。这不是信号安全的。
  • @wildplasser 谢谢你的提醒,但我必须打电话给它,因为我的任务要求这样做。
  • 请注意,如果信号处理程序退出,则整个程序都会退出。如果您想多次执行此操作,则需要返回信号处理程序,而不是调用exit()。测量经过时间:记录开始时间;在处理程序中,找到当前时间;计算并格式化差异。

标签: c signals sigaction setitimer


【解决方案1】:

为了打印经过的时间,处理程序必须有权访问计时器。一个简单的方法是让计时器也成为一个全局变量,就像计数器一样。对于打印的额外整数,这是因为信号在调用 printf() 的过程中中断了循环。循环中的 printf() 应该被移除,因为循环迭代的总数将被信号处理程序打印出来。

【讨论】:

  • 循环中的 printf() 应该去掉吗?不!那只是简单地改变程序的目的。请在回答之前仔细考虑。
  • 我的错误,看起来需要 printf() 来打印文件中的数据。在这种情况下,无法阻止处理程序在调用 printf() 期间中断主循环。这有时会导致在处理程序已经打印经过的时间之后打印最终的整数。另一种方法是让处理程序设置一个布尔值,并在布尔值更改时让循环正常退出。在这种情况下,主函数将在循环之后、最终退出之前打印经过的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多