9.2. Является ли привилегированным процесс со следующими идентификаторами пользователя? Обоснуйте ответ.
real=0 effective=1000 saved=1000 file-system=1000
9.3. Реализуйте функцию initgroups(), используя setgroups() и библиотечные функции, для извлечения информации из файлов паролей и групп (см. раздел 8.4). Не забудьте, что для возможности вызова setgroups() процесс должен быть привилегированным.
9.4. Если процесс, чьи пользовательские идентификаторы имеют одинаковое значение X, выполняет set-user-ID-программу, пользовательский идентификатор которой равен Y и имеет ненулевое значение, то полномочия процесса устанавливаются следующим образом:
real=X effective=Y saved=Y
(Мы игнорируем пользовательский идентификатор файловой системы, поскольку его значение следует за действующим идентификатором пользователя.) Запишите соответственно вызовы setuid(), seteuid(), setreuid() и setresuid(), которые будут применяться для выполнения таких операций, как:
1) приостановление и возобновление set-user-ID-идентичности (то есть переключение действующего идентификатора пользователя на значение реального пользовательского идентификатора, а затем возвращение к сохраненному установленному идентификатору пользователя);
2) безвозвратный сброс set-user-ID-идентичности (то есть гарантия того, что для действующего пользовательского идентификатора и сохраненного установленного идентификатора пользователя устанавливается значение реального идентификатора пользователя).
(Это упражнение также требует использования вызовов getuid() и geteuid() для извлечения реального и действующего идентификаторов пользователя.) Учтите, что для некоторых системных вызовов ряд этих операций не может быть выполнен.
9.5. Повторите предыдущее упражнение для процесса выполнения set-user-ID-root-программы, у которой следующий исходный набор идентификаторов процесса:
real=X effective=0 saved=0
10. Время
При выполнении программы нас могут интересовать два вида времени.
• Реальное время. Это время, отмеренное либо от какого-то стандартного момента (календарное время), либо от какого-то фиксированного момента в жизни процесса, обычно от его запуска (затраченное или физическое время). Получение календарного времени требуется в программах, которые, к примеру, ставят отметки времени на записях баз данных или на файлах. Замеры затраченного времени нужны в программах, предпринимающих периодические действия или совершающих регулярные замеры на основе данных, поступающих от внешних устройств ввода.
• Время процесса. Это продолжительность использования процессом центрального процессора. Замеры времени процесса нужны для проверки или оптимизации производительности программы либо алгоритма.
Большинство компьютерных архитектур предусматривают наличие встроенных аппаратных часов, позволяющих ядру замерять реальное время и время процесса. В этой главе мы рассмотрим системные вызовы, работающие с обоими видами времени, и библиотечные функции, занимающиеся преобразованием показателей времени между их легко читаемым и внутренним представлениями. Поскольку легко читаемое представление времени зависит от географического местоположения, а также от языковых и культурных традиций, перед рассмотрением этих представлений потребуется разобраться с понятиями часовых поясов и локали.
В зависимости от географического местоположения, внутри систем UNIX время представляется отмеренным в секундах от начала его отсчета (Epoch): от полуночи 1 января 1970 года, по всемирному координированному времени — Universal Coordinated Time (UTC, ранее называвшемуся средним временем по Гринвичу — Greenwich Mean Time, или GMT). Примерно в это время начали свое существование системы UNIX. Календарное время сохраняется в переменных типа time_t, который относится к целочисленным типам, указанным в SUSv3.
В 32-разрядных системах Linux тип time_t, относящийся к целочисленным типам со знаком, позволяет представлять даты в диапазоне от 13 декабря 1901 года, 20:45:52, до 19 января 2038 года, 03:14:07. (В SUSv3 нет определения отрицательного значения типа time_t.) Таким образом, многие имеющиеся на сегодня 32-разрядные системы UNIX сталкиваются с теоретически возможной проблемой 2038 года, которую им предстоит решить до его наступления, если они в будущем будут выполнять вычисления, связанные с датами. Эту проблему существенно смягчает уверенность в том, что к 2038 году все системы UNIX станут, скорее всего, 64-разрядными или даже более высокой разрядности. Но встроенные 32-разрядные системы, век которых продлится, видимо, намного дольше, чем представлялось поначалу, все же могут столкнуться с этой проблемой. Кроме того, она останется неразрешенной для любых устаревших данных и приложений, работающих со временем в 32-разрядном формате time_t.