Tempo No Linux

download Tempo No Linux

of 66

Transcript of Tempo No Linux

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

Relatrio Tcnico

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Florianpolis, dezembro de 2001.

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

2

SumrioSumrio ............................................................................................................................... 2 1. Introduo ....................................................................................................................... 3 2. Relgios de Hardware do PC - Pentium ......................................................................... 5 2.1 Real Time Clock (RTC)............................................................................................ 5 2.2 Time Stamp Counter (TSC) ...................................................................................... 6 2.3 Programmable Interval Timer (PIT) ......................................................................... 7 3. Obtendo a Hora ............................................................................................................. 10 3.1 Funo Time ........................................................................................................... 10 3.2 Funo Ftime .......................................................................................................... 10 3.3 Funo Gettimeofday.............................................................................................. 11 3.4 Acesso Direto ao RTC ............................................................................................ 12 3.5 Funes de Formatao do Tempo ......................................................................... 13 4. Medindo a Passagem do Tempo ................................................................................... 16 4.1 Diferena na Hora ................................................................................................... 16 4.2 Utilizando o TSC .................................................................................................... 17 5 Esperando o Tempo Passar ............................................................................................ 21 5.1 Funo Sleep........................................................................................................... 21 5.2 Funo Usleep......................................................................................................... 21 5.3 Funo Nanosleep................................................................................................... 21 5.4 Preciso das Funes Sleep .................................................................................... 22 6 Sinais, Temporizadores e Alarmes ................................................................................ 28 6.1 Os Sinais ................................................................................................................. 28 6.2 Funo Signal.......................................................................................................... 29 6.3 Funo Sigaction..................................................................................................... 30 6.4 Funo Kill.............................................................................................................. 32 6.5 Funo Alarm.......................................................................................................... 32 6.6 Sinais de Tempo Real ............................................................................................. 33 6.7 Implementao de Temporizadores e Alarmes....................................................... 33 7. Tarefas Peridicas ......................................................................................................... 36 8. Concluso...................................................................................................................... 44 Referncias Bibliogrficas ................................................................................................ 66

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

3

1. IntroduoO sistema operacional Linux [1] um sistema operacional tipo Unix, com cdigo fonte aberto e disponvel atravs de licena GPL, isto , de graa mediante certas restries. Este sistema tornou-se muito popular nos ltimos anos, tanto para uso em mquinas desktop como para uso em mquinas servidoras. Graas a sua robustez, seu bom desempenho e a disponibilidade de ambientes de desenvolvimento, tem sido cada vez mais usado como base para aplicaes de automao industrial. Muitas aplicaes do Linux necessitam manipular medidas de tempo, de alguma forma. Por exemplo, em sistemas de automao necessrio executar tarefas peridicas. Na comunicao de dados comum a utilizao de temporizaes para detectar time-outs. Para registrar eventos necessrio saber a hora corrente. Para medir desempenho necessrio medir a durao de intervalos de tempo. Freqentemente os programadores deparam-se com situaes onde devem lidar com valores e medies de tempo, alm de orientar o prprio fluxo de execuo em funo da passagem do tempo, como no caso de alarmes e tarefas peridicas. O sistema operacional Linux prov diversos mecanismos para manipular o tempo em nvel de aplicao. Diversas chamadas de sistema esto disponveis para isto. Entretanto, algumas vezes o uso desses mecanismos exige cuidados na programao. Medidas de tempo em computadores so sempre aproximadas, mas uma programao cuidadosa capaz de minimizar os erros. Alm disso, alguns "truques" de programao no so bvios a partir da simples leitura da descrio das chamadas de sistema e rotinas da biblioteca. O objetivo deste texto orientar o leitor sobre os recursos existentes no sistema operacional Linux para a manipulao do tempo, em nvel de aplicao. No sero descritos mtodos que exijam a alterao do kernel do Linux nem que necessitem a preparao de mdulos para serem incorporados dinamicamente ao kernel. A informao na qual este texto foi baseado est dispersa em livros, faqs e manuais de usurio. O propsito portanto reunir em um s manual todas as informaes relevantes para um programador de aplicao que necessite lidar com o tempo em seu programa. No do conhecimento dos autores outro texto que concentre as informaes relacionadas com a manipulao do tempo por aplicaes executando no sistema operacional Linux. A maior parte do texto trata de recursos existentes no sistema operacional Linux. Dessa forma, eles estaro disponveis em qualquer arquitetura para o Linux for portado. Entretanto, tambm sero descritos alguns recursos que esto disponveis apenas na arquitetura PC Pentium, pois utilizam registradores especficos desse processador. Como esta a arquitetura mais utilizada para executar Linux, tais informaes sero teis para muitas pessoas. Embora o texto tenha sido escrito com base na verso 2.4 do Linux, a maioria das chamadas de sistema utilizada comum e esto disponveis em todas as outras verses. Muitas delas seguem o padro POSIX [2] e podem ser encontradas tambm em outros sistemas operacionais. A seo 2 deste trabalho descreve como so os relgios de hardware presentes na arquitetura PC baseada no processador Intel Pentium. Os relgios de hardware so a base para a marcao do tempo no computador e o seu conhecimento facilita a compreenso das possibilidades e limitaes da marcao do tempo no sistema. A seo 3 mostra como possvel obter a hora, atravs de chamadas de sistema. A seo 4 descreve duas maneiras diferentes de medir a passagem do tempo: usando a diferena entre horas e usando o registrador Time Stamp Clock. Na seo 5 so

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

