Программирование >>  Структура ядра и системные вызовы 

1 ... 44 45 46 [ 47 ] 48 49 50 ... 98


return 3;

return 0;

Данная программа сначала задает функцию callme в качестве обработчика сигнала SIGUSR1. Затем она создает таймер, используя для этого системный таймер реального времени. Программа указывает, что после срабатывания таймера должен быть послан сигнал SIGUSR1, а данные таймера, которые следует отправить вместе с сигналом, - это TIMER TAG. Указатель на таймер, возвращенный API timer create, хранится в переменной tjd.

Следующий шаг - установка таймера на срабатывание 20 апреля 1997 года в 10 часов 27 минут 30 секунд; кроме того, после срабатывания таймер должен перезапускаться каждые 30 секунд. Абсолютные значения даты и времени завершения работы таймера указаны в переменной dojime (типа struct tm) и преобразуются в значение типа timejt функцией mktime. После выполнения всех перечисленных операций вызывается функция timer settime для включения таймера. Затем программа ожидает срабатывания таймера в указанные день и время, а через 30 секунд вновь прекращает свою работу. Наконец, перед своим окончательным завершением программа вызывает timer delete для освобождения всех системных ресурсов, выделенных под таймер.

Пробный запуск этой программы дал такие результаты:

% СС posix timer abs.с -о posix timer abs % posix timer abs

timer will go off at: Sun Apr 20 10:27:30 1997 callme: 12, signo:16. Sun Apr 20 10:27:30 1997 callme: 12, signo:16. Sun Apr 20 10:27:45 1997

Следует отметить, что данную программу можно модифицировать, с тем чтобы задать относительное время вместо абсолютного. Например, чтобы установить срабатывание таймера через 60 секунд и затем каждые 120 секунд, функция main должна быть модифицирована следующим образом:

int main{) {

/* установить sigaction для SIGUSR1 */

/* создать таймер с помощью timer create */

struct itimerspec val;

/* срабатывание через 60 секунд начиная с текущего момента */ val.it.value.tv sec = 60; val.it.value.tv nsGc = 0;

val.it.interval.tv sec = 120; /* повторять каждые 120 секунд */

val.it.interval.tv nsec = 0;

if <timer settime(t id, 0, ival, 0)== -1)

perror( timer settirae ); return 2;

/* ожидать срабатывания таймера */

Отличия модифицированной функции main от этой же функции в программе posix timer abc. С заключаются в следующем: переменная dotime и API mktime здесь не используются; в переменной val.it value задается непосредственно относительное время (по отношению к текущему моменту) первого срабатывания таймера; второй аргумент вызова timer settime устанавливается в О, а не в TIMER ABSTIME.

9.11. Класс timer

Таймеры POSIX.lb, отличаясь гибкостью применения и высокой точностью, для своего создания, использования и освобождения требуют разработки программы значительно большего объема . Однако таймеры POSIX. lb довольно точно соответствуют классу timer языка С++. Этот класс предоставляет пользователю ряд преимуществ:

Обеспечивает высокоуровневый интерфейс, предназначенный для манипулирования таймерами. В результате сокращается время обучения работе с таймером, время разработки программы и ее отладки.

Инкапсулирует коды интерфейсов. Эти коды используются повторно при создании множества других таймеров.

Функции-члены данного класса можно изменить с целью использования API setitimerh системах, не совместимых с POSIX. lb. Это позволит тратить меньше усилий на перенос пользовательских приложений.

Класс timer можно встраивать в другие пользовательские классы, для работы которых нужны встроенные таймеры. Например, программа банковского автомата может отменить операцию, если в течение 5 минут от пользователя не поступает никаких данных.

Между функциями класса timer и интерфейсами прикладного программирования POSIX.lb существует определенная связь.

Функция класса timer

АР! POSIX.lb

Конструктор

timer create

Деструктор

timer delete

Пуск и останов таймера

timer settime

Получение статистических данных 0 потерянных сигналах

timer getoverrun

Запрос значений таймера

timer gettime



к сказанному можно добавить, что конструктор класса timer гадает также механизм обработки сигналов таймера (посредством API sigaction). Объявление этого класса, приведенное в timer.h, имеет вид:

#ifndef TIMER H ♦define TIMER H

♦include <signal.h> ♦include <time.h> ♦include <errno.h>

typedef void (*SIGFUNC){int, siginfo*, void*);

class (

timer

timer t timer id;

int status;

struct itimerspec val; public:

/* конструктор: установка таймера timer( int signo, SIGFUNC action.

int timer val.

cloc)c t sys cloc)? = CLOCK REALTIME)

struct sigaction sigv; status =0;

sigemptyset ( ssigv.sa mas)c ); sigv.sa flags = SA SIGINFO; sigv.sa sigaction = action; if (sigaction( signo, ssigv.

0 ) == -1)

perrorCsigaction ); status = errno;

else {

struct sigevent sigx; sigx.sigev notifу sigx.sigev signo

SIGEV SIGNAIi;

signo;

sigx.sigev value.sival int = timer val; if (timer create ( sys clocl<, Ssigx, stimer id )

perror{ timer create ) status = errno;

/* деструктор: уничтожение таймера */

~timer О

if {status = 0) {

Системиое программирование на С++ для UNIX

stop О;

if (timer delete ( timer id ) (

perror( timer delete );

/* проверить статус таймера */

int operator!()

return status ? 1 : 0;

/* настроить таймер на относительное время */

int run(long start sec, long start nsec, long reload sec, long reload nsec)

if (status) return -1; val.it value.tv sec val.it value.tv nsec val.it interval.tv sec val.it interval.tv nsec

start sec; start nsec; reload sec; reload nsec;

if (timer settime( timer id, 0, Sval, 0 ) == -1 )

perror( timer settime ); status = errno; return -1;

return 0;

/* настроить таймер на абсолютное время */ int run( time t start time, long reload sec.

long reload nsec )

if (status) return -1; val.it value.tv sec-val.it value.tv nsec val.it interval.tv sec

= start time; = 0;

= reload sec;

val.it interval.tv nsec = reload nsec; if (timer settime( timer id, TIMER ABSTIME, Sval,0 )

-1 )

perror( timer settime ); status = errno; return -1;

return 0;

/* остановить таймер */ int stopO .

if (status) return -i;

Глава 9. Сигналы



val.it value.tv sее = О

val.it value.tv nsec О val.it interval.tv sec = О val.it interval.tv nsec 0 if (timer settime( timer id, {

perror{ timer settime ); status = errno; return -1;

return 0;

0, &val, 0 ) == -1 )

/* получить статистику потерь сигналов */

int overrun{)

if {status) return -1;

return timer getoverrun{ timer id );

/* получить время, оставшееся до срабатывания */ int values{ longfi sec, long&.nsec )

if {status) return -1;

if {timer gettime{ timer id, &val ) == -1) {

perror{ timer gettime ); status = errno; return -1;

sec = val.it value.tv sec;

nsec = val.it value.tv nsec; return 0;

/* перегрузить операцию для объектов класса timer */ friend ostreamfi operator { ostreamfi os, timers obj) { .-m

long sec, nsec; ¥, i

obj. values (sec> nsec ); jfc

double tval = sec + {(double)nsec/1000000000.0);

OS time left: tval ;

return os;

#endif

В этом классе конструктор timerr.timer принимает в качестве аргумента номер сигнала, подлежащего генерации после срабатывания таймера, указатель на обработчик сигнала для таймера и целочисленный идентификатор таймера timerjag. Последний аргумент, sys clock, не обязателен. Он

указывает, что новому таймеру следует использовать при своей работе определенные системные часы. Конструктор задает механизм обработки сигнала и создает новый таймер, основываясь на параметрах sys clock, timerjag и указанном номере сигнала.

Функция timerr.run включает, а функция timerstop выключает таймер. Они устанавливают данные, хранящиеся в структуре struct itimerspec, для вызова API timer settime. В частности, функция timerr.run перегружается, чтобы пользователь мог указывать относительное или абсолютное время первоначального запуска таймера. Если задано абсолютное время, значение аргумента startJime можно получить с помощью функции mktime, как показано на примере программы posixjimerC (см. предыдущий раздел).

Кроме того, функция timer:.overrun возвращает статистику потерь сигналов объекта класса timer, а функция timer::values - время, оставшееся до следующего срабатывания таймера. Наконец, операция перегружается для вывода на экран результатов работы функции timer::values класса timer.

Функции-члены класса timer позволяют представить таймер стандарта POSIX.lb в абстрактной форме. Их интерфейсы определяют все основные операции, которые требуется произвести для установки таймера и манипулирования им. Весь низкоуровневый код, взаимодействующий с API POSIX.lb, инкапсулируется и может повторно использоваться для множества объектов этого класса.

На примере программы posixjimer2. С демонстрируются преимущества и простота применения класса timer.

♦include <iostream.li> tinclude <stdio.li> tinclude <stdlib.h> tinclude <unistd.li> ♦include timer.h

void callme{ int signo, siginfo t* evp, void* ucontext ) {

long sec, nsec; time t tim = time{0);

cerr timer Id: evp-si value.sival int

, signo: signo , ctime{Stim);

int maln{) {

timer tl { SIGINT, callme, 1 ); timer t2 { SIGUSRl, callme, 2 ); timer t3 { SIGUSR2, callme, 3 );

if {!tl II It2 11- !t3 ) return 1;

tl.run( 2, 0, 2, 0 );

t2.run{ 3, 500000000, 3, 500000000 );

t3.run{ 5, 0, 5, 0 );



1 ... 44 45 46 [ 47 ] 48 49 50 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика