Выбрать главу

Споры разработчиков ядра привели в конечном счете к тому, что частота программных часов стала одной из настроек ядра (Timer frequency в разделе Processor type and features). Начиная с версии ядра 2.6.13, частоте работы часов может устанавливаться значение 100, 250 (по умолчанию) или 1000 Гц, что определяет значения мгновений, равные 10, 4 и 1 миллисекунде соответственно. С версии ядра 2.6.20 стала доступна еще одна частота: 300 Гц, представленная числом, которое делится без остатка на две самые распространенные частоты видеокадров: 25 кадров в секунду (PAL) и 30 кадров в секунду (NTSC).

10.7. Время процесса

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

• Пользовательское время центрального процессора, представляющее собой время, потраченное на выполнение кода в пользовательском режиме. Иногда его называют фактическим временем, и оно является временем, когда программе кажется, что она имеет доступ к ЦП.

• Системное время центрального процессора, представляющее собой время, потраченное на выполнение кода в режиме ядра. Это время, которое ядро затрачивает на выполнение системных вызовов или других задач в интересах программы (например, на обслуживание ошибок отсутствия страниц).

Иногда время процесса называют общим временем центрального процессора, потребленным процессом.

При запуске программы из оболочки для получения обоих значений времени процесса, а также реального времени, требуемого для выполнения программы, можно воспользоваться командой time(1):

$ time./myprog

real 0m4.84s

user 0m1.030s

sys 0m3.43s

Информация о времени процесса может быть извлечена системным вызовом times(), возвращающим ее в структуре, на которую указывает аргумент buf.

#include <sys/times.h>

clock_t times(struct tms *buf);

Возвращает при успешном завершении количество тиков часов (sysconf(_SC_CLK_TCK)) с некоторого момента времени в прошлом, или значение (clock_t) –1 при ошибке

Эта tms-структура, на которую указывает buf, выглядит следующим образом:

struct tms {

clock_t tms_utime; /* Пользовательское время ЦП,

использованное вызывающим процессом */

clock_t tms_stime; /* Системное время ЦП, использованное вызывающим процессом */

clock_t tms_cutime; /* Пользовательское время ЦП, прошедшее в ожидании

завершения всех дочерних процессов */

clock_t tms_cstime; /* Системное время ЦП, прошедшее в ожидании завершения

всех дочерних процессов */

};

В первых двух полях tms-структуры возвращаются пользовательские и системные компоненты времени центрального процессора, до сих пор затраченного вызывающим процессом. Последние два поля возвращают информацию о времени ЦП, затраченном всеми завершившимися дочерними процессами, для которых родительский процесс (то есть процесс, вызвавший times()) выполнил системный вызов wait().

Тип данных clock_t, применяемый для задания типов четырех полей tms-структуры, является целочисленным типом, который используется для времени, замеренного в единицах, называемых тиками часов. Чтобы привести его к секундам, надо значение типа clock_t разделить на результат (значение, которое вернула sysconf(_SC_CLK_TCK)). (Функция sysconf() рассматривается в разделе 11.2.)

В большинстве аппаратных архитектур Linux sysconf(_SC_CLK_TCK) возвращает число 100. Это соответствует константе ядра USER_HZ. Но на некоторых архитектурах, таких как Alpha и IA-64, USER_HZ может быть определена со значением, отличным от 100.

В случае успешного завершения times() возвращает затраченное (реальное) время в тиках часов, прошедшее с некоторого момента в прошлом. В SUSv3 намеренно не указывается, что собой представляет этот момент, — там просто утверждается, что он не должен поменяться в течение всего времени существования вызывающего процесса. Поэтому единственный портируемый вариант использования этого возвращаемого значения — замерить затраченное время в выполнении процесса, вычислив разницу между значениями, возвращенными парой вызовов times(). Но даже при таком использовании возвращаемое значение times() не отличается надежностью, поскольку может переполнить допустимый диапазон значений типа clock_t, и тогда значение снова начнется с нуля. Иными словами, последующий вызов times() может вернуть число, меньшее, чем ранее сделанный вызов times(). Надежный способ замерить протекание затраченного времени — использовать функцию gettimeofday() (рассмотренную в разделе 10.1).