Mecanismos de temporizador permitem agendar o kernel do sistema operacional para notificar um aplicativo quando um tempo predeterminado tiver decorrido. Você normalmente os usará fornecendo duas informações. Primeiro, você precisará especificar quanto tempo o cronômetro deve levar antes de notificar. Em segundo lugar, você precisará preparar uma função de retorno de chamada para agir quando essa notificação ocorrer.

Abordagem Tradicional para Temporizadores

Mecanismos de temporizador em sistemas baseados em Linux e Unix evoluíram para atender a várias necessidades. Diferentes abordagens podem ajudá-lo a resolver diferentes tipos de problemas. No entanto, muitas vezes você verá a primeira versão do alarme() mecanismo ainda em uso.

A função de alarme é a maneira mais simples de usar um temporizador; aqui está o seu protótipo:

não assinadointalarme(não assinadoint segundos);

Usando este método, você só pode especificar o tempo em segundos inteiros. Quando o tempo acabar, o sistema operacional envia o

instagram viewer
SIGALRM sinal para sua aplicação. Para processar a expiração do cronômetro em seu aplicativo, você também deve definir uma função de retorno de chamada.

Aqui está um exemplo de uma função de manipulador de sinal:

#incluir
#incluir
#incluir
#incluir

vaziotimer_callback(int signum)
{
time_t agora = tempo(NULO);
printf("Sinal %d capturado em %li", signum, agora);
}

inta Principal()
{
sinal (SIGALRM, timer_callback);
alarme(1);
dorme(3);
Retorna0;
}

Este código levanta uma SIGALRM sinal depois 1 segundo. Se você quiser aumentar o atraso do temporizador para cinco segundos, basta ligar alarme (5) em vez de. Para parar o temporizador, passe um valor de 0: alarme (0).

Quando o tempo acabar, o cronômetro que você usa não será reiniciado periodicamente. Por exemplo, se você quiser atrasar por mais um segundo, você deve reiniciar o mecanismo com outra chamada para alarme().

Apesar de sua facilidade de uso, este método tem algumas desvantagens:

  • Apenas um temporizador de cada vez.
  • Sem suporte a temporizador periódico.
  • Você só pode fornecer o período de tempo em múltiplos de segundos inteiros.
  • Não há como saber quanto tempo resta em um cronômetro.

Salve o código de exemplo fornecido acima como alarme.c. Quando você compila e executa isso, o programa chamará o timer_callback funcionar após um segundo. Em seguida, aguardará os dois segundos restantes devido à dormir (3) linha e, em seguida, terminar.

$ gcc -o alarme alarme.c
$ hora ./alarme
Sinal 14 capturado em 1653490465
0m1.004s reais
usuário 0m0.000s
sistema 0m0.003s

A razão para usar o comando time é poder ver os tempos. Mas se você observar o resultado, o tempo total de execução não é de três segundos. Isso se deve ao SIGALRM sinal de alarme (1) quando o primeiro segundo termina, enquanto o syscall causado pela função sleep (3) está em execução. Quando este sinal chega, ele interrompe o syscall iniciado para dormir (3).

Usando um temporizador de intervalo

O mecanismo do temporizador de intervalo foi disponibilizado pela primeira vez na versão 4.2 BSD. Foi mais tarde padronizado por POSIX. Suas principais vantagens sobre o tradicional alarme() método de temporizador baseado são:

  • Fornece resolução de microssegundos.
  • Permite controlar a medição do tempo com mais detalhes em três modos diferentes.
  • É possível configurá-lo uma vez e fazê-lo funcionar periodicamente.
  • É possível descobrir quanto tempo está presente em um determinado momento.

Os protótipos de função usados ​​para operações de temporizador de intervalo são os seguintes:

#incluir

intsettimer(int que, const struct itimerval *newValue, struct itimerval *oldValue);
intgettimer(int que, struct itimerval *valor);

estruturaintervalo de tempo
{
estruturatempoitInterval;// próximo valor
estruturatempoitValue;// valor atual
};

estruturatempo
{
grandes tv_sec;
grandes tv_usec;
};

Se você quiser configurar um temporizador de intervalo, você precisará usar o intervalo de tempo estrutura. Você precisará passar um valor usando esta estrutura como o segundo argumento para o Definir temporizador função.

Por exemplo, um temporizador de intervalo que notificará seu aplicativo por 1 segundo e depois a cada 300 milissegundos pode ser configurado da seguinte forma:

estruturaintervalo de temponovoTimer;
estruturaintervalo de tempooldTimer;

newTimer.itValue.tv_sec = 1;
newTimer.itValue.tv_usec = 0;

newTimer.itInterval.tv_sec = 0;
newTimer.itInterval.tv_usec = 300 * 1000;

settimer (ITIMER_REAL, &newTimer, &oldTimer);

Se houver um temporizador de intervalo ativo antes que os novos valores sejam definidos, seus valores são transferidos para o endereço da variável do intervalo de tempo tipo dado ao terceiro parâmetro da função.

Você pode configurar três tipos diferentes de temporizadores com o mecanismo de temporizador de intervalo. Especifique o tipo de temporizador no primeiro parâmetro de settimer():

Tipo de temporizador Sinal Explicação
ITIMER_REAL SIGALRM Independente do tempo gasto pelo aplicativo, calculado sobre o tempo total decorrido.
ITIMER_VIRTUAL SIGVTALRM Calculado ao longo do tempo em que o aplicativo está sendo executado apenas no modo de usuário.
ITIMER_PROF SIGPROF Calculado sobre a soma do tempo gasto pelo aplicativo nos modos de usuário e sistema.

Você pode ver nesta tabela que o ITIMER_REAL tipo envia um SIGALRM sinal, assim como o alarme() função.

Usando um temporizador de intervalo e alarme() na mesma aplicação será confuso. Embora você possa fazer uma segunda verificação do tempo restante com gettimer(), não faz sentido usá-los simultaneamente.

Aqui está um exemplo de definição da função de manipulador de sinal com o cabeçalho de depuração:

#incluir
#incluir
#incluir
#incluir
#incluir
#incluir
#incluir
#incluir "./debug.h"

vaziotimer_callback(int signum)
{
estruturatempoagora;
gettimeofday(&agora, NULO);
printf("Sinal %d capturado em %li.%03li ", signum, now.tv_sec, now.tv_usec / 1000);
}

inta Principal()
{
não assinadoint restante = 3;

estruturaintervalo de temponovo_temporizador;
estruturaintervalo de tempoold_timer;

new_timer.it_value.tv_sec = 1;
new_timer.it_value.tv_usec = 0;
new_timer.it_interval.tv_sec = 0;
new_timer.it_interval.tv_usec = 300 * 1000;

settimer (ITIMER_REAL, &new_timer, &old_timer);
sinal (SIGALRM, timer_callback);

enquanto (dormir (restante) != 0)
{
E se (errno == EINTR)
debugf("sono interrompido por sinal");
senão
errorf("erro de suspensão %s", strerror (errno));
}

Retorna0;
}

O código acima usa o dorme() função para aguardar três segundos. Durante esse tempo, um temporizador de intervalo é executado, primeiro por um segundo, depois em um intervalo de 300 milissegundos.

Para melhor compreensão, salve e compile o código de exemplo com o nome intervalo.c:

$ gcc -o interval interval.c
$ tempo ./intervalo
Sinal 14 capturado em 1653493614.325
debug: sono interrompido por sinal (intervalo principal.c: 36)
Sinal 14 capturado em 1653493614.625
debug: sono interrompido por sinal (intervalo principal.c: 36)
Sinal 14 capturado em 1653493614.925
debug: sono interrompido por sinal (intervalo principal.c: 36)
Sinal 14 capturado em 1653493615.225
debug: sono interrompido por sinal (intervalo principal.c: 36)
Sinal 14 capturado em 1653493615.525
...

Como você pode ver na saída após a execução do cronômetro, ele chama a função de retorno de chamada a cada 300 milissegundos.

No entanto, depois de esperar um pouco mais, você notará que o aplicativo não termina. Ele continua a executar a função de retorno de chamada a cada 300 milissegundos. Se você aumentar o valor do intervalo em milissegundos, verá que o aplicativo termina. Isso ocorre devido à área de uso do dorme() função.

Importância do uso de temporizadores no Linux

Especialmente para aplicações em tempo real, o mecanismo do temporizador é de grande importância. Esta também é uma solução usada para otimizações de desempenho. Você pode até usá-lo para medir o tempo de atividade ou a latência em seu aplicativo. É importante usar mecanismos de temporizador para acompanhar o tempo decorrido e os eventos de transição de tempo.

Como compilar e instalar software da fonte no Linux

Leia a seguir

CompartilharTweetCompartilharE-mail

Tópicos relacionados

  • Programação
  • Programação
  • Dicas para Linux

Sobre o autor

Fatih Küçükkarakurt (10 Artigos Publicados)

Um engenheiro e desenvolvedor de software que é fã de matemática e tecnologia. Ele sempre gostou de computadores, matemática e física. Ele desenvolveu projetos de mecanismos de jogos, bem como aprendizado de máquina, redes neurais artificiais e bibliotecas de álgebra linear. Além disso continua a trabalhar em aprendizado de máquina e matrizes lineares.

Mais de Fatih Küçükkarakurt

Assine a nossa newsletter

Junte-se à nossa newsletter para dicas de tecnologia, análises, e-books gratuitos e ofertas exclusivas!

Clique aqui para assinar