4

descritas as vrias formas que o programador dispe para esperar o tempo passar. Os mecanismos dos temporizadores e dos sinais so descritos na seo 6. Essa mesma mostra como uma aplicao pode estabelecer alarmes do tipo time-out. As diferentes formas possveis de implementar tarefas peridicas so apresentadas na seo 7. Finalmente, a seo 8 traz algumas concluses. No anexo esto includas informaes sobre as chamadas de sistema e rotinas de biblioteca utilizadas ao longo do texto.

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

5

2. Relgios de Hardware do PC PentiumO kernel do Linux interage com trs relgios de hardware diferentes: Real Time Clock (RTC), Time Stamp Counter (TSC) e o Programmable Interval Time (PIT). Como veremos a seguir, os dois primeiros auxiliam o kernel a obter a data e hora atual e o ultimo programado para gerar interrupes fixas em uma freqncia determinada pelo kernel, que sero importantes para execuo de tarefas do kernel e de programas do usurio [1].

2.1 Real Time Clock (RTC)O Real Time Clock, RTC, ou relgio de tempo real, um relgio de hardware implementado por um circuito integrado, geralmente o Motorola 146818 e integrado a placa me, mais precisamente ao CMOS RAM, presente em todos os PCs atuais. Sua funo registrar a data e a hora atual. Ele alimentado por uma pequena bateria, a mesma que alimenta a memria com a configurao do hardware do PC, ou seja, esse relgio continua funcionando mesmo com o PC desligado. Com relao a sua preciso, espera-se um erro de 10 segundos a cada ms. Alm de registrar a data e a hora, pode funcionar como um timer, gerando interrupes na IRQ 8 quando seu relgio atingir determinado valor. O Motorola 146818 possui a seguinte estrutura interna [3]:

A CMOS RAM possui 64 bytes, onde esto gravados dados da BIOS, como configurao da mquina e a data e hora providos pelo RTC. Os endereos de memria internos da CMOS so:Endereo: 0x00 0x02 0x04 0x06 0x07 0x08 0x09 0x32 Contedo Segundos Minutos Horas Dia da semana Dia do ms Ms Ano Sculo

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

6

A palavra contida em cada endereo possui 1 byte, sendo atualizada sempre pelo RTC e est no formato BCD. O acesso essas informaes so feitas nos endereos 0x70 e 0x71 das portas de entrada / sada da mquina. Por exemplo, se quisermos ter o valor do minuto corrente, devemos inserir o valor do endereo da CMOS RAM correspondente a minutos no endereo 0x70 do PC, e a leitura ser feita no endereo 0x71. Pode ser implementado em C da seguinte forma (leitura dos minutos, por exemplo):unsigned short int minuto; outb (0x02,0x70); minutos=inb (0x71);

