printf("Hello world");

execlp("sleep", "sleep", "0", (char *) NULL);

}

27.6. Представьте, что родительский процесс установил обработчик для SIGCHLD и заблокировал этот сигнал. После того как один из его потомков завершается, родитель выполняет вызов wait(), чтобы получить статус потомка. Что произойдет, если родитель разблокирует SIGCHLD? Напишите программу, чтобы проверить свой ответ. Имеет ли это какое-либо отношение к программе, вызывающей функцию system()?

<p>28. Подробнее о создании процесса и выполнении программы</p>

Эта глава дополняет материал, изложенный в главах 24–27, охватывая различные темы, касающиеся создания процесса и выполнения программы. Будет описан учет используемых ресурсов — функция, ядра, которая в момент завершения любого процесса в системе записывает его учетную информацию. Мы рассмотрим системный вызов clone(), который представляет собой низкоуровневый программный интерфейс для создания потоков выполнения в Linux. За этим последует сравнение производительности fork(), vfork() и clone(). В конце будет рассмотрено влияние вызовов fork() и exec() на атрибуты процесса.

28.1. Учет ресурсов, используемых процессом

Когда система учета ресурсов включена, ядро записывает в общесистемный файл данные о каждом процессе, который оно завершает. Каждая такая запись содержит различные сведения, собираемые ядром, такие как код завершения процесса и сколько тот затратил процессорного времени. Учетный файл можно анализировать с помощью стандартных инструментов (вызов sa(8) предоставляет краткую сводку, а lastcomm(1) показывает информацию о ранее выполненных командах) или специализированных приложений.

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

Система учета ресурсов не описывается в стандарте SUSv3, хотя и доступна в большинстве разновидностей UNIX. Формат записей и местоположение файла, в котором они хранятся, могут варьироваться в зависимости от реализации. В этом разделе мы сосредоточимся на деталях, характерных для Linux, не забывая при этом отмечать некоторые различия, встречающиеся в других системах UNIX.

В Linux система учета ресурсов является опциональным компонентом ядра, который настраивается посредством параметра CONFIG_BSD_PROCESS_ACCT.

Включение и отключение учета ресурсов

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

#define _BSD_SOURCE

#include

int acct(const char *acctfile);

Возвращает 0 при успешном завершении и –1 при ошибке

Чтобы включить учет ресурсов, аргументу acctfile нужно передать путь к обычному существующему файлу. Типичный путь к учетному файлу имеет вид /var/log/pacct или /usr/account/pacct. Для отключения учета ресурсов аргументу acctfile достаточно передать NULL.

Программа из листинга 28.1 использует вызов acct() для включения и отключения учета ресурсов. По своим возможностям она похожа на консольную команду accton(8).

Листинг 28.1. Включение и выключение учета ресурсов

procexec/acct_on.c

#define _BSD_SOURCE

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

if (argc > 2 || (argc > 1 && strcmp(argv[1], "-help") == 0))

usageErr("%s [file]\n", argv[0]);

if (acct(argv[1]) == –1)

errExit("acct");

printf("Process accounting %s\n",

(argv[1] == NULL)? "disabled": "enabled");

exit(EXIT_SUCCESS);

}

procexec/acct_on.c

Записи в системе учета ресурсов

После включения учета ресурсов данные, записанные в структуру acct, сбрасываются в файл при завершении каждого процесса. Структура acct объявлена в заголовочном файле и имеет следующий вид:

typedef u_int16_t comp_t; /* См. текст */

struct acct {

char ac_flag; /* Флаги учета (см. текст) */

u_int16_t ac_uid; /* Пользовательский идентификатор процесса */

u_int16_t ac_gid; /* Групповой идентификатор процесса */

u_int16_t ac_tty; /* Управляющий терминал процесса (может

равняться 0, если процесс является демоном) */

u_int32_t ac_btime; /* Начальное время (time_t; секунды с начала эры UNIX) */

comp_t ac_utime; /* Пользовательское процессорное время

(такты системного времени) */

comp_t ac_stime; /* Системное процессорное время

(такты системного времени) */

comp_t ac_etime; /* Прошедшее (реальное) время (такты системного времени) */

comp_t ac_mem; /* Среднее потребление памяти (килобайты) */

comp_t ac_io; /* Байты, переданные вызовами read(2) и write(2)

(не используется) */

Перейти на страницу:

Похожие книги