|
Программирование >> Структура ядра и системные вызовы
ITIMER.PROF Таймер общего времени, затраченного процессом на задачу пользователя и на системные задачи. ПО истечении заданного времени генерирует сигнал SIGPROF Тип данных struct itimerval определен в заголовке <sys/time.h> следующим образом: struct itimeval ( struct timeval it interval; интервал таймера struct timeval it value; текущее значение Для API setitimer значение, заносимое в элемент val.it value структуры, является временем установки указанного таймера, а val.itjnterval - временем перезагрузки таймера после его срабатывания. Значение val.itlnterval можно установить в О, если таймер необходимо запустить только один раз. Если же значение val.itvalue устанавливается в О в то время, когда таймер работает, последний останавливается. Для API getitimer элементы old.it value и old.tjnterval структуры возвращают соответственно оставшееся время (до срабатывания) указанного таймера и его интервал срабатывания. Аргумент old API setitimer подобен аргументу old в API getitimer. Если этот аргумент является адресом переменной типа struct itimeval, то он возвращает предьщущее значение таймера. Если аргумент old установлен в О, старое значение таймера не будет возвращено. Таймеры ITIMER VIRTUAL и ITIMER PROF предназначены, в первую очередь, для планирования общего времени выполнения избранных пользовательских функций. Работают они лишь в том случае, если задействован пользовательский процесс (или когда ядро выполняет системные функции от имени пользовательского процесса для таймера ITIMER PROF). В случае успешного завершения API setitimer и getitimer возвращают нулевое значение, а в случае неудачи возвращают - I. Кроме того, значения таймеров, устанавливаемые интерфейсом API setitimer в родительском процессе, не наследуются порожденными им процессами, но сохраняются, когда процесс выполняет новую программу с помощью exec. Программа timer2.C, приведенная ниже в качестве примера, идентична программе timer. С, но вместо API alarm использует API setitimer Кроме того, нет необходимости вызывать API setitimer внутри функции обработки сигнала, так как таймеру указывается автоматическая перезагрузка: ♦include <stdio.h> finclude <unistd.h> finclude <sys/time.h> finclude <signal.h> INTERVAL 2 int sig no ) fdefine void callme( { /* выполнить запланированные задания */ int main/) struct itimerval val; struct sigaction action; sigemptyset(Saction.sa mask); ♦ifdef S0LARIS 25 action.sa handler (void (*)(int))callme; ♦else action.sa handler (void (*)())callme; ♦endif action.sa flags = SA RESTART; if ( sigaction! SIGALRM,saction,0 )==-l ) perror ( sigaction ); return 1; val. it interval. tv sec =INTERVAL; val.it interval.tv usec =0; val.it value.tv sec =INTERVAL; ,val.it value.tv usec =0; if (setimer(ITIMER REAL, Sval, 0)== -1) perror( alarm ); else w)iile( 1 ) /* выполнять .обычную работу */ return 0; Необходимо отметить, что таймер реального времени, устанавливаемый API setitimer, отличается от таймера, который устанавливается API alarm. Таким образом, используя эти два API, процесс может задействовать два таймера реального времени. Поскольку оба интерфейса требуют от пользователя задания механизма обработки сигнала для контроля работы таймера, их не следует применять (когда они используются для установки таймера реального времени) совместно с API sleep. Причина в том, что API sleep может изменить механизм обработки сигнала SIGALRM. 9.10. Таймеры стандарта POSIX.Ib POSIX.Ib определяет ряд интерфейсов прикладного программирования, D?pnQTYfK манипулирования интервальными таймерами. Таймеры IUblX.Ib принято считать более гибкими и мощными в сравнении с таймерами UNIX по следующим причинам: пользователи могут определять множество независимых таймеров на одни системные часы; таймеры POSIX. lb ведут отсчет времени в наносекундах; пользователи могут указывать для каждого таймера сигнал, подлежащий генерации по срабатывании таймера; интервал таймера может быть задан в форме абсолютного либо относительного времени. На количество устанавливаемых на один процесс POSIX-таймеров существует ограничение. Пределом является константа TIMER MAX, определенная в заголовке <limits.h>. Более того, таймеры POSIX, созданные процессом, не наследуются порожденными им процессами, но сохраняются с помощью системного вызова exec. Однако в отличие от таймеров UNIX таймер POSIX.l по срабатывании не посылает сигнап SIGALRM и может свободно использоваться в одной программе с API sleep. В POSIX.lb предусмотрены следующие API, предназначенные для манипулирования таймерами: #include <signal.h> #include <time.h> int timerjcreate ( clockid t clock, struct sigevent* spec, timer t* timer hdr); int timerjsettime ( timer t timer hdr, int flag, struct itimerspec* val, struct itimerspec* old ); int timergettime ( timer t timer hdr, struct itimerspec* old ); int timer getoverrun ( timer t timer hdr ); int timerjdelete ( timer t timer hdr ); API timercreate динамически создает таймер и возвращает указатель на него. Аргумент clock указывает, показания какого системного таймера будет использовать новый таймер. Аргумент clock может принимать значение CLOCK REALTIME, позволяющее задавать установки таймера в реальном времени. Это значение определяется стандартом POSIX.lb. Другие значения аргумента clock зависят от системы. Аргумент spec определяет, какое действие необходимо предпринять по срабатывании таймера. Тип данных struct sigevent определяется так: struct sigevent int int union sigval sigev notify; sigev signo; sigev value; Поле sigevsigno содержит номер сигнала, который будет генерироваться после срабатывания таймера. Оно действительно только тогда, когда в поле sigev notiJy указано значение SIGEV SIGNAL. Если поле 5;у лоЛ>5 устанавливается в SIGEV NONE, по срабатывании таймера никакой сигнап не посылается. Так как различные таймеры могут генерировать одинаковый сигнал, поле sigevvalue применяется для хранения пользовательских данных, позволяющих определить, каким конкретно таймером послан сигнал. Структура данных поля sigev value следующая: union sigval ( int sival int; void *sival ptr; Например, процесс может присвоить каждому таймеру уникальный целочисленный номер-идентификатор. Затем этот номер может бьггь присвоен полю spec->sigev value.sival int. Для того чтобы можно было передать эти данные вместе с сигналом (spec->sigev signo) после его генерации, в вызове sigaction должен быть установлен флаг SA SIGINFO, задающий механизм обработки сигнала, а функция обработки сигнала должна иметь такой прототип: void <signal handler>(ХпЬ signo, siginfo t* evp, void* ucontext); Структура данных siginfoj определяется в заголовке <siginfo.h>. При вызове обработчика сигнала поле epv->si value должно содержать данные spec- >sigev value. Если аргумент spec установлен в О, а тип таймера - CLOCK REALTIME, то по срабатывании таймера генерируется сигнал SIGALRM. Наконец, аргумент timerjidr ь KV\ timer create является адресом переменной типа timerj, используемой для хранения указателя на вновь установленный таймер. Данный аргумент не следует устанавливать в NULL, так как этот указатель используется для вызова других API таймера POSIX.lb. API timercreate, также как и все остальные интерфейсы таймеров POSIX.lb, возвращает О в случае успешного завершения и -1 в случае неудачи. API timer settime начинает и останавливает работу таймера, API timer get-time используется для запроса его текущих значений. В частности, тип данных struct itimerspec определяется так: struct itimerspec ( struct timespec it interval; struct timespec it value; a структура данных struct timespec - следующим образом: struct timespec { time long tv sec; tv nsec; Значение itimerspec::it value указывает время, оставшееся до срабатывания таймера, а itimerspec::itjnterval определяет новое время, по истечении которого таймер будет перегружен. Все значения времени задаются в секундах (в поле timespec::tv sec) и наносекундах (в поле timespec::tv nsec). в API timer settime значение аргумента flag может бьггь равным О или TIMER RELTIME, если время запуска таймера (указанное в аргументе vat) дается относительно текущего времени. Если значение аргумента у/л равно TIMER ABSTIME, время запуска таймера является абсолютным. Следует отметить, что для установки абсолютного времени срабатывания таймера можно воспользоваться функцией mktime, определенной в ANSI С. Кроме того, если значение val.it value равно О, работа таймера останавливается. Если значение val.itjnterval тоже равно О, работа таймера после его срабатывания не возобновляется. Наконец, аргумент old в API timersettime используется для получения предьщущих значений таймера. Этот аргумент может бьггь установлен равным NULL, тогда значения таймера не возвращаются. Аргумент old в API timerjgettime возвращает текущие установки указанного таймера. API timer getoverrun возвращает ряд сигналов, которые были посланы таймером, но утеряны. В частности, ядро не ставит в очередь сигналы таймера, если они генерируются, но процессами-получателями не обрабатываются (такие процессы, возможно, в это время заняты обработкой других сигналов). Вместо этого ядро регистрирует количество сигналов для каждого таймера. Данный API можно использовать для определения истекшего времени (от момента запуска или срабатывания таймера и до текущего момента времени), основываясь на подсчете потерянных сигналов таймера. Следует отметить, что счетчик потерянных сигналов в таймере сбрасывается каждый раз, когда какой-либо процесс-получатель обрабатывает сигнал таймера. API timerdestroy используется для уничтожения таймера, созданного с помощью API timer create. На примере программы posixJimer abs. С демонстрируется способ установки таймера абсолютного времени, который должен сработать 20 апреля 1997 г. в 10:27. finclude <iostream.h> finclude <stdio.h> finclude <unistd.h> finclude <signai.h> finclude <time.h> void caiime( int signo, siginfo t* evp, void* ucontext ) time t tim = time(O); cerr caiime: evp->si vaiue.sivai int , signo: signo , ctime(Stim); int mainO ( struct sigaction sigv>r struct sigevent sigx; struct itimerspec vai;. struct tm timer t do time; t id; sigemptyset( fisigv.sa mask ); sigv.sa flags = SA SIGINFO; sigv.aa sigaction = caiime; if (sigaction( SIGUSRl, ssigv, 0) == -i) perror( sigaction ); return 1; sigx.aigev notify = SIGEV SIGNAL; sigx.sigev signo = SIGUSRl; sigx.sigev vaiue.sivai int = 12; if ( timer create( CLOCK REALTIME, fisigx, St id ) == -1) perror( timer create ); . return i; ~ /* установить таймер на срабатьтение 20 апреля 1997 #! в 10:27 */ do time.tm hour = 10; do time.tm min =27; do time.tm sec = 30; do time.tm mon = 3; do time.tm year =97; do time.tm mday = 20; vai.it vaiue.tv sec vai.it value.tv nsec vai.it intervai.tv sec = 15; vai.it intervai.tv naec = 0; mktime( &do time ); 0; . cerr timer wiii go off attfii? ctime(svai.it vaiue.tv sec); if (timersettime ( t id, TIMER ABSTIME, svai, о ) == -1 ) perror( timer settime ); return 2; /* выполнять другие операции, a затем ждать, пока время таймера не истечет дважды*/ for (int 1=0; i < 2; i++ ) pause О; if (timer deiete( t id ) ==-l) perror( timer delete );
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |