Программирование в стандарте POSIX

Пример использования служебной


moda=`date +%m%d` ho=$((`date +%H` + 1)) mi=`date +%M` date ${moda}${ho}${mi}
Листинг 12.1. Пример использования служебной программы date.
Закрыть окно




#include <time.h> time_t time (time_t *tloc);
Листинг 12.2. Описание функции time().
Закрыть окно




#include <time.h> double difftime ( time_t time1, time_t time0);
Листинг 12.3. Описание функции difftime().
Закрыть окно






#include <sys/time.h> int gettimeofday (struct timeval * restrict tp, void *restrict tzp);
Листинг 12.4. Описание функции gettimeofday().
Закрыть окно




#include <time.h> int clock_getres (clockid_t clock_id, struct timespec *res); int clock_gettime (clockid_t clock_id, struct timespec *tp); int clock_settime ( clockid_t clock_id, const struct timespec *tp);
Листинг 12.5. Описание функций опроса характеристик и установки часов.
Закрыть окно




#include <stdio.h> #include <time.h> #include <sys/time.h>
int main (void) { struct timespec tmsp; struct timeval tmvl; time_t st; double s = 0; double d = 1; int i;
if (clock_getres (CLOCK_REALTIME, &tmsp) == -1) { perror ("CLOCK_GETRES"); return (1); } printf ("Разрешающая способность общесистемных часов: %ld нсек.\n", tmsp.tv_nsec);
if (clock_gettime (CLOCK_REALTIME, &tmsp) == -1) { perror ("CLOCK_GETTIME"); return (2); } printf ("Текущее время по общесистемным часам: %ld сек. %ld нсек.\n", tmsp.tv_sec, tmsp.tv_nsec);
(void) gettimeofday (&tmvl, NULL); printf ("Текущее время, функция gettimeofday(): %ld сек. %ld мксек.\n", tmvl.tv_sec, tmvl.tv_usec);
(void) time (&st); for (i = 1; i <= 100000000; i++) { s += d / i; d = -d; } printf ("Время выполнения цикла: %g сек.\n", difftime (time (NULL), st));
return (0); }
Листинг 12.6. Пример программы, использующей функции опроса показаний часов реального времени.
Закрыть окно




Разрешающая способность общесистемных часов: 10000000 нсек. Текущее время по общесистемным часам: 1072534678 сек. 296598000 нсек. Текущее время, функция gettimeofday(): 1072534678 сек. 296637 мксек. Время выполнения цикла: 15 сек.
Листинг 12.7. Возможные результаты работы программы, использующей функции опроса показаний часов реального времени.
Закрыть окно




#include <time.h> struct tm *gmtime (const time_t *tloc); struct tm *localtime (const time_t *tloc)
Листинг 12.8. Описание функций gmtime() и localtime().
Закрыть окно




#include <time.h> extern char *tzname[2]; extern long timezone; extern int daylight; void tzset (void);
Листинг 12.9. Описание функции tzset() и ассоциированных внешних переменных.
Закрыть окно




#include <time.h> time_t mktime (struct tm *tmptr);
Листинг 12.10. Описание функции mktime().
Закрыть окно




#include <time.h> size_t strftime (char * restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict tmptr);
Листинг 12.11. Описание функции strftime().
Закрыть окно




#include <time.h> char *strptime (const char * restrict s, const char *restrict format, struct tm *restrict tmptr); struct tm *getdate (const char *s);
Листинг 12.12. Описание функций strptime() и getdate().
Закрыть окно




#include <stdio.h> #include <time.h> #include <limits.h>
int main (void) { char dtbuf [LINE_MAX]; /* Буфер для данных о времени */ time_t st; struct tm stm;
(void) time (&st);
(void) strftime (dtbuf, sizeof (dtbuf), "%c", gmtime (&st)); printf ("Текущее всемирное время: %s\n", dtbuf);
(void) strftime (dtbuf, sizeof (dtbuf), "%c", localtime (&st)); printf ("Текущее местное время: %s\n", dtbuf);
/* Узнаем, каким днем недели будет 01 января 2038 года */ stm.tm_year = 2038 - 1900; stm.tm_mon = 1 - 1; stm.tm_mday = 1; stm.tm_hour = 0; stm.tm_min = 0; stm.tm_sec = 0; stm.tm_isdst = -1; if ((st = mktime (&stm)) == (time_t) (-1)) { perror ("MKTIME"); } else { (void) strftime (dtbuf, sizeof (dtbuf), "%A", &stm); printf ("День недели 01 января 2038 года: %s\n", dtbuf); printf ("Число секунд от начала отсчета в начале 2038 года (шест.): %x\n", (unsigned int) st); }
/* Узнаем, когда наступит переполнение значений типа time_t, */ /* представленных как 32-разрядное целое со знаком */ st = (time_t) 0x7fffffff; (void) strftime (dtbuf, sizeof (dtbuf), "%c", gmtime (&st)); printf ("Всемирное время конца 32-разрядного отсчета: %s\n", dtbuf);
/* Преобразуем эту дату в формат ISO 8601:2000 */ if (strptime (dtbuf, "%c", &stm) == NULL) { perror ("STRPTIME"); } else { (void) strftime (dtbuf, sizeof (dtbuf), "%F", &stm); printf ("Дата конца 32-разрядного отсчета в формате ISO 8601:2000: %s\n", dtbuf); }
return (0); }
Листинг 12.13. Пример программы, использующей функции преобразования данных о времени.
Закрыть окно




Текущее всемирное время: Sat Jan 3 13:54:02 2004 Текущее местное время: Sat Jan 3 16:54:02 2004 День недели 01 января 2038 года: Friday Число секунд от начала отсчета в начале 2038 года (шест.): 7fe7ed50 Всемирное время конца 32-разрядного отсчета: Tue Jan 19 03:14:07 2038 Дата конца 32-разрядного отсчета в формате ISO 8601:2000: 2038-01-19
Листинг 12.14. Возможные результаты работы программы, использующей функции преобразования данных о времени.
Закрыть окно




#include <time.h> clock_t clock (void);
Листинг 12.15. Описание функции clock().
Закрыть окно




#include <stdio.h> #include <time.h>
int main (void) { time_t st; clock_t ct; double s = 0; double d = 1; int i;
fprintf (stderr, "Начало выполнения цикла\n"); (void) time (&st); ct = clock; for (i = 1; i <= 100000000; i++) { s += d / i; d = -d; } fprintf (stderr, "Процессорное время выполнения цикла: %g сек.\n", (double) (clock - ct) / CLOCKS_PER_SEC); fprintf (stderr, "Астрономическое время выполнения цикла: %g сек.\n", difftime (time (NULL), st));
return (0); }
Листинг 12.16. Пример программы, использующей функции опроса показаний часов реального и процессорного времени.
Закрыть окно




Начало выполнения цикла Процессорное время выполнения цикла: 15.19 сек. Астрономическое время выполнения цикла: 15 сек.
Листинг 12.17. Возможные результаты работы программы, использующей функции опроса показаний часов реального и процессорного времени.
Закрыть окно




Начало выполнения цикла Процессорное время выполнения цикла: 15.2 сек. Астрономическое время выполнения цикла: 15 сек. real 15.20 user 15.20 sys 0.00
Листинг 12.18. Возможные результаты измерения времени работы программы, использующей функции опроса показаний часов реального и процессорного времени.
Закрыть окно




