Раньше мы познакомились с тем, как получать параметры в программе с помощью семейства функций getopt (подробнее читайте "Шаг 10 - Передача опций в программу - getopt" и "Шаг 11 - Передача длинных опций в программу - getopt_long"). Но существует еще один метод - переменные окружения или переменные среды. С ними мы успели уже познакомиться раньше в шаге "Шаг 13 - Получение информации о пользователе". С помощью данных переменных можно передавать в программу дополнительные специфические параметры, которые могут использоваться несколькими программами одновременно и они характеризуют "среду", в которой выполняется программа.
Например, если Вы разрабатываете какую-то систему состоящую из нескольких программ работающих независимо, то к примеру, Вы захотите сообщить всем программам рабочий каталог, временную директорию или какой-нибудь другой специфичный параметр. Тогда переменные окружения, это единственный разумный метод, ведь передавать такие параметры через командную строку глупо. Почему ?! Ну, например, приведу скрипт запуска какой-нибудь сложной системы:
#!/bin/bash /yoyosystem/cheduler --time=60 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem /yoyosystem/counter -c 25 -w 31 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem /yoyosystem/pusher --stack-size=512 -m 12 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem
Ну, как ?! Громодко ! А вот как более красиво:
#!/bin/bash export YOYO_WORK_DIR="/yoyosystem/data" export YOYO_TEMP_DIR="/tmp/yoyosystem" /yoyosystem/cheduler --time=60 /yoyosystem/counter -c 25 -w 31 /yoyosystem/pusher --stack-size=512 -m 12
Каждая из указанных программ будет брать параметры об используемых директориях из переменных среды YOYO_WORK_DIR и YOYO_TEMP_DIR, что значительно упрощает написание и модификацию скрипта запуска системы, а также убережет от опечаток и связанных с этим ошибок. Поэтому переменные среды достаточно важны и Вы всегда должны помнить об их удобстве.
А теперь собственно давайте познакомимся с этими переменными среды. Библиотека glibc предоставляет весь спектр функций для работы с ними в заголовочном файле stdlib.h.
Сначала познакомимся с самим массивом переменных окружения, который определен в заголовочном файле unistd.h в таком виде:
/* NULL-terminated array of "NAME=VALUE" environment variables. */ extern char **__environ; #ifdef __USE_GNU extern char **environ; #endif
Представлет собой массив указателей на строки формата "имя=значение" и заканчивается нулевым указателем NULL. Давайте попробуем написать программу вывода всех переменных:
#include <stdlib.h> #include <unistd.h> int main(int argc,char **argv) { int i=0; while (__environ[i] != NULL) { printf("%s\n",__environ[i]); i++; }; return 0; };
Данная программа выведет весь список переменных среды окружения, которые доступны программе:
root@darkstar:/@@@@@@# ./a.out MANPATH=/usr/local/man:/usr/man:/usr/X11R6/man:/usr/lib/java/man HOSTNAME=darkstar.example.net SHELL=/bin/bash TERM=xterm USER=root MC_TMPDIR=/tmp/mc-root T1LIB_CONFIG=/usr/share/t1lib/t1lib.config MINICOM=-c on PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin: MAIL=/var/mail/root LC_COLLATE=C PWD=/@@@@@@ INPUTRC=/etc/inputrc JAVA_HOME=/usr/lib/java LANG=en_US PS1=\u@\h:\w\$ HISTCONTROL=ignorespace PS2=> HOME=/root SHLVL=2 LOGNAME=root LESS=-M LESSOPEN=|lesspipe.sh %s OLDPWD=/usr/include _=./a.out
Я конечно вырезал некоторые переменные, которые слишком большие, но все равно достаточно информативно и можно считать, что программа знает о среде в которой запущена практически все.
Для доступа к переменным окружения, есть несколько функций:
Используя набор данных функций вы можете полностью управлять переменными среды, которые доступны вашей программе.
#include <stdlib.h> int main(int argc,char **argv) { char *HOME = getenv("HOME"); char *USER = getenv("USER"); printf("Home directory: \"%s\"\n",HOME); printf("User name: \"%s\"\n",USER); return 0; };
При вызове данной программы вы узнаете свой домашний каталог и имя пользователя. Например:
root@darkstar:/@@@@@@# ./a.out Home directory: "/root" User name: "root"
Использование переменных окружения полезно не только, когда Вам требуется настроить в нескольких программах какие-то параметры, но и для обмена данными между процессами. То есть в одной программе Вы создаете переменную, а в другой получаете значение этой переменной. Таким образом можно наладить обмен простыми короткими данными между процессами. Но, конечно, все-таки не стоит сильно злоупотреблять этой возможностью :)