учебники, программирование, основы, введение в,

 

Время и работа с ним

Основные понятия и объекты
Согласно стандарту POSIX, за начало отсчета (астрономического) времени принимается ноль часов, ноль минут, ноль секунд первого января 1970-го года универсального координированного времени (далее для краткости именуемого также всемирным).
Всемирным называют поясное время нулевого часового пояса, которое представляет собой местное среднее солнечное время гринвичского меридиана.
Московское время опережает всемирное на три часа. Имеется в виду так называемое декретное московское время, которое не следует путать с поясным.
Поясное время Москвы, лежащей во втором часовом поясе, опережает всемирное на два часа.
Московское летнее время опережает всемирное на 4 часа.
За стандартную единицу измерения астрономического времени в POSIX-2001 принята секунда. Пусть некоторый момент времени задан в терминах секунд (значение tm_sec), минут (tm_min), часов (tm_hour), а также номером дня в году (tm_yday) и номером года минус 1900 (tm_year). Тогда число секунд всемирного времени, прошедшее на этот момент от начала отсчета, вычисляется по формуле
tm_sec + tm_min*60 + tm_hour*3600 +
tm_yday*86400 + (tm_year-70)*31536000 +
((tm_year-69)/4)*86400 - ((tm_year-1)/100)*
86400 + ((tm_year+299)/400)*86400
(три последних слагаемых предназначены для учета високосных лет).
Учет разного рода поправок к всемирному времени (таких, например, как вставка дополнительной секунды в начале 1996 года) зависит от реализации.
Для представления данных о моментах времени в программах на языке C обычно используется структура tm, описанная во включаемом файле <time.h> и содержащая, согласно стандарту POSIX-2001, по крайней мере следующие поля.
int tm_sec;   /* Секунды [0,60]             */
int tm_min;   /* Минуты [0,59]              */
int tm_hour;  /* Часы [0,23]                */
int tm_mday;  /* Номер дня в месяце [1,31]  */
int tm_mon;   /* Номер месяца в году [0,11] */
int tm_year;  /* Номер года минус 1900      */
int tm_wday;  /* Номер дня недели [0,6]     */
/* (воскресенью соответствует ноль) */
int tm_yday;  /* Номер дня в году [0,365]   */
int tm_isdst;
/* Признак учета летнего времени */
Диапазон [0, 60] для поля tm_sec позволяет справляться с производимой время от времени вставкой дополнительной секунды.
Значение поля tm_year задается со знаком, что позволяет представлять годы до 1900.
Значение признака tm_isdst должно быть положительным, если действует летнее время, нулевым, если летнее время не действует, или отрицательным, если про летнее время ничего не известно.
Часами называется программный или аппаратный объект, предназначенный для измерения видимого или истинного хода времени.
Показания часов можно опросить и установить (в допустимых для часов пределах).
Разрешающей способностью часов называется минимальный промежуток времени, который может быть этими часами измерен.
Под скачком часов понимается разность между двумя последовательными, различными с точки зрения приложения (использующего стандартные средства) показаниями часов.
Часы называются монотонными, если их нельзя установить стандартными средствами и они не могут иметь отрицательных скачков.
Такт часов - это зависящие от реализации промежутки времени, на которые дробится каждая секунда.
Реальным (или астрономическим) называется время, измеренное по системным часам безотносительно к тому, какой процесс (поток управления) выполняется.
Под временем выполнения (процессорным временем) понимается время, затрачиваемое на выполнение процесса (потока управления), включая работающие от его имени системные сервисы.
Время выполнения конкретного процесса или потока управления измеряется часами процессорного времени.
Под мониторингом времени выполнения понимается оперативное отслеживание процессорного времени, затрачиваемого процессом (потоком управления).
Виртуальное время процесса - время, измеряемое системными часами, пока процесс выполняется.
Таймер - это механизм, способный известить процесс (поток управления) об истечении заданного временного промежутка (подобный таймер называется интервальным) или о достижении (или превышении) часами заданных показаний (абсолютный таймер). Соответствующее событие называется срабатыванием таймера.
Таймером процессорного времени называется таймер, ассоциированный с часами процессорного времени.
Взвести (зарядить) - значит запустить таймер, измеряющий ход времени и позволяющий уведомить процесс о наступлении заданного момента.
Таймер снимается со взвода (разряжается), когда он перестает измерять ход времени, отключая тем самым будущие уведомления процесса до нового взведения таймера.
Таймеры можно подразделить на одноразовые и периодические.
Одноразовые таймеры снимаются со взвода после первого (и единственного) срабатывания.
Периодические таймеры после очередного срабатывания запускаются вновь в соответствии с однажды заданной спецификацией следующего срабатывания.
Под избыточным срабатыванием таймера понимается ситуация, когда таймер срабатывает до того, как процесс обработал сигнал о предыдущем срабатывании.
Все, что касается часов процессорного времени и таймеров, относится к необязательным частям стандарта POSIX-2001. Тем не менее, мы детально рассмотрим соответствующие средства ввиду их важности и употребительности.
Опрос и установка показаний часов реального времени
Простейшим средством опроса и/или изменения текущих даты и времени является служебная программа date:
date  [-u] [+формат]
date  [-u] ммддччмм[[вв]гг]