#include <sys/times.h> clock_t times (struct tms *buffer);
Листинг 12.19. Описание функции times().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа копирует строки со стандартного ввода на стандартный вывод, */ /* "прокачивая" их через пару сокетов. */ /* Используются функции ввода/вывода нижнего уровня. */ /* Измеряется астрономическое и процессорное время */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <sys/wait.h> #include <sys/times.h>
#define MY_PROMPT "Вводите строки\n" #define MY_MSG "Вы ввели: "
int main (void) { int sds [2]; char buf [1]; int new_line = 1; /* Признак того, что надо выдать сообщение MY_MSG */ /* перед отображением очередной строки */ clock_t st_ct; /* Данные об астрономическом и процессорном времени */ struct tms st_cpt; /* в начале работы программы */ clock_t en_ct; /* Данные об астрономическом и процессорном времени */ struct tms en_cpt; /* в конце работы программы */ long tck_p_sec; /* Количество тактов часов в секунде */
/* Опросим данные о времени начала выполнения */ if ((st_ct = times (&st_cpt)) == (clock_t) (-1)) { perror ("TIMES-1"); return (1); }
/* Создадим пару соединенных безымянных сокетов */ if (socketpair (AF_UNIX, SOCK_STREAM, 0, sds) < 0) { perror ("SOCKETPAIR"); return (2); }
switch (fork ()) { case -1: perror ("FORK"); return (3); case 0: /* Чтение из сокета sds [0] и выдачу на стандартный вывод */ /* реализуем в порожденном процессе */ while (read (sds [0], buf, 1) == 1) { if (write (STDOUT_FILENO, buf, 1) != 1) { perror ("WRITE TO STDOUT"); break; } } exit (0); }
/* Чтение со стандартного ввода и запись в сокет sds [1] */ /* возложим на родительский процесс */ if (write (sds [1], MY_PROMPT, sizeof (MY_PROMPT) - 1) != sizeof (MY_PROMPT) - 1) { perror ("WRITE TO SOCKET-1"); }
while (read (STDIN_FILENO, buf, 1) == 1) { /* Перед отображением очередной строки */ /* нужно выдать сообщение MY_MSG */ if (new_line) { if (write (sds [1], MY_MSG, sizeof (MY_MSG) - 1) != sizeof (MY_MSG) - 1) { perror ("WRITE TO SOCKET-2"); break; } } if (write (sds [1], buf, 1) != 1) { perror ("WRITE TO SOCKET-3"); break; } new_line = (buf [0] == '\n'); } shutdown (sds [1], SHUT_WR);
(void) wait (NULL);
/* Опросим данные о времени конца выполнения, */ /* вычислим и выдадим результаты измерений */ if ((en_ct = times (&en_cpt)) == (clock_t) (-1)) { perror ("TIMES-2"); return (4); }
tck_p_sec = sysconf (_SC_CLK_TCK); fprintf (stderr, "Тактов в секунде: %ld\n", tck_p_sec); fprintf (stderr, "Астрономическое время работы программы: %g сек.\n", (double) (en_ct - st_ct) / tck_p_sec); fprintf (stderr, "Процессорное время, затраченное процессом: %g сек.\n", (double) (en_cpt.tms_utime - st_cpt.tms_utime) / tck_p_sec); fprintf (stderr, "Процессорное время, затраченное системой: %g сек.\n", (double) (en_cpt.tms_stime - st_cpt.tms_stime) / tck_p_sec); fprintf (stderr, "Аналогичные данные для порожденных процессов:\n"); fprintf (stderr, "%g сек.\n%g сек.\n", (double) (en_cpt.tms_cutime - st_cpt.tms_cutime) / tck_p_sec, (double) (en_cpt.tms_cstime - st_cpt.tms_cstime) / tck_p_sec);
return (0); }
Листинг 12.20. Пример программы, использующей функцию times().
Закрыть окно




Тактов в секунде: 100 Астрономическое время работы программы: 1.19 сек. Процессорное время, затраченное процессом: 0.02 сек. Процессорное время, затраченное системой: 0.08 сек. Аналогичные данные для порожденных процессов: 0.09 сек. 1 сек.
Листинг 12.21. Возможные результаты работы программы, использующей функцию times().
Закрыть окно




#include <time.h> int clock_getcpuclockid ( pid_t pid, clockid_t *clock_id);
Листинг 12.22. Описание функции clock_getcpuclockid().
Закрыть окно




#include <stdio.h> #include <time.h> #include <sys/types.h> #include <errno.h>
int main (void) { clockid_t clk_id; /* Идентификатор часов процессорного времени */ struct timespec tmsp; double s = 0; double d = 1; int i;
if ((errno = clock_getcpuclockid ((pid_t) 0, &clk_id)) != 0) { perror ("CLOCK_GETCPUCLOCKID"); return (1); }
if (clock_getres (clk_id, &tmsp) == -1) { perror ("CLOCK_GETRES"); return (2); } printf (" Разрешающая способность часов процессорного времени: %ld нсек.\n", tmsp.tv_nsec);
/* Измерим процессорное время выполнения цикла. */ fprintf (stderr, "Начало выполнения цикла\n"); tmsp.tv_sec = tmsp.tv_nsec = 0; if (clock_settime (clk_id, &tmsp) == -1) { perror ("CLOCK_SETTIME"); return (3); } for (i = 1; i <= 100000000; i++) { s += d / i; d = -d; } if (clock_gettime (clk_id, &tmsp) == -1) { perror ("CLOCK_GETTIME"); return (4); } fprintf (stderr, "Процессорное время выполнения цикла: %ld сек. %ld нсек.\n", tmsp.tv_sec, tmsp.tv_nsec);
return (0); }
Листинг 12.23. Пример программы, манипулирующей часами процессорного времени.
Закрыть окно




Разрешающая способность часов процессорного времени: 2 нсек. Начало выполнения цикла Процессорное время выполнения цикла: 15 сек. 350313054 нсек.
Листинг 12.24. Возможные результаты работы программы, манипулирующей часами процессорного времени.
Закрыть окно




#include <utime.h> int utime (const char *path, const struct utimbuf *times);
Листинг 12.25. Описание функции utime().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа устанавливает время последнего доступа к файлу - */ /* аргументу командной строки, равное текущему времени */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h> #include <sys/stat.h> #include <time.h> #include <utime.h>
int main (int argc, char *argv []) { struct stat st_buf; /* Буфер для опроса данных о файле */ struct utimbuf ut_buf; /* Буфер для формирования изменяемых данных о файле */
if (argc != 2) { fprintf (stderr, "Использование: %s файл\n", argv [0]); return (1); }
if (stat (argv [1], &st_buf) != 0) { perror ("STAT"); return (2); }
ut_buf.actime = time (NULL); ut_buf.modtime = st_buf.st_mtime;
if (utime (argv [1], &ut_buf) != 0) { perror ("UTIME"); return (3); }
return (0); }
Листинг 12.26. Пример программы, изменяющей время последнего доступа к файлу.
Закрыть окно




#include <unistd.h> unsigned sleep (unsigned seconds);
Листинг 12.27. Описание функции sleep().
Закрыть окно




#include <time.h> int nanosleep ( const struct timespec *rqtp, struct timespec *rmtp);
Листинг 12.28. Описание функции nanosleep().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа отслеживает изменение размера файла, */ /* заданного как аргумент командной строки */ /* * * * * * * * * * * * * * * * * * * * * * * * * */
#include <unistd.h> #include <stdio.h> #include <sys/stat.h> #include <time.h> #include <limits.h>
static time_t lt_mod = 0; /* Время последнего изменения файла */ static struct stat st_buf; /* Данные о файле */
/* Функция начальной обработки файла */ static void proc_init (const char *path) { fprintf (stderr, "Данные о размере файла %s\n", path); fprintf (stderr, "Время изменения Размер\n"); }
/* Функция проверки, нужно ли обрабатывать файл */ /* Результат > 0 - нужно */ /* 0 - не нужно */ /* &lt; 0 - ошибка */ static int check_mod (const char *path) { if (stat (path, &st_buf) != 0) { perror ("STAT"); return (-1); }
if (st_buf.st_mtime != lt_mod) { /* Файл изменился и, следовательно, нуждается в обработке */ lt_mod = st_buf.st_mtime; return (1); }
return 0; }
/* Функция обработки файла. */ /* Выведем время последнего изменения и текущий размер */ static void proc_mod (void) { char dtbuf [LINE_MAX]; /* Буфер для данных о времени */
(void) strftime (dtbuf, sizeof (dtbuf), "%c", localtime (&lt_mod)); fprintf (stderr, "%s %ld\n", dtbuf, st_buf.st_size); }
int main (int argc, char *argv []) { int res;
if (argc != 2) { fprintf (stderr, "Использование: %s файл\n", argv [0]); return (1); }
proc_init (argv [1]); while (1) { if ((res = check_mod (argv [1])) > 0) { proc_mod (); } else if (res &lt; 0) { return (res); } sleep (1); }
return 0; }
Листинг 12.29. Пример программы, использующей функцию sleep().
Закрыть окно




Данные о размере файла /var/log/ cron Время изменения Размер Tue Jan 6 12:50:00 2004 11191 Tue Jan 6 13:01:00 2004 11263 Tue Jan 6 13:10:00 2004 11409 Tue Jan 6 13:20:00 2004 11481 . . . Tue Jan 6 13:40:00 2004 11624 . . .
Листинг 12.30. Возможные результаты работы программы, использующей функцию sleep().
Закрыть окно




#define N ... #define MY_BUFSIZ ...
struct timespec tmsp = {0, 20000000}; int fds [2]; /* Файловые дескрипторы канала */ int semid; /* Идентификатор набора семафоров */ struct sembuf sembuf [1]; /* Массив для задания операций над семафором */ char buf [MY_BUFSIZ]; /* Буфер для чтения данных из канала */ int brd; /* Число прочитанных байт */ int i;
. . .
fcntl (fds [0], F_SETFL, O_NONBLOCK); sembuf [0].sem_num = 0; sembuf [0].sem_flg = IPC_NOWAIT; sembuf [0].sem_op = 0;
for (i = 0; i &lt; N; i++) { nanosleep (&tmsp, NULL);
if ((brd = read (fds [0], buf, MY_BUFSIZ) > 0) { /* Обработка прочитанных данных. */ /* Возможно, поступление данных на этом не закончилось */ . . . continue; }
if (semop (semid, sembuf, 1) == 0) { /* Значение семафора обнулено, ждать больше нечего */ . . . if (brd <= 0) { close (fds [0]); break; } } }
. . .
Листинг 12.31. Пример реализации полуактивного ожидания наступления нескольких событий с помощью функции nanosleep().
Закрыть окно




#include <sys/time.h> int getitimer (int timer_id, struct itimerval *cvalue); int setitimer ( int timer_id, const struct itimerval *restrict nvalue, struct itimerval *restrict ovalue);
Листинг 12.32. Описание функций getitimer() и setitimer().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа выясняет размер такта часов реального времени */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h> #include <sys/time.h>
int main (void) { struct itimerval itvl;
itvl.it_interval.tv_sec = 0; itvl.it_interval.tv_usec = 1; itvl.it_value.tv_sec = 0; itvl.it_value.tv_usec = 0;
if (setitimer (ITIMER_REAL, &itvl, NULL) < 0) { perror ("SETITIMER"); return (1); }
if (getitimer (ITIMER_REAL, &itvl) < 0) { perror ("GETITIMER"); return (2); }
if (itvl.it_interval.tv_usec < 2) { printf ("Не удалось выяснить размер такта часов реального времени\n"); } else { printf ("Размер такта часов реального времени: %ld мксек\n", itvl.it_interval.tv_usec); }
return 0; }
Листинг 12.33. Пример программы, использующей функции getitimer() и setitimer().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа сравнивает ход реального и виртуального */ /* времени процесса */ /* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/time.h> #include <signal.h>
#define TM_BUF_SIZE 128
/* Массив для хранения показаний часов */ /* реального времени в момент срабатывания */ /* таймера виртуального времени процесса */ static struct timeval rt_vls [TM_BUF_SIZE]; /* Указатель на текущий элемент */ /* массива rt_vls */ static struct timeval *prt_vls = rt_vls;
/* Функция обработки срабатывания таймеров */ /* (сигналы SIGALRM и SIGVTALRM) */ static void proc_itexprtn (int signo) { struct itimerval itmvl = {{0, 0}, {0, 0}};
/* Запомним текущее астрономическое время */ (void) gettimeofday (prt_vls++, NULL); if (signo == SIGALRM) { /* Сработал таймер реального времени. */ /* Разрядим таймер виртуального времени */ /* и завершимся (с выдачей результатов) */ (void) setitimer (ITIMER_VIRTUAL, &itmvl, NULL); exit (0); } }
/* Функция выдачи данных о ходе реального времени */ /* на фоне равномерного течения виртуального времени процесса */ static void print_rt_data (void) { struct timeval *tprt_vls = rt_vls; int i = 0;
printf ("Прошедшее реальное время за один квант виртуального\n"); while (++tprt_vls != prt_vls) { printf (" %3d %10ld мксек\n", ++i, (tprt_vls->tv_sec - (tprt_vls - 1)->tv_sec) * 1000000 + (tprt_vls->tv_usec - (tprt_vls - 1)->tv_usec)); } }
int main (void) { struct itimerval itvl; struct sigaction sact; sigset_t sset;
/* Установим реакцию на сигналы SIGALRM и SIGVTALRM. */ /* Позаботимся, чтобы функция обработки не могла быть прервана */ /* срабатыванием другого таймера */ if ((sigemptyset (&sset) < 0) || (sigaddset (&sset, SIGALRM) < 0) || (sigaddset (&sset, SIGVTALRM) < 0)) { perror ("SIGEMPTYSET or SIGADDSET"); return (1); }
sact.sa_handler = proc_itexprtn; sact.sa_flags = 0; sact.sa_mask = sset; if (sigaction (SIGALRM, &sact, NULL) < 0) { perror ("SIGACTION-SIGALRM"); return (2); } if (sigaction (SIGVTALRM, &sact, NULL) < 0) { perror ("SIGACTION-SIGVTALRM"); return (3); }
/* Зарегистрируем функцию print_rt_data() в atexit() */ if (atexit (print_rt_data) != 0) { perror ("ATEXIT"); return (4); }
/* Взведем таймер реального времени как одноразовый */ itvl.it_interval.tv_sec = 0; itvl.it_interval.tv_usec = 0; itvl.it_value.tv_sec = 10; itvl.it_value.tv_usec = 0; if (setitimer (ITIMER_REAL, &itvl, NULL) < 0) { perror ("SETITIMER-REAL"); return (5); }
/* Установим начало отсчета для данных о реальном времени */ (void) gettimeofday (prt_vls++, NULL);
/* Таймер виртуального времени сделаем периодическим */ itvl.it_interval.tv_sec = 0; itvl.it_interval.tv_usec = 100000; /* 0.1 сек */ itvl.it_value.tv_sec = 0; itvl.it_value.tv_usec = 100000; if (setitimer (ITIMER_VIRTUAL, &itvl, NULL) < 0) { perror ("SETITIMER-VIRTUAL"); return (6); }
/* Убедимся, что пока процесс приостановлен, */ /* его виртуальное время также стоит */ sleep (5);
/* Нагрузим процессор вычислениями, которые не должны завершиться */ /* до срабатывания таймера реального времени */ { double s = 0; double d = 1; int i;
for (i = 1; i <= 100000000; i++) { s += d / i; d = -d; } }
return 0; }
Листинг 12.34. Пример программы, использующей интервальные таймеры реального и виртуального времени.
Закрыть окно




Прошедшее реальное время за один квант виртуального 1 5255378 мксек 2 249993 мксек 3 250003 мксек 4 100000 мксек 5 250177 мксек 6 859831 мксек 7 100054 мксек 8 729943 мксек 9 580003 мксек 10 99989 мксек 11 580129 мксек 12 429881 мксек 13 99990 мксек
Листинг 12.35. Возможные результаты работы программы, использующей интервальные таймеры реального и виртуального времени.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * */ /* Программа вызывает функции обработки */ /* и контролирует время их выполнения */ /* с помощью интервального таймера */ /* * * * * * * * * * * * * * * * * * * * */
#include <stdio.h> #include <sys/time.h> #include <signal.h> #include <setjmp.h>
/* Период интервального таймера (в секундах) */ #define IT_PERIOD 1
static jmp_buf buf_env; /* Буфер для функций setjmp и longjmp */
static double s; /* Результат функций обработки данных */
/* Функция обработки срабатывания таймера реального времени */ /* (сигнал SIGALRM) */ static void proc_sigalrm (int dummy) { printf ("Текущий результат текущей функции обработки данных: %g\n", s); longjmp (buf_env, 1); }
/* Первая функция обработки данных */ /* (вычисляет ln (2)) */ static void proc_data_1 (void) { double d = 1; int i;
s = 0; for (i = 1; i <= 100000000; i++) { s += d / i; d = -d; } }
/* Вторая функция обработки данных */ /* (вычисляет sqrt (2)) */ static void proc_data_2 (void) { s = 1; do { s = (s + 2 / s) * 0.5; } while ((s * s - 2) > 0.000000001); }
int main (void) { /* Массив указателей на функции обработки данных */ void (*fptrs []) (void) = {proc_data_1, proc_data_2, NULL}; /* Указатель на указатель */ /* на текущую функцию обработки данных */ void (**tfptr) (void); /* Вспомогательная временная переменная */ void (*tmpfptr) (void); struct itimerval itvl; struct sigaction sact; sigset_t sset; int i;
/* Установим реакцию на сигнал SIGALRM */ if (sigemptyset (&sset) < 0) { perror ("SIGEMPTYSET"); return (1); }
sact.sa_handler = proc_sigalrm; sact.sa_flags = SA_NODEFER; /* Не блокировать SIGALRM */ /* в функции обработки этого сигнала */ sact.sa_mask = sset; if (sigaction (SIGALRM, &sact, NULL) < 0) { perror ("SIGACTION"); return (2); }
/* На всякий случай сделаем таймер реального времени периодическим */ itvl.it_interval.tv_sec = IT_PERIOD; itvl.it_interval.tv_usec = 0;
/* Цикл вызова функций обработки данных. */ /* Выполним его дважды */ for (i = 0; i < 2; i++) { tfptr = fptrs; (void) setjmp (buf_env); /* Сюда вернется управление после срабатывания таймера */ while ((tmpfptr = *tfptr++) != NULL) { /* Даже если предыдущая функция обработки данных */ /* закончилась до того, как сработал таймер, */ /* обеспечим текущей функции полный интервал */ itvl.it_value.tv_sec = IT_PERIOD; itvl.it_value.tv_usec = 0; if (setitimer (ITIMER_REAL, &itvl, NULL) < 0) { perror ("SETITIMER"); return (3); } (*tmpfptr) (); printf ("Результат текущей функции обработки данных: %g\n", s); } }
return 0; }
Листинг 12.36. Пример программы, использующей интервальные таймеры реального времени для управления ходом выполнения программы.
Закрыть окно




Текущий результат текущей функции обработки данных: 0.693147 Результат текущей функции обработки данных: 1.41421 Текущий результат текущей функции обработки данных: 0.693147 Результат текущей функции обработки данных: 1.41421
Листинг 12.37. Возможные результаты работы программы, использующей интервальные таймеры реального времени для управления ходом выполнения программы.
Закрыть окно




if (setitimer (ITIMER_REAL, &itvl, NULL) < 0) { . . . }
. . .
(void) setjmp (buf_env);
Листинг 12.38. Пример некорректной последовательности взведения таймера и инициализации структуры для нелокального перехода.
Закрыть окно




#include <unistd.h> unsigned alarm (unsigned seconds);
Листинг 12.39. Описание функции alarm().
Закрыть окно



Содержание раздела