const char *getenv(const char * name);
Единственный параметр getenv()
— это имя переменной окружения, значение которой интересует. Если переменная существует, getenv()
вернет указатель на ее значение. Если переменная не существует в текущем окружении (то есть окружении, на которое указывает environ
), функция вернет NULL
.
Linux предоставляет два способа добавления строк в программное окружение: setenv()
и putenv()
. POSIX определяет только putenv()
, что делает его более переносимым.
int putenv(const char * string);
Переданный функции параметр string
должен иметь форму ИМЯ=ЗНАЧЕНИЕ
. putenv()
добавляет переменную по имени ИМЯ
к текущему окружению и присваивает ей значение ЗНАЧЕНИЕ
. Если окружение уже содержит переменную ИМЯ
, ее значение изменяется на ЗНАЧЕНИЕ
.
BSD определяет функцию setenv()
, которую Linux также поддерживает. Это более гибкий и удобный способ добавления переменных к окружению.
int setenv(const char * name, const char * value, int overwrite);
Здесь имя и новое значение переменной окружения передаются раздельно, что обычно программам делать проще. Если overwrite
равно 0, окружение не модифицируется, если оно уже содержит переменную по имени name
. В противном случае значение переменной модифицируется, как и в putenv()
.
Ниже приведен короткий пример использования обеих функций. Оба вызова делают одно и то же, заменяя переменную окружения PATH
для запущенной программы.
putenv("PATH=/bin:/usr/bin");
setenv("PATH","/bin:/usr/bin", 1);
10.3.2 Использование ресурсов
Ядро Linux отслеживает, сколько ресурсов использует каждый процесс. Хотя отслеживается только небольшое их число, их измерения могут быть полезными разработчикам, администраторам и пользователям. В табл. 10.1 перечислены ресурсы, использование которых отслеживается ядром Linux версии 2.6.7.
Таблица 10.1. Ресурсы процессов, отслеживаемые Linux
Тип | Член | Описание |
---|---|---|
struct timeval |
ru_utime |
Общее время, затраченное на выполнение кода в режиме пользователя. Это включает в себя все время, потраченное на выполнение инструкций приложения, но исключая время, потраченное ядром на обслуживание запросов приложения. |
struct timeval |
ru_stime |
Общее время, потраченное ядром на выполнение запросов процесса. Это не включает времени блокировки процесса в период ожидания выполнения системных вызовов. |
long |
ru_minflt |
Количество второстепенных сбоев (minor faults), вызванных данным процессом. Второстепенные сбои — это попытки доступа к памяти, переключающие процессор в режим ядра, но не вызывающих обращений к диску. Это случается, когда процесс пытается писать за пределами стека, что вынуждает ядро распределить больше пространства стека, прежде чем продолжить выполнение процесса. |
long |
ru_majflt |
Количество первостепенных сбоев (major faults), вызванных данным процессом. Первостепенные сбои — это обращения к памяти, заставляющие ядро обратиться к диску, прежде чем программа сможет продолжить работу. Одной из частых причин этого может быть обращение к части исполняемой памяти, которая еще не была загружена в ОЗУ с диска либо была временно выгружена на диск. |
long |
ru_nswap |
Количество страниц памяти, для которых был выполнен обмен с диском при обращении к памяти из процесса. |
Процесс может проверять использование ресурсов им самим, общее использование ресурсов его дочерними процессами либо сумму того и другого.
Системный вызов getrusage()
возвращает структуру struct rusage
(определенную в <sys/resource.h>
), содержащую информацию о текущем использовании ресурсов.
int getrusage(int who, struct rusage * usage);
Первый параметр, who
, сообщает, какой из трех счетчиков ресурсов должен быть возвращен. RUSAGE_SELF
возвращает использование ресурсов текущим процессом, RUSAGE_CHILDREN
— его дочерними процессами, a RUSAGE_BOTH
— общее использование ресурсов текущим процессом и всеми его дочерними процессами. Второй параметр getrusage()
— это указатель на struct rusage
, куда помещается информация об использовании ресурсов. Хотя struct rusage и содержит относительно немного членов (список унаследован из BSD), большинство этих членов пока не используются Linux). Ниже представлено полное определение этой структуры. В табл. 10.1 описаны члены, используемые в настоящее время Linux.
#include <sys/resource.h>
struct rusage {
struct timeval ru_utime;
struct timeval ru_stime;
long intru_maxrss;
long intru_ixrss;
long intru_idrss;
long intru_isrss;
long intru_minflt;
long intru_majfit;
long intru_nswap;
long intru_inblock;
long intru_oublock;
long intru_msgsnd;
long intru_msgrcv;
long intru_nsignals;
long intru_nvcsw;
long intru_nivcsw;
};
10.3.3. Применение ограничений использования ресурсов
Чтобы помочь в предотвращении неконтролируемого снижения производительности процессами, Unix отслеживает многие ресурсы, которые может использовать процесс, и позволяет системному администратору и самим пользователям накладывать ограничения на расход ресурсов процессами.
Предусмотрены два класса доступных ограничений: жесткие и мягкие ограничения. Жесткие обычно установлены при запуске системы в RLIM_INFINITY
, что означает отсутствие каких-либо ограничений. Единственное исключение из этого — RLIMIT_CORE
(максимальный размер дампа памяти), который Linux инициирует нулем, чтобы предотвратить неожиданный сброс дампов ядра. Многие дистрибутивы сбрасывают этот лимит при запуске, однако, большинство технических пользователей ожидают появления дампов памяти при некоторых условиях (информацию о дампах памяти можно найти далее в главе). Мягкие ограничения — это те ограничения, которые установлены в ядре в данный момент. Любой процесс может наложить мягкое ограничение на использование ресурса на определенном уровне — равном или более низком, чем установленное жесткое ограничение.