Na primeira linha declarada a varivel minuto. Na segunda, escreve-se na porta 0x70 o valor correspondente ao endereo da CMOS RAM a qual se quer ter acesso, que em nosso caso 0x02 que corresponde ao campo onde o RTC registra o valor dos minutos. Na terceira, guarda-se na varivel minuto o valor correspondente ao minuto atual, lido na porta 0x71. No devemos esquecer que este valor est no formato BCD. O Linux usa o RTC somente para ler a data e a hora atual. Ele faz isso apenas uma vez, quando o kernel iniciado. Para manter a hora atualizada, o kernel usa um outro artifcio. Aps ler a hora do RTC, ele no o usa mais para saber a hora e data atual. A hora em vigor no sistema ento a hora lida no RTC atualizada atravs de timers, como veremos adiante. O administrador do sistema pode tambm setar esse clock usando o programa de sistema /sbin/clock para agir diretamente nessas duas portas, ou pode program-lo atravs de /dev/rtc.

2.2 Time Stamp Counter (TSC)O Time Stamp Counter, ou TSC, um registrador que comeou a estar presente na famlia dos microprocessadores 80x86 a partir do Pentium. Ele um registrador de 64 bits que incrementado a cada sinal, ou perodo de clock, ou seja, a cada frao de tempo correspondente ao inverso do clock do processador em Hz. Por exemplo, em um Pentium de 500 MHz, o TSC incrementado a cada 2 nanosegundos. O TSC uma ferramenta de alta preciso para a medio de tempo em PCs. O valor desse registrador pode ser acessado pela funo implementada em C abaixo:static inline long long unsigned lrdtsc (void) { long long unsigned time; __asm__ __volatile__ (rdtsc:=A(time)); return time; }

O Linux se aproveita do TSC pelo fato dele ser muito mais preciso que os derivados do Programmable Interval Time (PIT). Um exemplo de aplicao do TSC a determinao da freqncia real do clock do processador, tarefa que o Linux faz quando iniciado. Essa freqncia obtida pela contagem de sinais de clock durante um intervalo de tempo pr-estabelecido (mais precisamente, 50,00077 milisegundos) gerado por um dos canais do PIT. Assim, a freqncia do processador ser o nmero de sinais de clock divido pelo tempo pr-determinado em que ocorreram (freqncia em Hz = sinais do clock / tempo em segundos).

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

7

2.3 Programmable Interval Timer (PIT)O PIT, ou Programmable Interval Timer a terceira forma de medio de tempo utilizada pelo Linux. O kernel o usa para gerar perodos de tempo com uma freqncia fixa. O PIT implementado nos PCs pelo circuito integrado 8253 ou 8254 CMOS, que utiliza os endereos de 0x40 a 0x5F das portas de entrada e sada. Cada PC possui ao menos um PIT, e cada um, trs canais. O primeiro canal usado para atualizao da hora, o segundo para controlar a atualizao (refresh) da memria RAM e o terceiro para gerao de ondas quadradas para o alto-falante do PC. O PIT recebe um sinal de clock no valor de 1.19318 MHz, e conectado ao C.I. 8259, que o responsvel pela gerao de interrupes do micro.

O PIT possui um contador, que decrementado a cada sinal de clock. Os endereos de memria usados pelo primeiro PIT so [4]: 0x40 - Contador do canal 0 (leitura / escrita). 0x41 - Contador do canal 1 (leitura / escrita). 0x42 - Contador do canal 2 (leitura / escrita). 0x43 - Palavra de Controle (somente escrita). Os dois bits mais significativos da palavra de controle so responsveis pela escolha do canal a ser utilizado (00b para o canal 0, 01b para o canal 1 e 10b para o ultimo canal). Os prximos dois bits definem o modo de escrita/leitura, sendo: 0 (00b) - Contador fechado: O contador passa a operar internamente, mas ao ser lido em seu endereo de memria tem-se a impresso que est parado naquele valor. 1 (01b) - Leitura e escrita do byte menos significativo. 2 (10b) - Leitura e escrita do byte mais significativo. 3 (11b) - Leitura e escrita dos bytes mais e menos significativos. Os prximos trs bits definem o modo em que o PIT ir funcionar, que so: Modo 0 (000b) - Interrupo ao final da contagem: Contagem regressiva. A interrupo ser ativada aps o trmino da contagem estabelecida no seu endereo de memria. Uma nova contagem ser iniciada e a interrupo desligada quando for escrito um novo valor no contador do canal. Modo 1 (001) - Semelhante ao primeiro modo, mas nesse caso a contagem pode ser reiniciada sem a necessidade de escrever novamente o valor do contador. Modo 2 (010b) - Gerador de freqncia: A cada perodo de tempo prdeterminado gerado uma interrupo. Modo 3 (011b) - Gerador de onda quadrada: Gera uma onda quadrada de freqncia pr-determinada. Modo 4 (100b) - Similar ao modo 0, sendo que a interrupo iniciada ativada e aps o final da contagem desligada. Modo 5 (101b) - Similar ao anterior, mas a contagem aguarda um sinal de hardware para iniciar a contagem.

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

