Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций 2009.doc
Скачиваний:
40
Добавлен:
13.11.2019
Размер:
2.3 Mб
Скачать

3.7Организация процессов и потоков в Linux

3.7.1Среда окружения в Linux

Любая UNIX-программа получает в свое распоряжение глобальную переменную environ. Она указывает на массив с переменными окружения, который также завершается пустым указателем (переменной, в которой хранилось бы количество элементов массива, не предусмотрено):

extern char **environ; /* массив переменных среды окружения */

/* (нет ни в одном из заголовочных файлов) */

Строки в массиве аргументов могут содержать любую комбинацию символов, но каждая строка обязательно завершается символом «\0». Строки с переменными окружения имеют более строгую форму. Каждая из них записывается в виде: «имя= значение», и также завершается символом «\0». Само собой разумеется, имя переменной окружения не может содержать символ «=».

Самый простой способ получения и изменения значений этого массива — обратиться к массиву environ напрямую:

extern char **environ;

int main(void) {

int i;

for (i = 0; environ[i] != NULL; i++)

printf("%s\n", environ[i]);

exit(EXIT_SUCCESS);

}

В ОС Solaris данный код вернёт следующий результат:

H0ME=/home/marc

HZ=100

LC_COLLATE=en_US.IS08859-1

LC_CTYPE=en_US.IS0BB59-1

LC_MESSAGES=C

LC_MONETARY=en_US.IS08859-1

LOGNAME=marc

MAIL=/va r/mail/marc

В целях экономии места приведен не весь список переменных. Как правило, в программах и не требуется просматривать весь список, чаще всего необходимо получить значение какой-нибудь определенной переменной. Для этой цели используется стандартная функция getenv:

#include <stdlib.h>

char *getenv

(

const char* var /* имя переменной */

);

/* Возвращает значение переменней или NULL, если таковая не найдена (значение переменней errno не определено) */

Функция getenv возвращает часть строки, которая стоит после символа «=», например, программа:

int main(void) ,

{

char *s;

s = getenv("LOGNAME");

if (s == NULL)

{

printf("переменная не найдена\п");

}

else

{

printf("значение переменней: \"Xs\"\n", s);

}

exit(EXIT_SUCCESS);

}

Данный код возвращает значение текущего имени пользователя.

Изменить значение переменной окружения не так просто, как прочитать. Хотя этот массив и является исключительной собственностью приложения и может изменяться без каких-либо ограничений, тем не менее, нет никаких гарантий, что в нем предусмотрено дополнительное место под новые строки или что в строку можно записать более длинное значение переменной. Таким образом, изменение среды окружения есть задача нетривиальная — необходимо полностью пересоздать массив строк. После этого можно будет изменить указатель environ, записав туда адрес нового массива. Измененная версия среды окружения может быть передана новым программам, запускаемым из данного приложения, к ней же будут обращаться и все последующие вызовы getenv. Изменения не коснутся других приложений, включая командный интерпретатор, который запустил процесс, выполнивший модификацию. Таким образом, если вы хотите изменить переменные окружения командной оболочки, нужно делать это с помощью самой командной оболочки.

Вместо того, чтобы работать с массивом environ напрямую, можно воспользоваться стандартными функциями putenv, setenv, unsetenv.

#include <stdlib.h>

int putenv(

char *string /* стрска e виде «имя=значение» */

);

/* Возвращает 0 в случае успеха, ненулевое значение – в случае ошибки (код ошибки - в переменной еrrпo) */

#include <stdlib.h>

int setenv(

const char *var, /* переменная, кoтoрая дoбавляется или изменяется */

const char *val, /* значение */

int overwrite /* затереть старее значение? */

);

/* Вoзвращает 0 в случае успеха, -1 в случае ошибки (код сшибки - в переменной еrrпo) */

#include <stdlib.h>

int unsetenv(

const char *var /* удаляемая переменная */

);

/* Возвращает 0 в случае успеха, -1 в случае ошибки (код сшибки – в переменной errno) */

Функции putenv и setenv изменяют илм добавляют переменные окружения, unsetenv – удаляет переменную среды окружения.

Все эти функции вносят изменения в массив, который хранит переменные среды окружения и, возможно, изменяют сам указатель environ, если в массиве обнаружится нехватка места. Если вы самостоятельно изменяете указатель environ или какую-либо часть массиве, на который он указывает, то поведение этих функций может быть непредсказуемым. Поэтому выбирайте всегда что-то одно — или вы пользуетесь стандартными функциями, или взаимодействуете со средой окружения самостоятельно, но никогда не смешивайте эти два способа.

Функция putenv принимает строку в виде «имя=значение» и вставляет в массив environ указатель на нее, в результате строка становится частью среды окружения. По этой причине никогда не передавайте функции данные с автоматическим классом размещения (локальные и нестатические переменные) и не изменяйте их содержимое после вызова putenv.

Функция setenv более сложная. Она копирует имя переменной и ее значение в специально отведенное для этого место. Если переменная уже существует, ее значение будет изменено при условии, что аргумент overwrite не равен нулю, в противном случае «старое» значение останется без изменений. Если переменной не существует, она будет добавлена в среду окружения, в этом случае значение аргумента overwrite игнорируется.

Функция unsetenv является парной к setenv. Она удаляет переменную среды окружения. Если ваша система не поддерживает функцию unsetenv, то самый лучший способ «удалить» переменную — присвоить ей в виде значения пустую строку. В некоторых случаях это может оказаться неприемлемым, но это уже зависит от самого приложения. (Некоторые системы, такие как Linux, FreeBSD и Darwin определяют unsetenv как void и в этих системах она не имеет возвращаемого значения.)

Несмотря на то, что эти функции стандартизованы, их наличие в системе не является обязательным. Операционные системы FreeBSD, Linux и Solaris имеют функцию putenv, а первые две — все три функции. Спецификация SUS3 требует наличия в системе функций setenv и unsetenv, но не все системы следуют ей. Таким образом, самый простой способ определить наличие этих функций следующий: setenv и unsetenv пришли из мира BSD, поэтому все производные системы, включая FreeBSD, поддерживают их. Функция putenv пришла из System V и должна присутствовать во всех системах, производных от System V, включая Solaris. Поскольку SUS3 рекомендует поддержку функций setenv и putenv, лучшим выходом будет все-таки использовать их, а для систем, которые не поддерживают setenv и putenv — включать в приложения собственные версии этих функций.