В первой форме утилита date выдает на стандартный вывод дату и время (по умолчанию - текущие), в соответствии с заданным форматом. Во второй форме date позволяет установить системные дату и время.
При наличии опции -u работа ведется без учета часового пояса, во всемирном времени (как если бы значением переменной окружения TZ была цепочка "UTC0"). Без этой опции учитывается значение TZ или, если таковое не установлено или пусто, принимается во внимание системное подразумеваемое значение.
Если в командной строке date задан аргумент, начинающийся со знака +, форматом вывода даты и времени управляет пользователь. Формат включает спецификаторы преобразований и прочие символы (последние выводятся без изменений). Спецификаторы преобразований начинаются со знака % и замещаются при выводе соответствующим значением.


Таблица 12.1. Спецификаторы преобразований

Спецификатор

Описание

%a

Сокращенное название дня недели.

%A

Полное название дня недели.

%b

Сокращенное название месяца.

%B

Полное название месяца.

%c

Принятое в данной языково-культурной среде представление даты и времени.

%C

Две первые цифры четырехзначного номера года [00, 99].

%d

Номер дня в месяце [01, 31].

%D

Дата в формате мм/дд/гг.

%e

Номер дня в месяце [1, 31] в двухсимвольном поле с дополнением, при необходимости, пробела.

%h

То же, что %b.

%H

Номер часа [00, 23].

%I

Номер часа [01, 12].

%j

Номер дня в году [001, 366].

%m

Номер месяца [01, 12].

%M

Минуты [00, 59].

%n

Перевод строки

%S

Секунды [00, 60].

%t

Табуляция

%T

Время в формате чч:мм:сс.

%u

Номер дня недели [1, 7] (единица соответствует понедельнику).

%U

Номер недели в году [00, 53]. Первым днем недели считается воскресенье. Все дни нового года, предшествующие первому воскресенью, относятся к нулевой неделе.

%V

Номер недели в году [01, 53]. Первым днем недели считается понедельник. Если первое января приходится на пятницу, субботу или воскресенье, конец недели формально относят к прошлому году, а первой считают следующую неделю.

%w

Номер дня недели [0, 6] (ноль соответствует воскресенью).

%W

Номер недели в году [00, 53]. Первым днем недели считается понедельник. Все дни нового года, предшествующие первому понедельнику, относятся к нулевой неделе.

%x

Принятое в данной языково-культурной среде представление даты.

%X

Принятое в данной языково-культурной среде представление времени.

%y

Две младшие цифры номера года [00, 99].

%Y

Четырехзначный номер года.

%Z

Имя часового пояса.

%%

Знак процента.

Чтобы установить текущие дату и время, необходимо, чтобы система допускала данное действие, а у процесса были соответствующие привилегии.
Во второй форме вызова утилиты date первая пара букв м обозначает номер месяца, дд - номер дня в месяце, чч - часы, мм - минуты, ввгг - год. Если две первые цифры года опущены, то диапазон [69, 99] трактуется как [1969, 1999], а [00, 68] - как [2000, 2068]. Если год не указан, имеется в виду текущий.
Приведем несколько примеров употребления служебной программы date.
Вывод в подразумеваемом формате, используемом командой date без аргументов, может выглядеть так:
Fri Dec 26 17:48:02 MSK 2003
Опция -u повлияет на вывод следующим образом:
Fri Dec 26 14:48:05 UTC 2003
Команда
date '+Дата: %d.%m.%Y%nВремя: %H:%M:%S'
выдаст примерно следующее:
Дата: 26.12.2003
Время: 17:49:15

Для сдвига показаний системных часов на один час вперед можно воспользоваться shell-процедурой, показанной в листинге(предполагается, что ее выполняют днем при наличии соответствующих привилегий).
moda=`date +%m%d`
ho=$((`date +%H` + 1))
mi=`date +%M`
date ${moda}${ho}${mi}
Листинг 12.1. Пример использования служебной программы date.
На уровне языка C для опроса текущего времени (в секундах от начала отсчета) служит функция time().
#include <time.h>
time_t time (time_t *tloc);
Листинг 12.2. Описание функции time().
Если значение аргумента tloc отлично от пустого указателя, то текущее время не только возвращается в качестве результата, но еще и записывается по заданному адресу.
Отметим, что если тип time_t реализован как 32-разрядное целое со знаком, то в 2038-м году наступит переполнение (так называемая проблема 2038-го года). Стандарт POSIX-2001 не справляется с проблемой в полной мере, но облегчает ее решение за счет использования более или менее абстрактного типа time_t вместо какой-либо конкретной разновидности int. Вероятно, в последующие версии стандарта POSIX будут включены требования к способности значений типа time_t представлять время в далеком будущем (например, вплоть до 10000-го года) или явное требование не менее чем 64-разрядности.
С функцией time() ассоциирована функция difftime(), вычисляющая (в виде значения типа double) разность в секундах между двумя моментами времени.
#include <time.h>
double difftime (time_t time1, time_t time0);
Листинг 12.3. Описание функции difftime().
Узнать текущее время с большей точностью позволяет функция gettimeofday().
#include <sys/time.h>
int gettimeofday (struct timeval *restrict tp,
void *restrict tzp);
Листинг 12.4. Описание функции gettimeofday().
Согласно стандарту POSIX-2001, описанная в заголовочном файле <sys/time.h> структура timeval содержит по крайней мере следующие поля.
time_t      tv_sec;     /* Секунды */
suseconds_t tv_usec;    /* Микросекунды */
Функция gettimeofday() записывает текущее время, выраженное в секундах и микросекундах от начала отсчета, в структуру типа timeval, на которую указывает аргумент tp. Указатель tzp должен быть пустым.
Впрочем, микросекунды - это еще на предел точности, а опрос системных часов - не предел общности. В необязательную часть стандарта POSIX-2001, регламентирующую работу с таймерами, входят функции, позволяющие опросить и установить показания заданных часов, а также узнать их разрешающую способность.
#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. Описание функций опроса характеристик и установки часов.
Структура timespec отличается от timeval тем, что вместо микросекунд хранит наносекунды:
time_t tv_sec;  /* Секунды */
long   tv_nsec; /* Наносекунды */
Функция clock_getres() позволяет опросить разрешающую способность часов с заданным идентификатором и поместить результат в структуру, на которую указывает аргумент res.
Функция clock_gettime() записывает в аналогичную структуру текущие показания заданных часов.
Наконец, функция clock_settime() устанавливает заданные часы на основании значений полей структуры типа timespec, на которую указывает аргумент tp.
Часы могут быть общесистемными, т. е. видимыми для всех процессов, или принадлежащими процессу (измеряют время, имеющее смысл только для конкретного процесса). Все реализации должны поддерживать общесистемные часы реального времени, измеряющие время от начала отсчета и имеющие идентификатор CLOCK_REALTIME. Интерпретация показаний других часов (если таковые имеются) стандартом не специфицируется.
Установка новых показаний для часов CLOCK_REALTIME влияет на срабатывание таймеров, взведенных на абсолютное время, но не затрагивает интервальные таймеры.
Если в системе поддерживаются монотонные часы (с идентификатором CLOCK_MONOTONIC), они измеряют время от некоторого неспецифицированного момента в прошлом (например, от загрузки системы или начала отсчета). Монотонные часы предназначены для измерения относительного времени. По определению, их показания нельзя установить с помощью функции clock_settime().
Применение описанных выше функций иллюстрируется программой, показанной в. Возможно, при редактировании ее внешних связей придется указать дополнительные библиотеки (например, -lrt), что является следствием использования необязательных компонентов стандарта POSIX.
Листинг 12.6. Пример программы, использующей функции опроса показаний часов реального времени.
Результаты работы этой программы могут выглядеть так, как показано в.
Листинг 12.7. Возможные результаты работы программы, использующей функции опроса показаний часов реального времени.
Преобразование данных о времени
Стандартом POSIX-2001 предусмотрено несколько способов представления данных о времени. Выше были описаны структура tm и тип time_t. Кроме того, время может записываться в виде цепочки символов. (Есть еще структуры timeval и timespec, но они в данном контексте играют подчиненную роль, лишь уточняя значения типа time_t.)
Для выполнения преобразований между разными представлениями данных о времени служат описываемые далее функции ).
Функции gmtime() и localtime() преобразуют значения типа time_t в структуру типа tm. Соотношение между временем в секундах от начала отсчета и значениями полей структуры типа tm дается в приведенной выше формуле. Кроме того, функция localtime() учитывает данные о часовом поясе и сезонных поправках.
#include <time.h>
struct tm *gmtime (const time_t *tloc);
struct tm *localtime (const time_t *tloc)
Листинг 12.8. Описание функций gmtime() и localtime().
Для учета данных о часовом поясе и сезонных поправках используются внешние переменные tzname, timezone, daylight, значения которых функция tzset() устанавливает по переменной окружения TZ.
#include <time.h>
extern char *tzname[2];
extern long timezone;
extern int daylight;
void tzset (void);
Листинг 12.9. Описание функции tzset() и ассоциированных внешних переменных.
Элементам массива tzname присваиваются имена местного часового пояса в стандартном (tzname [0]) и "летнем" (tzname [1]) вариантах. Значение переменной timezone устанавливается равным разности в секундах между всемирным и местным поясным временем. Переменной daylight присваивается отличное от нуля значение, если для местного часового пояса предусмотрен переход на летнее время.
Отметим, что в общем случае значение переменой окружения TZ устроено довольно сложным образом:
Станд_поясСмещение[Лет_пояс[Смещение]
[,Нач_лет[/Время],Кон_лет[/Время]]]
Здесь Станд_пояс и Лет_пояс - имена, присваиваемые элементам массива tzname [], Смещение - разность между всемирным и местным поясным временем (в виде чч[:мм[:сс]]), Нач_лет и Кон_лет, соответственно, даты начала и окончания действия летнего времени (обычно их задают в виде Mмм.н.д - месяц, неделя, день), время - время перехода (по умолчанию - два часа ночи). Можно видеть, что данных для вычисления местного времени оказывается вполне достаточно.
Функцию mktime() можно считать обратной по отношению к localtime(). Она преобразует местное время, заданное в виде структуры типа tm, в значение типа time_t, т. е. в секунды от начала отсчета по всемирному времени.
#include <time.h>
time_t mktime (struct tm *tmptr);
Листинг 12.10. Описание функции mktime().
При входе в функцию mktime() значения полей tm_wday и tm_yday структуры tm, на которую указывает аргумент tmptr, игнорируются; при выходе они устанавливаются должным образом. Значения других полей также приводятся к стандартным для них диапазонам (при входе это условие может не выполняться).
Другим весьма мощным средством преобразования местного времени из структурного в текстовое представление является функция strftime(). Как и служебная программа date, она преобразует дату и время в соответствии с заданным форматом, только исходными данными служит не текущий момент времени, а структура типа tm, на которую указывает аргумент tmptr, и результат направляется не на стандартный вывод, а в буфер, заданный указателем s и длиной maxsize.
#include <time.h>
size_t strftime (char *restrict s,
size_t maxsize, const char *restrict format,
const struct tm *restrict tmptr);
Листинг 12.11. Описание функции strftime().
По сравнению с date, функция strftime() содержит несколько дополнительных спецификаторов форматных преобразований. Перечислим наиболее употребительные из них.


Таблица 12.1. Спецификаторы преобразований

Спецификатор

Описание

%F

Представление даты в соответствии со стандартом ISO 8601:2000: эквивалент последовательности спецификаторов %Y-%m-%d.

%R

Часы и минуты (%H:%M) в 24-часовом представлении.

%z

Смещение относительно всемирного времени, представленное по стандарту ISO 8601:2000: +ччмм или -ччмм (положительные значения соответствуют часовым поясам к востоку от Гринвича).

Функция strftime() возвращает число байт, помещенное в буфер (без учета завершающего нулевого байта). Если буфер оказался мал, возвращается ноль.
На роль обратной по отношению к strftime() могут претендовать сразу две функции: strptime() и getdate().
#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().
Функция strptime() напоминает sscanf(): она сканирует цепочку символов, на которую указывает аргумент s, в соответствии с заданным форматом, включающим описанные выше спецификаторы преобразований, а также, быть может, пробельные и обычные символы, и помещает извлеченные значения в структуру типа tm по указателю tmptr. В качестве результата возвращается указатель на первый несканированный символ или NULL в случае неудачи.
Функция getdate(), по сути аналогичная strptime(), использует для разбора входной цепочки s форматы, содержащиеся в файле, чье полное маршрутное имя задано переменной окружения DATEMSK (для интерпретации выбирается первый подходящий формат). Если дата и время специфицированы не полностью (например, задан только день недели), как исходные берутся данные о первом подходящем моменте времени, начиная с текущего. Если в формате присутствует спецификатор %Z, выходная структура инициализируется текущим временем в сканируемом часовом поясе. В противном случае применяется местное время.
С помощью внешней переменной (или макроса) getdate_err функция getdate() возвращает коды ошибок.
Приведем пример использования описанных функций преобразования данных о времени.
Листинг 12.13. Пример программы, использующей функции преобразования данных о времени.
Возможные результаты выполнения этой программы показаны в.
Листинг 12.14. Возможные результаты работы программы, использующей функции преобразования данных о времени.
Последовательность инструкций языка C
char dtbuf [];
time_t st;
(void) strftime (dtbuf, sizeof (dtbuf), "%c",
localtime (&st));
является стандартной для получения текущего времени в текстовом виде. (Разумеется, вместо "%c" допустим другой спецификатор преобразования.) Нужно помнить только, что функции gmtime() и localtime() возвращают указатели на статические структуры, содержимое которых, возможно, перезаписывается при каждом вызове, поэтому, если оно понадобится в дальнейшем, его следует скопировать в собственные объекты.

http://localhost:3232/img/empty.gifhttp://localhost:3232/img/empty.gifОпрос показаний часов процессорного времени

Базовым средством для работы с часами процессорного времени является функция clock(). Она возвращает в качестве результата процессорное время, затраченное процессом с некоего момента, зависящего от реализации и связанного только с его (процесса) запуском. В случае ошибки результат равен (clock_t) (-1).
#include <time.h>
clock_t clock (void);
Листинг 12.15. Описание функции clock().
Чтобы перевести время, возвращаемое функцией clock(), в секунды, его следует поделить на константу CLOCKS_PER_SEC, которая определена в заголовочном файле <time.h> равной одному миллиону, хотя разрешающая способность часов процессорного времени в конкретной реализации может и отличаться от микросекунды.
Отметим, что если значения типа clock_t представлены как 32-разрядные целые со знаком, то менее чем через 36 минут (процессорного времени) наступит переполнение.
В показан пример использования функции clock(). Поскольку начало отсчета для часов процессорного времени не специфицировано, их показания опрашиваются в начале и конце измеряемого промежутка, а результатом измерения затраченного процессорного времени служит разность этих показаний.
Листинг 12.16. Пример программы, использующей функции опроса показаний часов реального и процессорного времени.
Возможные результаты работы этой программы показаны в. Процессорное время получилось больше астрономического из-за ошибок округления.
Начало выполнения цикла
Процессорное время выполнения цикла: 15.19 сек.
Астрономическое время выполнения цикла: 15 сек.
Листинг 12.17. Возможные результаты работы программы, использующей функции опроса показаний часов реального и процессорного времени.
Для измерения времени выполнения простой команды можно воспользоваться служебной программой time (не входящей, правда, в обязательную часть стандарта POSIX-2001):
time [-p] команда [аргумент ...]
Она выдает в стандартный протокол астрономическое и процессорное время, прошедшее от запуска до завершения команды с указанными аргументами. Если задана опция -p, время выдается в секундах в виде вещественных чисел. Процессорное время подразделяется на пользовательское (затраченное самой командой) и системное (ушедшее на оказание системных услуг команде). Если предположить, что выполнимый файл приведенной выше программы называется my_tcex, то командная строка
time -p my_tcex
выдаст в стандартный протокол примерно следующее:
Начало выполнения цикла
Процессорное время выполнения цикла: 15.2 сек.
Астрономическое время выполнения цикла: 15 сек.
real 15.20
user 15.20
sys 0.00
Листинг 12.18. Возможные результаты измерения времени работы программы, использующей функции опроса показаний часов реального и процессорного времени.
Если нужно измерить время выполнения конвейера или списка команд, их можно поместить в файл, превратив тем самым в простую команду, или воспользоваться конструкцией вида
time sh -c 'составная команда'
Оружием более крупного калибра является специальная встроенная в shell команда
times
Она выдает на стандартный вывод процессорное время, затраченное командным интерпретатором и порожденными им процессами. Например, после выполнения команд
my_tcex & my_tcex
times
на стандартный вывод может быть выдано:
0m0.010s 0m0.000s
0m30.410s 0m0.000s
Можно видеть, что сам командный интерпретатор практически не занимал процессор, а два порожденных им процесса в сумме потребили чуть меньше тридцати с половиной секунд; время системных услуг в обоих случаях оказалось пренебрежимо малым.
Реализация описанных выше утилит time и times опирается на функцию times(). Она опрашивает данные о времени выполнения вызывающего процесса и порожденных процессов, завершение которых ожидалось с помощью функций wait() или waitpid(). В отличие от clock(), функция times() измеряет время в тактах часов, и переполнение 32-разрядного представления значений типа clock_t происходит не через полчаса, а примерно в течение года (если секунда делится на 60 - 100 тактов). Соответственно, для перевода результатов работы times() в секунды их нужно делить на sysconf (_SC_CLK_TCK), а не на CLOCKS_PER_SEC.
#include <sys/times.h>
clock_t times (struct tms *buffer);
Листинг 12.19. Описание функции times().
В качестве результата функция times() возвращает астрономическое время, прошедшее от некоторого момента в прошлом (например, от загрузки системы), но основные, содержательные данные, относящиеся к вызывающему процессу и его потомкам, помещаются в структуру типа tms, которая описана в заголовочном файле <sys/times.h> и, согласно стандарту POSIX-2001, должна содержать по крайней мере следующие поля:
clock_t tms_utime; 
/* Процессорное время, затраченное */
/* вызывающим процессом            */

clock_t tms_stime; 
/* Процессорное время, затраченное системой */
/* на обслуживание вызывающего процесса     */

clock_t tms_cutime;
/* Процессорное время, затраченное
/*завершившимися порожденными процессами    */

clock_t tms_cstime;
/* Процессорное время, затраченное системой */
/* на обслуживание завершившихся            */
/* порожденных процессов                    */
Значения времени завершившихся порожденных процессов (tms_utime и tms_cutime, а также tms_stime и tms_cstime) добавляются, соответственно, к элементам tms_cutime и tms_cstime структуры родительского процесса при возврате из функций wait() или waitpid(). Это происходит рекурсивно: если порожденный процесс ожидал завершения своих потомков, то в упомянутых элементах структуры накопятся данные о времени выполнения поддерева процессов.
В качестве примера использования функции times() измерим время работы рассматривавшейся ранее программы, копирующей строки со стандартного ввода на стандартный вывод через сокеты адресного семейства AF_UNIX с помощью порожденного процесса .
Листинг 12.20. Пример программы, использующей функцию times().
Если перенаправить стандартный ввод в какой-либо текстовый файл заметных размеров, а стандартный вывод - в другой файл, можно получить результаты, подобные тем, что показаны в.
Листинг 12.21. Возможные результаты работы программы, использующей функцию times().
Прямое манипулирование часами процессорного времени возможно после обращения к функции clock_getcpuclockid(), позволяющей выяснить их идентификатор. Оговоримся, однако, что эта функция не входит в обязательную часть стандарта POSIX-2001 (она относится к продвинутым средствам реального времени).
#include <time.h>
int clock_getcpuclockid
(pid_t pid, clockid_t *clock_id);
Листинг 12.22. Описание функции clock_getcpuclockid().
Идентификатор часов процессорного времени, обслуживающих заданный аргументом pid процесс, возвращается по адресу, специфицированному аргументом clock_id. Если значение pid равно нулю, имеется в виду вызывающий процесс. Признаком успешного завершения является нулевой результат; в противном случае возвращается код ошибки.
В показан пример употребления функции clock_getcpuclockid() и манипулирования часами процессорного времени. Возможные результаты выполнения этой программы - в.
Листинг 12.23. Пример программы, манипулирующей часами процессорного времени.
Листинг 12.24. Возможные результаты работы программы, манипулирующей часами процессорного времени.
Обратим внимание на два момента. Перед началом измеряемого участка программы на часах процессорного времени были установлены нулевые показания, что, разумеется, не влияет на приоритет процесса и его планирование. Конечно, можно было обойтись без переустановки, запомнив показания часов в начале и конце измеряемого промежутка и произведя затем их вычитание, но технически это чуть сложнее; кроме того, нам хотелось применить функцию clock_settime(). Второй заслуживающий отдельного упоминания момент состоит в отсутствии необходимости выяснять идентификатор часов процессорного времени вызывающего процесса с помощью функции clock_getcpuclockid(): можно воспользоваться именованной константой CLOCK_PROCESS_CPUTIME_ID.
Опрос и изменение данных о времени, ассоциированных с файлами
Информацию о файле, в том числе данные о времени последнего доступа и изменения, можно получить с помощью описанных ранее функций семейства stat().
Для изменения ассоциированных с файлами данных о времени служит функция utime(), оперирующая в терминах секунд от начала отсчета.
#include <utime.h>
int utime (const char *path,
const struct utimbuf *times);
Листинг 12.25. Описание функции utime().
Если значение аргумента times равно пустому указателю, используется текущее время. В этом случае для успешного изменения данных о времени действующий идентификатор процесса должен соответствовать владельцу файла либо процесс должен иметь права на запись в файл или соответствующие привилегии.
Если значение times отлично от NULL, оно трактуется как указатель на структуру типа utimbuf, которая, согласно стандарту POSIX-2001, содержит по крайней мере следующие поля:
time_t actime; 
/* Время последнего доступа   */

time_t modtime;
/* Время последнего изменения */
При этом данные о времени устанавливаются по указуемой структуре, а вызывающий процесс должен обладать соответствующими привилегиями или действующим идентификатором, совпадающим с идентификатором владельца файла (наличия права на запись недостаточно).

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика