- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Операционная система UNIX - Андрей Робачевский
Шрифт:
Интервал:
Закладка:
extern char *environ;
Рекомендуется следовать последнему формату передачи для лучшей переносимости программ на другие платформы UNIX.
Рис. 2.6. Передача переменных окружения
Приведем пример программы, соответствующую стандарту POSIX.1, которая выводит значения всех аргументов, переданных функции main(): число переданных параметров, сами параметры и значения первых десяти переменных окружения.
#include <stddef.h>
extern char **environ;
main(int argc, char *argv[]) {
int i;
printf("число параметров, переданных программе %s равно %dn",
argv[0], argc-1);
for (i=1; i<argc; i++)
if (environ[i] != NULL)
printf("environ[%d] : %sn", i, environ[i]);
}
В результате компиляции будет создан исполняемый файл программы (по умолчанию a.out). Запустив его, мы увидим следующую информацию:
$ a.out first second 3
число параметров, переданных программе a.out равно 3
argv[1] = first
argv[2] = second
argv[3] = 3
environ[0] : LOGNAME=andy
environ[1] : MAIL=/var/mail/andy
environ[2] : LD_LIBRARY_PATH=/usr/openwin/lib:/usr/ucblib
environ[3] : PAGER=/usr/bin/pg
environ[4] : TERM=vt100
environ[5] : PATH=/usr/bin:/bin:/etc:/usr/sbin:/sbin:/usr/ccs/bin:/usr/local/bin
environ[6] : HOME=/home/andy
environ[7] : SHELL=/usr/local/bin/bash
Максимальный объем памяти для хранения параметров и переменных окружения программы ограничен величиной ARG_MAX, определенной в файле <limits.h>. Это и другие системные ограничения могут быть получены с помощью функции sysconf(2).
Для получения и установки значений конкретных переменных окружения используются две функции: getenv(3C) и putenv(3C):
#include <stdlib.h>
char *getenv(const char *name);
возвращает значение переменной окружения name, a
int putenv(const char *string);
помещает переменную и ее значение (var_name=var_value) в окружение программы.
В качестве примера приведем программу, похожую по своей функциональности на предыдущую, которая выборочно выводит значения переменных и устанавливает новые значения по желанию пользователя.
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
main(int argc, char *argv[]) {
char *term;
char buf[200], var[200];
/* Проверим, определена ли переменная TERM */
if ((term = getenv("TERM")) == NULL)
/* Если переменная не определена, получим от пользователя ее значение и
поместим переменную в окружение программы */
{
printf("переменная TERM не определена, введите значение: ");
putenv(var);
} else
/* Если переменная TERM определена, предоставим пользователю возможность
изменить ее значение, после чего поместим ее в окружение процесса */
{
printf("TERM=%s. Change? [N]", getenv("TERM"));
gets(buf);
if (buf[0] == 'Y' || buf[0] == 'y') {
printf("TERM=");
gets{buf);
sprintf(var, "TERM=%s", buf);
putenv(var);
printf("new %sn", var);
}
}
}
Сначала программа проверяет, определена ли переменная TERM. Если переменная TERM не определена, пользователю предлагается ввести ее значение. Если же переменная TERM определена, пользователю предлагается изменить ее значение, после чего новое значение помещается в окружение программы.
Запуск этой программы приведет к следующим результатам:
$ а.out
TERM=ansi. Change? [N]y
TERM=vt100
new TERM=vt100
$
К сожалению, введенное значение переменной будет действительно только для данного процесса и порожденных им процессов: если после завершения программы a.out вывести значение TERM, то видно, что оно не изменилось:
$ echo $TERM
ansi
$
Наследование окружения программы мы обсудим в разделе "Создание и управление процессами" далее в этой главе.
Переменные окружения, как и параметры, позволяют передавать программе некоторую информацию. Однако если программа является интерактивной, основную информацию она, скорее всего, будет получать непосредственно от пользователя. В связи с этим встает вопрос: каким образом программа узнает, где находится пользователь, чтобы правильно считывать и выводить информацию? Другими словами, программе необходимо знать, с каким терминальным устройством работает пользователь, запустивший ее.
Обычно при запуске программы на выполнение из командной строки shell автоматически устанавливает для нее три стандартных потока ввода/вывода: для ввода данных, для вывода информации и для вывода сообщений об ошибках. Начальную ассоциацию этих потоков (их файловых дескрипторов) с конкретными устройствами производит терминальный сервер (в большинстве систем это процесс getty(1M)), который открывает специальный файл устройства, связанный с терминалом пользователя, и получает соответствующие дескрипторы. Эти потоки наследует командный интерпретатор shell и передает их запускаемой программе. При этом shell может изменить стандартные направления (по умолчанию все три потока связаны с терминалом пользователя), если пользователь указал на это с помощью специальных директив перенаправления потока (>, <, >>, <<) см. главу 1, раздел "Пользовательская среда UNIX"). Раздел "Группы и сеансы" внесет окончательную ясность в этот вопрос при описании управляющего терминала.
Такой механизм позволяет программисту не задумываться о местонахождении пользователя, и в то же время обеспечить получение и передачу данных именно запустившему данную программу пользователю.
Завершая разговор о запуске программ, заметим, что при компиляции программы редактор связей устанавливает точку входа в программу, указывающую на библиотечную функцию _start(). Эта функция инициализирует процесс, создавая кадр стека, устанавливая значения переменных и, в конечном итоге, вызывая функцию main().
Завершение C-программы
Существует несколько способов завершения программы. Основными являются возврат из функции main()[17] и вызов функций exit(2), оба приводят к завершению выполнения задачи. Заметим, что процесс может завершиться по не зависящим от него обстоятельствам, например, при получении сигнала, действие по умолчанию для большинства из которых приводит к завершению выполнения процесса[18] (см. раздел "Сигналы" далее в этой главе). В этом случае функция exit(2) будет вызвана ядром от имени процесса.
Системный вызов exit(2) выглядит следующим образом:
#include <unistd.h>
void exit(int status);
Аргумент status, передаваемый функции exit(2), возвращается родительскому процессу и представляет собой код возврата программы. По соглашению программа возвращает 0 в случае успеха и другую величину в случае неудачи. Значение кода неудачи может иметь дополнительную трактовку, определяемую самой программой. Например, программа grep(1), выполняющая поиск заданных подстрок в файлах, определяет следующие коды возврата:
0 совпадение было найдено 1 совпадений найдено не было 2 синтаксическая ошибка или недоступны файлы поискаНаличие кода возврата позволяет программам взаимодействовать друг с другом. Например, следующая программа (назовем ее fail) может являться условием неудачи и использоваться в соответствующих синтаксических конструкциях shell:
main() {
exit(1);
}
$ fail
$ echo $? Выведем код возврата программы fail
1
$ fail || echo fail Конструкция shell, использующая условие неудачи fail
fail
Помимо передачи кода возврата, функция exit(2) производит ряд действий, в частности выводит буферизованные данные и закрывает потоки ввода/вывода. Альтернативой ей является функция _exit(2), которая не производит вызовов библиотеки ввода/вывода, а сразу вызывает системную функцию завершения ядра. Более подробно о процедурах завершения процесса см. раздел "Создание и управление процессами".
Задача может зарегистрировать обработчики выхода (exit handler), — функции, которые вызываются после вызова exit(2), но до окончательного завершения процесса. Эти обработчики, вызываемые по принципу LIFO (последний зарегистрированный обработчик будет вызван первым), запускаются только при "добровольном" завершении процесса. Например, при получении процессом сигнала обработчики выхода вызываться не будут. Для обработки таких ситуаций следует использовать специальные функции — обработчики сигналов (см. раздел "Сигналы" далее в этой главе).

