8.2 СИСТЕМНЫЕ ОПЕРАЦИИ, СВЯЗАННЫЕ СО ВРЕМЕНЕМ
Существует несколько системных
функций, имеющих отношение к
времени протекания процесса: stime,
time, times и alarm. Первые две имеют дело с
глобальным системным временем,
последние две - с временем
выполнения отдельных процессов.
Функция stime дает
суперпользователю возможность
заносить в глобальную переменную
значение глобальной переменной.
Выбирается время из этой
переменной с помощью функции time:
time(tloc);
где tloc - указатель на переменную,
принадлежащую процессу, в которую
заносится возвращаемое функцией
значение. Функция возвращает это
значение и из самой себя, например,
команде date, которая вызывает эту
функцию, чтобы определить текущее
время.
Функция times возвращает суммарное
время выполнения процесса и всех
его потомков, прекративших
существование, в режимах ядра и
задачи. Синтаксис вызова функции:
times(tbuffer)
struct tms *tbuffer;
где tms - имя структуры, в которую
помещаются возвращаемые значения и
которая описывается следующим
образом:
struct tms {
/* time_t - имя структуры данных, в которой хранится время */
time_t tms_utime; /* время выполнения процесса в режиме задачи */
time_t tms_stime; /* время выполнения процесса в режиме ядра */
time_t tms_cutime; /* время выполнения потомков в режиме задачи */
time_t tms_cstime; /* время выполнения потомков в режиме ядра */
};
Функция times возвращает
время, прошедшее "с некоторого
произвольного момента в
прошлом", как правило, с момента
загрузки системы.
#include <sys/types.h>
#include <sys/times.h>
extern long times();
main()
{
int i;
/* tms - имя структуры данных, состоящей из 4 элемен-
тов */
struct tms pb1,pb2;
long pt1,pt2;
pt1 = times(&pb1);
for (i = 0; i < 10; i++)
if (fork() == 0)
child(i);
for (i = 0; i < 10; i++)
wait((int*) 0);
pt2 = times(&pb2);
printf("процесс-родитель: реальное время %u
в режиме задачи %u в режиме ядра %u
потомки: в режиме задачи %u в режиме ядра %un",
pt2 - pt1,pb2.tms_utime - pb1.tms_utime,
pb2.tms_stime - pb1.tms_stime,
pb2.tms_cutime - pb1.tms_cutime,
pb2.tms_cstime - pb1.tms_cstime);
}
child(n);
int n;
{
int i;
struct tms cb1,cb2;
long t1,t2;
t1 = times(&cb1);
for (i = 0; i < 10000; i++)
;
t2 = times(&cb2);
printf("потомок %d: реальное время %u в режиме задачи %u
в режиме ядра %un",n,t2 - t1,
cb2.tms_utime - cb1.tms_utime,
cb2.tms_stime - cb1.tms_stime);
exit();
}
|
Рисунок 8.7. Пример
программы, использующей функцию times
На Рисунке 8.7 приведена
программа, в которой
процесс-родитель создает 10
потомков, каждый из которых 10000 раз
выполняет пустой цикл.
Процесс-родитель обращается к
функции times перед созданием
потомков и после их завершения, в
свою очередь потомки вызывают эту
функцию перед началом цикла и после
его завершения. Кто-то по наивности
может подумать, что время
выполнения потомков процесса в
режимах задачи и ядра равно сумме
соответствующих слагаемых каждого
потомка, а реальное время
процесса-родителя является суммой
реального времени его потомков.
Однако, время выполнения потомков
не включает в себя время,
затраченное на исполнение
системных функций fork и exit, кроме
того оно может быть искажено за
счет обработки прерываний и
переключений контекста.
С помощью системной функции alarm
пользовательские процессы могут
инициировать посылку сигналов
тревоги ("будильника") через
кратные промежутки времени.
Например, программа на Рисунке 8.8 каждую
минуту проверяет время доступа к
файлу и, если к файлу было
произведено обращение, выводит
соответствующее сообщение. Для
этого в цикле, с помощью функции stat,
устанавливается момент последнего
обращения к файлу и, если оно имело
место в течение последней минуты,
выводится сообщение. Затем процесс
с помощью функции signal делает
распоряжение принимать сигналы
тревоги, с помощью функции alarm
задает интервал между сигналами в 60
секунд и с помощью функции pause
приостанавливает свое выполнение
до момента получения сигнала. Через
60 секунд сигнал поступает, ядро
подготавливает стек задачи к
вызову функции обработки сигнала
wakeup, функция возвращает управление
на оператор, следующий за вызовом
функции pause, и процесс исполняет
цикл вновь.
Все перечисленные функции работы
с временем протекания процесса
объединяет то, что они опираются на
показания системных часов
(таймера). Обрабатывая прерывания
по таймеру, ядро обращается к
различным таймерным счетчикам и
инициирует соответствующее
действие.
Предыдущая
глава || Оглавление
|| Следующая глава
|