times() yields: user CPU=0.00; system CPU: 0.00
After getppid() loop:
clock() returns: 2960000 clocks-per-sec (2.96 secs)
times() yields: user CPU=1.09; system CPU: 1.87
Листинг 10.5. Извлечение затраченного процессом времени ЦП
time/process_time.c
#include
#include
#include "tlpi_hdr.h"
static void /* Вывод сообщения, на которое указывает 'msg',
и показателей времени процесса */
displayProcessTimes(const char *msg)
{
struct tms t;
clock_t clockTime;
static long clockTicks = 0;
if (msg!= NULL)
printf("%s", msg);
if (clockTicks == 0) { /* Извлечение тиков часов в первом вызове */
clockTicks = sysconf(_SC_CLK_TCK);
if (clockTicks == -1)
errExit("sysconf");
}
clockTime = clock();
if (clockTime == -1)
errExit("clock");
printf(" clock() returns: %ld clocks-per-sec (%.2f secs)\n",
(long) clockTime, (double) clockTime / CLOCKS_PER_SEC);
if (times(&t) == -1)
errExit("times");
printf(" times() yields: user CPU=%.2f; system CPU: %.2f\n",
(double) t.tms_utime / clockTicks,
(double) t.tms_stime / clockTicks);
}
int
main(int argc, char *argv[])
{
int numCalls, j;
printf("CLOCKS_PER_SEC=%ld sysconf(_SC_CLK_TCK)=%ld\n\n",
(long) CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK));
displayProcessTimes("At program start: \n");
numCalls = (argc > 1)? getInt(argv[1], GN_GT_0, "num-calls")
: 100000000;
for (j = 0; j < numCalls; j++)
(void) getppid();
displayProcessTimes("After getppid() loop: \n");
exit(EXIT_SUCCESS);
}
time/process_time.c
Реальное время соответствует обычному определению времени. Когда реальное время отмеряется от какого-то стандартного момента, мы называем его календарным временем; затраченным временем называется время, отмеряемое от какого-либо момента в жизни процесса (обычно от его запуска).
Время процесса представляет собой время центрального процессора, использованное процессом, и разбивается на пользовательский и системный компоненты.
Получить и установить значение системных часов (то есть календарного времени, замеренного в секундах от начала отсчета (Epoch)) позволяют различные системные вызовы, а некоторые библиотечные функции дают возможность выполнять преобразования между календарным временем и другими форматами времени, включая разделенное время (время, разбитое на компоненты) и время в виде читаемых символьных строк. Описание этих преобразований не обходится без рассмотрения вопросов локалей и интернационализации.
Использование времени и даты, а также вывод их на экран важны для многих приложений, и функции, рассмотренные в этой главе, будут еще часто упоминаться на протяжении всей книги. Дополнительно вопросы замеров времени мы также рассмотрим в главе 23.
Подробности, касающиеся способов замеров времени ядром Linux, можно найти в [Love, 2010].
Подробно о часовых поясах и интернационализации вы можете прочитать в руководстве по GNU-библиотеке C (по адресу http://www.gnu.org
/). Подробности относительно локалей также можно найти в документах по SUSv3.10.1. Возьмем систему, где вызов sysconf(_SC_CLK_TCK) возвращает значение 100. Сколько времени пройдет, пока значение типа clock_t, возвращенное функцией times(), снова превратится в 0, при условии, что оно представлено 32-разрядным целым числом? Выполните такое же вычисление для значения CLOCKS_PER_SEC, возвращенного функцией clock().
11. Системные ограничения и возможности
Каждая реализация UNIX накладывает ограничения (limits) на различные системные характеристики и ресурсы и предоставляет возможности (options), определенные в различных стандартах (или отказывает в их предоставлении). Например, можно определить следующее.
• Сколько файлов процесс может одновременно держать открытыми?
• Поддерживает ли система сигналы реального времени?
• Какое наибольшее значение может быть сохранено в переменной типа int?
• Насколько большим может быть список аргументов программы?
• Какова максимальная длина путевого имени?
Можно, конечно, жестко задать ограничения и возможности в самом приложении, но это снизит портируемость, поскольку все ограничения и возможности могут варьироваться:
•