8

O bit menos significativo da palavra de controle configura o padro do nmero do contador: 0b - Binrio de 16 bits. 1b - BCD de 4 dcadas O Linux programa o primeiro PIT para gerar interrupes na IRQ 0, a freqncia de 100 Hz, ou seja, com um perodo de 10 milisegundos (o programa no modo 3, gerador de freqncia). A cada interrupo, ou seja, a cada instante em que se passaram mais 10 milisegundos ocorre o que chamamos de tick. Esses ticks so utilizados para sinalizar todas as atividades do sistema. Por exemplo: atualizar a hora no sistema, atualizar as estatsticas dos recursos usados no kernel, determinar quanto tempo esta ocupando a CPU determinado processo e se esse j estourou o tempo de limite de uso, enfim, vrias atividades de responsabilidade do kernel. O tick de 10 milisegundos o padro adotado pelo Linux. Pode ser alterado, mas devemos ter em mente certos fatores. Ticks curtos produzem melhores repostas do sistema. Isto devido resposta do sistema ser largamente dependente de quo rpido um processo rodando preemptado por um processo de alta prioridade assim que ele se tornou executvel. Alm disso, o kernel usualmente verifica se o processo rodando pode ser preemptado enquanto for tratada uma interrupo de timer. Ou seja, ticks curtos requerem que a CPU gaste uma larga frao de seu tempo em Modo Kernel, isto , tem uma menor frao de tempo no Modo Usurio. Como conseqncia disso, programas do usurio rodaro devagar. Portanto, somente mquinas com muito poder de processamento podem adotar ticks curtos e arcar com as conseqncias. Atualmente, somente o Compaq Alpha apresenta um tick em torno de um milisegundo (1024 interrupes por segundo). A seguir veremos como o Linux programa o PIT. Como vimos, seu contador decrementado a cada sinal de clock, que 1.19318 MHz. Assim, a cada segundo, o contador decrementado de 1193180 unidades. Para que seja zerada uma interrupo a cada 10 ms, um centsimo de segundo, esse valor dever ser dividido por 100. O Linux o faz da seguinte forma: O kernel possui uma varivel interna, Hz (asm/param.h), que setada em 100. H outra varivel, chamada de Clock_tick_rate (asm/timex.h), que setada em 1193180. E a ltima varivel, que ser a gravada no endereo de memria do contador do canal 0, chamada de Latch (asm/timex.h), a razo entre Clock_tick_rate e Hz, e que ser usada para programar o PIT e nos fornecer interrupes a cada 10 milisegundos. O PIT ento inicializado pela funo init_IRQ() (arch/i386/kernel/i8259.c), que possui a seguinte programao em C:outb_p (0x34, 0x43); outb_p (LATCH & 0xFF, 0x40); outb (LATCH >> 8, 0x40);

A funo outb() em C equivalente a mesma instruo em assembly: ela copia o primeiro operando para o endereo de memria especificado no segundo operando. Nessa primeira operao, o Linux grava a palavra 0x34 no endereo de memria da palavra de controle do PIT. A palavra em 0x34 corresponde a 00110100 em binrio. O bit menos significativo 0, e como vimos, define que o valor gravado no contador do canal ser em binrio de 16 bits. Os prximos trs, 010b, definem o modo 2, que ser um gerador de freqncia. Os prximos dois, 11b, permitem a leitura e escrita dos bytes menos e mais significativos do contador. E os dois bits mais significativos, 00b, informam que ser usado o primeiro canal (canal 0) do PIT. A funo outb_p()

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

9

similar a outb(). A primeira linha um comando para o PIT para assumir a interrupo para uma nova taxa. A segunda e terceira linha fornece uma nova taxa para o 8254. A constante LATCH uma varivel de 16 bits, e a porta 0x40 de apenas 8 bits. Com 2 bytes consecutivos. Como resultado o PIT est programado para gerar interrupes a cada 10 milisegundos. Para se fazer uso da funo outb() em um programa do usurio acessando endereos de portas I/O necessrio logar-se como super-usurio e usar o a funo ioperm() para habilitar o acesso a esses endereos, como ser descrito na seo 3.4.

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

10

3. Obtendo a HoraPara se obter a hora no Linux atravs de chamadas de sistema, em nvel de programao, tem-se disponveis as seguintes funes: time(); ftime() e gettimeofday(). Podemos tambm fazer acesso a informaes sobre hora atravs do acesso direto ao RTC, como explicado na seo anterior e que ser visto novamente com mais algumas consideraes. Existem tambm as funes responsveis pela formatao das unidades de tempo, como ctime(), asctime(), gmtime(), localtime(), mktime() e strftime(). A seguir, veremos o uso e caracterstica de cada forma de se obter a hora no PC em nvel de programao em C [5].

3.1 Funo TimeA funo time() a mais simples de todas. Com ela obtemos apenas um valor, que o nmero de segundos passados desde a primeira hora do dia primeiro de janeiro de 1970. Esse valor no conta os segundos que foram retirados ou acrescentados ao calendrio desde ento para correo do prprio. Para ela, cada dia transcorrido desde ento possu exatamente 24 horas. A funo declarada da seguinte forma: time_t time (time_t *time), sendo time um ponteiro para a rea de memria contendo o tempo em segundos. necessria a incluso de time.h para o funcionamento da mesma, j que esta contm a estrutura time_t. Podemos fazer uso da funo time() da seguinte forma:time_t time; time (&time);

Assim, na varivel time teramos agora o valor de tempo em segundos transcorridos desde 1970, GMT (horrio do Meridiano de Greenwich). A funo time() retorna zero quando bem sucedida e -1 quando no. Time_t uma varivel definida em time.h como long int. A funo time() demora em mdia 2200 ciclos de clock de CPU para ser executada, considerando sua execuo com prioridade normal e interrupes do kernel do Linux habilitadas, alm de outros processos em atividade. Para se chegar em tal valor de ciclos de clock, se faz uso da funo lrdtsc() demonstrada na seo anterior. Faz-se uma chamada antes e uma depois da funo time(), e o nmero de ciclos ser a subtrao do valor fornecido da segunda pela primeira, alm de descontarmos o nmero de ciclos de clock que a lrdtsc() tambm consome. Operaes que exigem preciso no podero ser feitas com a funo time(). Por definio, a melhor resoluo que conseguimos com ela de 1 segundo, ou seja, o erro em mdia meio segundo. Assim, ela s poderia ser usada para execuo de tarefas de controle por exemplo em processos com uma resposta extremamente lenta.

3.2 Funo FtimeA funo ftime() mais elaborada que a time(). Possui uma estrutura de dados interna que nos fornecem mais informaes sobre a hora atual. Era a funo principal na obteno da hora no Unix BSD verso 4.2, sendo ento suplantada pela funo

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

11

gettimeofday() na verso 4.3 desse sistema operacional. A estrutura interna usada a seguinte:struct timeb { time_t time; short unsigned millitm; short timezone; short dstflag; }

Onde, em time teremos o nmero de segundos transcorridos desde primeiro de janeiro de 1970, GMT, igual a ao retornado pela funo time(); millitm nos d os milisegundos transcorridos desde ento; timezone o valor em minutos a oeste do meridiano de Greenwich em que nos encontramos; dstflag ser setado em 1 se estivermos nos horrio de vero ou 0 se no. A biblioteca a ser inclusa para seu uso, onde declarada essa estrutura timeb, a sys/timeb.h. A chamada de ftime() na forma int ftime (struct timeb *time). Abaixo, time ser a varivel que acessar as informaes sobre a hora. A funo ftime() sempre retorna 0. Para fazer uso da funo, declaramos a varivel time:struct timeb time;

A chamada a funo ser ento:Ftime (&time);

Assim, a partir de time, podemos acessar os dados da estrutura timeb que contero as informaes sobre a hora no momento em que ftime() fora chamada. A funo ftime() demora em mdia 500 ciclos de clock da CPU para ser executada, considerando sua execuo com prioridade normal e interrupes do kernel do Linux habilitadas, alm de outros processos em atividade. Ftime(), como vimos na sua varivel millitm, apresenta um resoluo de milisegundos. Sua execuo e suas operaes internas demoram na ordem de centenas de nanosegundos, tempo cerca de mil vezes menor que sua menor unidade de medio de tempo. Sendo assim, bastante precisa, e pode ser usada em operaes onde se exija uma preciso de milisegundos.

3.3 Funo GettimeofdayA funo gettimeofday() a funo mais utilizada atualmente para a obteno da hora atual. Passou a ocupar o lugar da ftime() a partir do BSD 4.3. Sua principal diferena em relao a anterior que possui duas estruturas de dados internas:struct timeval { long tv_sec; long tv_usec; } struct timezone { int tz_minuteswest; int tz_dsttime; }

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

12

A biblioteca que contm essa estrutura a sys/time.h. A chamada de gettimeofday() na forma: int gettimeofday( struct timeval *tv, struct timezone *tz), sendo que tv e tz sero nossas variveis que acessaro as informaes sobre a hora atual. Gettimeofday() retorna 0 se a operao foi executada com sucesso ou -1 se falhou. Aps uma chamada de gettimeofday(), a varivel tv_sec guardar o valor em segundos que se passaram desde a primeira hora de primeiro de janeiro de 1970, assim como faz a funo time(). A varivel tv_usec retorna o nmero de microssegundos transcorridos aps o ltimo segundo. Essas duas variveis pertencem a estrutura timeval, como j fora citado. J as duas variveis pertencentes a timezone, so tz_minuteswest, que como a varivel timezone de ftime() apresenta o valor em minutos a oeste do meridiano de Greenwich em que nos encontramos. A varivel tz_dsttime est em desuso, sendo que nem pode ser utilizada sobre o Linux (seu uso gera erro na execuo do programa), e armazena um valor simblico com informaes sobre a rea do planeta no qual nos encontramos, para que a partir de um algoritmo presente em algum programa do usurio seja calculado os dias em que se aplicar o horrio de vero. Seu desuso se deve ao fato de que esses dias, na atualidade, no podem ser calculados por um simples algortmo, pois dependem mais de decises polticas do que de qualquer outro fator. Assim, para fazermos uso de gettimeofday():struct timeval tv; struct timezone tz;

E chamamos a funo:int gettimeofday (&tv,&tz);

Assim, temos em tv.tv_sec e tv.tv_usec as informaes j expostas anteriormente. A funo gettimeofday() obtm o tempo da seguinte forma: a cada interrupo do PIT, na IRQ 0, ocorre um tratamento dessa interrupo pelo kernel. Nessa rotina, o Linux sabe que se acabaram de passar dez milisegundos desde o ltimo tick, e tambm faz a leitura do TSC e guarda seu valor em uma varivel. Assim, a cada chamada de gettimeofday(), o Linux sabe o tempo atual at o ltimo tick, e o restante ele obtm fazendo uma nova leitura do TSC, subtraindo esse valor por aquele lido na interrupo e convertendo-o em microssegundos. A funo gettimeofday() consome em mdia 3200 ciclos de clock da CPU para ser executada, considerando sua execuo com prioridade normal e interrupes do kernel do Linux habilitadas, alm de outros processos em atividade. Em um Pentium de 100 MHz, 3000 ciclos de clock demoram 3 microssegundos. Como a resoluo dessa funo de 1 microssegundo, podemos notar que a preciso no igual a resoluo, sendo um pouco menor. Porque? Porque a funo demorando cerca de 3 microssegundos para ser executada, aps terminada o tempo j no ser o mesmo do qual ela o leu em microssegundos (provavelmente j se tero passados de 1 a 3 microssegundos). Assim, quanto mais rpido a funo gettimeofday() for executada, maior ser a preciso, ou seja, deveremos levar em conta o clock da CPU.

3.4 Acesso Direto ao RTCUma outra forma de obtermos informaes sobre a hora atravs do acesso direto ao RTC. Mas para tal necessrio ter em mente alguns fatores. O primeiro

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

13

que a hora do sistema no exatamente a mesma do RTC. O Linux ao ser iniciado l a hora do RTC e a partir de ento gerencia a hora do sistema por conta prpria, sem mais consult-lo. A prxima hora em que far isso ser ao ser desligado, quando atualizar a hora do RTC com a do sistema. Ou seja, como o RTC possui um erro em torno de 10 segundos ao ms e o artifcio usado pelo Linux para atualizar a hora depende do PIT e este tambm no perfeito, em um sistema ligado a muito tempo pode haver uma grande disparidade entre a hora dada pelo RTC e a do sistema. Outro fator que devemos ter em mente que para lermos o valor do RTC devemos escrever em endereos de memria protegida pelo Linux, sendo necessria a incluso da seguinte linha de comando no programa do usurio:ioperm (0x70,2,1);

Essa funo, bem como a outb() e a inb() esto na biblioteca sys/io.h. Para o usurio rodar esse programa dever primeiro logar-se como root. Essa funo tem por objetivo liberar (usando 1 no terceiro argumento) o uso de 2 bytes (segundo argumento) a partir do endereo 0x70. Assim, podero ser escritos / lidos os bytes 0x70 e 0x71 das portas de entrada e sada da mquina. Como j fora explicado, deveremos guardar o valor no endereo 0x70 respectivo ao que queremos receber no endereo 0x71, conforme a tabela abaixo:Endereo (CMOS RAM): 0x00 0x02 0x04 0x06 0x07 0x08 0x09 0x32 Contedo Segundos Minutos Horas Dia da semana Dia do ms Ms Ano Sculo

Assim, para qualquer contedo da tabela que desejarmos obter devemos, utilizamos a funo outb (y,0x70), onde y o endereo da CMOS RAM presente na tabela acima correspondente. Para se ler o resultado basta invocarmos a funo inb (0x71), que retornar o valor correspondente, em um byte, mas no formato BCD. Uma chamada outb() seguida de um inb() nesse contexto demora aproximadamente de 400 a 500 ciclos de clock. A resoluo mnima acessvel tambm na ordem de segundos, ou seja, no satisfaz aplicaes crticas.

3.5 Funes de Formatao do TempoAs funes ctime(), asctime(), gmtime(), localtime(), mktime() e strftime(), so responsveis pela manipulao e formatao do tempo, ou seja, transformam uma forma de indicao de tempo em outra correspondente. Para o funcionamento das mesmas, necessria a incluso da biblioteca time.h. A funo ctime(), declarada char *ctime (const time_t *timep) retorna o valor de apontado por timep (segundos desde primeiro de janeiro de 1970) em uma string, da forma: Mon Oct 2 12:30:21 2001. Gmtime() declarada como struct tm *gmtime (const time_t *timep), sendo timep os segundos desde janeiro de 1970. Ela retorna um ponteiro para aCarlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

14

estrutura tm com as informaes sobre a hora atual (GMT), que tem a seguinte declarao em time.h:struct tm int int int int int int int int int }; { tm_sec; tm_min; tm_hour; tm_mday; tm_mon; tm_year; tm_wday; tm_yday; tm_isdst;

Sendo tm_sec o nmero de segundos (0 a 60), tm_min o tempo em minutos (0-59), tm_hour as horas (0 a 23), tm_mday o dia do ms (1 a 31), tm_mon o ms (0 a 11), tm_year o ano (se em 1999, nos retorna 99, se em 2001, 101), tm_wday o dia da semana (0 a 6), tm_yday o dia do ano (0 a 365) e tm_isdst a informao a respeito do horrio de vero, sendo -1 para uma hora de atraso, 1 para uma hora adiantada e 0 para desativado. J localtime() igual a gmtime(), mas retorna o tempo regional, enquanto a anterior, o valor GMT, alm de gerar variveis externas, como tzname, com informaes sobre a regio onde nos encontramos, timezone com o nmero de segundos a oeste est essa regio do Meridiano de Greenwich, e daylight indicando se so aplicadas ou no polticas sobre o horrio de vero. Asctime() tem a seguinte declarao: char *asctime (const struct tm *timeptr). Retorna a data na forma de uma string, como ctime(), a partir de um ponteiro para uma estrutura tm com informaes sobre a hora atual. A funo mktime() declarada time_t mktime (struct tm *timeptr) e faz o inverso de gmtime() ou localtime(), retornando a partir de um ponteiro para um estrutura tm o tempo em segundos transcorridos desde primeiro de janeiro de 1970. E por fim, strftime(), que declarada: size_t strftime (char *s, size_t max, const char *format, const struct tm *tm). A partir de um ponteiro para a estrutura tm, retorna uma string s de tamanho max no formato definido por format, em um formato semelhante a printf(). Por exemplo: strftime ("%r %A %e %B %Y", localtime (time()) retorna a string: "00:30:21 AM Monday 2 October 2001". Os parmetros passados em format podem ser vistos atravs do man strftime no terminal do Linux:Parmetro %n %t %H %I %k %l %M %p %r %R %s %S %T Contedo Nova Linha Tabulao Horas (00 a 23) Horas (01 a 12) Horas (0 a 23) Horas (1 a 12) Minutos (00-59) AM ou PM Tempo, 12 horas (hh:mm:ss [AP]m) Tempo, 24 horas (hh:mm) Segundos desde 01/01/1970 Segundos (0 a 59) Tempo, 24 horas (hh:mm:ss)

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux %a %A %b ou %h %B %C %d %e %D %j %m %U %w %x %y %Y Abreviao do dia da semana Dia da semana (nome completo) Abreviao do nome do ms Nome do ms completo Sculo (00 a 99) Dia do ms (01 a 31) Dia do ms (1 a 31) Data GMT (mm/dd/aa) Dia do ano Ms (01-12) Nmero da semana (00 a 53) Dia da semana (0 a 6) Data local (mm/dd/aa) ltimos dois dgitos do ano (00 a 99) Ano (19xx ou 20xx)

15

Carlos Alexandre Piccioni Cssia Yuri Tatibana Rmulo Silva de Oliveira

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

16

4. Medindo a Passagem do TempoMedir a passagem do tempo uma tarefa freqentemente exigida de aplicaes de reas diversas, seja para sincronizao dos processos que a compe, ou para utilizao por um tipo especfico de aplicao, como programas de avaliao de desempenho. Aplicaes de tempo real, entretanto, lidam com o tempo de maneira explcita e portanto, tem a medio da passagem de tempo como uma tarefa de intrnseca e de extrema importncia. Como ferramentas de suporte no estudo de sistemas computacionais de tempo real, programas com o propsito especfico de capturar intervalos de tempo so freqentemente construdos. Iteraes contnuas de um lao de medio de tempo revelam informaes importantes sobre o comportamento do sistema em tempo de execuo. Embora existam diversos outros meios de obter a mesma informao, muito deles interferem demasiadamente nos valores capturados, o que eventualmente compromete a qualidade dos estudos sobre os mesmos. Este o caso por exemplo, de simuladores e depuradores. A construo de programas que possam garantir determinada preciso na medio de tempo e conseqentemente fornecer base confivel para o estudo desenvolvido, deve apresentar cuidados especiais quanto a escolha dos valores a serem adotados como parmetros. O parmetro utilizado um valor sobre o qual todos os demais clculos do programa so efetuados. Ele lido a partir de alguma fonte de medio de tempo externa ao programa atravs de consultas, realizadas por chamadas do sistema. Contadores de hardware caracterizam uma fonte confivel e relativamente precisa de medio de tempo. Como visto anteriormente, os contadores no so afetados por flutuaes de desempenho do sistema, falhas de software ou sobrecarga. Embora o processo de leitura dos mesmos o seja, eles so freqentemente utilizados como fonte de parmetros para os programas em questo. No Linux, como citado anteriormente, existem trs mecanismos voltados para o registro de passagem de tempo: o Real Time Clock, (RTC), o Time Stamp Counter (TSC), e o Programable Interrupt Timer (PIT). Portanto, a medio de passagem de tempo nesta plataforma feita direta ou indiretamente a partir de uma dessas fontes.

4.1 Diferena na HoraEm sua grande maioria, os estudos relacionados a tempo real sobre plataformas existentes exigem em dado momento o conhecimento do comportamento temporal desta plataforma. Seja para realizao de testes que comprovem uma determinada teoria, ou testes de carter ilustrativo ou coleta de dados. Esse conhecimento pode ser adquirido pelo estudo detalhado do cdigo fonte do sistema e posterior aproximao de valores de tempo para sua execuo, ou pela medio do intervalo de tempo transcorrido durante a execuo de um conjunto de instrues conhecidas, cujo tempo de execuo se deseja medir. No segundo caso, a medio revela apenas uma aproximao do tempo consumido pela instruo ou instrues executadas. Entretanto, a preciso desta medio pode ser melhorada caso executadas dentro de um lao. Obtendo um vetor de valores para execuo de uma mesma instruo ou seqncia de instrues que permite a verificao do tempo mdio de execuo das mesmas dentro do loop. O trecho de cdigo de programa a seguir ilustra tais mecanismos.

DAS UFSC Dezembro de 2001

Trabalhando com o Tempo Real em Aplicaes Sobre o Linux

17

int j=1; int media=0; while (j