
- •Часть 3. Подсистема управления процессами
- •Глава 7. Среда окружения процесса 2
- •Глава 8. Управление процессами 16
- •Глава 9. Взаимоотношения между процессами 49
- •Глава 10. Сигналы 62
- •Глава 11. Процессы-демоны 98
- •Глава 7. Среда окружения процесса
- •7.1. Введение
- •7.2. Функция main
- •7.3. Завершение работы процесса
- •7.3.1. Функции семейства exit
- •7.3.2. Функция atexit
- •7.4. Аргументы командной строки
- •7.5. Раскладка памяти программы на языке c
- •7.6. Разделяемые библиотеки
- •7.7. Распределение памяти
- •7.8. Список переменных окружения
- •7.9. Функции getrlimit и setrlimit
- •7.10. Выводы по главе 7
- •7.11. Упражнения по главе 7
- •Глава 8. Управление процессами
- •8.1. Введение
- •8.2. Идентификаторы процесса
- •8.3. Функция fork
- •8.4. Совместное использование файлов
- •8.5. Функция exit
- •8.6. Функции wait и waitpid
- •8.7. Гонка за ресурсами
- •8.8. Функция exec
- •8.9. Изменение идентификаторов пользователя и группы
- •8.9.1. Функции setreuid и setregid
- •8.9.2. Функции seteuid и setegid
- •8.9.3. Идентификаторы группы
- •8.10. Интерпретируемые файлы
- •8.11. Функция system
- •8.12. Идентификация пользователя
- •8.13. Временные характеристики процесса
- •8.14. Выводы по главе 8
- •8.15. Упражнения по главе 8
- •Глава 9. Взаимоотношения между процессами
- •9.1. Введение
- •9.2. Вход с терминала
- •9.2.1. Вход в систему с терминала в bsd-системах
- •9.2.2. Вход в систему с терминала в Linux
- •9.3. Вход в систему через сетевое соединение
- •9.3.1. Вход в систему через сетевое соединение в bsd-системах
- •9.3.2. Вход в систему через сетевое соединение в Linux
- •9.4. Группы процессов
- •9.5. Сессии
- •9.6. Управляющий терминал
- •9.7. Функции tcgetpgrp, tcsetpgrp и tcgetsid
- •9.8. Выводы по главе 9
- •9.9. Упражнения по главе 9
- •Глава 10. Сигналы
- •10.1. Введение
- •10.2. Концепция сигналов
- •10.3. Функция signal
- •10.3.1. Запуск программы
- •10.3.2. Создание процесса
- •10.4. Ненадежные сигналы
- •10.5. Прерванные системные вызовы
- •10.6. Реентерабельные функции
- •10.7. Надежные сигналы. Терминология и семантика
- •10.8. Функции kill и raise
- •10.9. Функции alarm и pause
- •10.10. Наборы сигналов
- •10.11. Функция sigprocmask
- •10.12. Функция sigpending
- •10.13. Функция sigaction
- •10.14. Функция sigsuspend
- •10.15. Функция abort
- •10.16. Функция system
- •10.17. Функция sleep
- •10.18. Дополнительные возможности
- •10.19. Выводы по главе 10
- •10.20. Упражнения по главе 10
- •Глава 11. Процессы-демоны
- •11.1. Введение
- •11.2. Характеристики демонов
- •11.3. Правила программирования демонов
- •11.4. Журналирование ошибок
- •11.5. Демоны в единственном экземпляре
- •11.6. Соглашения для демонов
- •11.7. Модель клиент-сервер
- •11.8. Выводы по главе 11
- •11.9. Упражнения по главе 11
7.8. Список переменных окружения
Каждой программе, помимо аргументов командной строки, передается также список переменных окружения. Подобно списку аргументов командной строки, список переменных окружения представляет собой массив указателей, каждый из которых указывает на строку символов, завершающуюся нулевым символом. Адрес массива указателей хранится в глобальной переменной environ:
extern char **environ;
Например, среда окружения, которая насчитывает пять переменных, будет похожа на то, что изображено на рис. 7.2. Здесь явно показаны нулевые символы, которыми завершаются строки. Переменная environ отмечена как указатель на среду окружения, массив указателей – как список переменных среды окружения, а строки, на которые они указывают, как строки окружения.
рис. 7.2
В соответствии с принятыми соглашениями окружение состоит из строк следующего формата (рис. 7.2): name=value. Большинство предопределенных имен состоят из символов верхнего регистра, но это всего лишь традиция.
Ядро Unix никогда не обращается к этим строкам; их интерпретация полностью зависит от самих приложений. Так, например, командные оболочки широко используют в своей работе многочисленные переменные окружения. Некоторые из них, такие как HOME и LOGNAME, устанавливаются автоматически при входе в систему, другие определяются пользователем. Обычно инициализация переменных окружения производится в файле начального запуска командной оболочки. В частности, переменная среды MAIL сообщает командной оболочке имя файла, в котором хранится электронная почта пользователя.
Исторически в большинстве версий Unix функция main имеет третий аргумент, который является указателем на среду окружения:
int main (int argc, char *argv[], char *envp[]);
Стандарт ISO C определяет только два аргумента функции main, а передача среды окружения через третий аргумент не имеет никаких преимуществ перед передачей той же информации через глобальную переменную environ. Поэтому стандарт Posix.1 указывает, что передача среды окружения должна осуществляться не через третий аргумент функции main, а через глобальную переменную environ (если это возможно). Доступ к конкретным переменным окружения обычно осуществляется с помощью функций getenv и putenv, которые будут описаны в разделе 7.9, а не через глобальную переменную environ. Однако для просмотра всех переменных окружения следует использовать указатель environ.
Стандарт ISO C не определяет никаких переменных окружения, но предоставляет функцию, с помощью которой можно получить значение любой переменной окружения, оговаривая, что содержимое среды окружения зависит от реализации.
#include <stdlib.h>
char *getenv (const char *name);
/* возвращает указатель на значение переменной с именем name или NULL, если переменная не найдена */
Обратите внимание, что эта функция возвращает указатель на подстроку value в строке name=value. Когда нужно получить значение конкретной переменной окружения, следует всегда использовать функцию getenv вместо прямого обращения к массиву environ.
Иногда может потребоваться не только получить, но и изменить значение существующей переменной или даже добавить новую переменную. В следующей главе мы рассмотрим, как можно оказывать влияние на среду окружения текущего и любых порожденных им процессов. Мы не можем изменить среду окружения родительского процесса, однако можем при необходимости изменять среду окружения текущего процесса. ОС Linux предоставляет следующие три функции:
#include <stdlib.h>
int putenv (char *str);
int setenv (const char *name, const char *value, int rewrite);
/* эти две функции возвращают 0 в случае успеха, ненулевое значение – в случае ошибки */
void unsetenv (char *name);
Работают эти функции следующим образом:
функция putenv принимает строку в формате name=value и помещает ее в список переменных окружения. Если переменная с именем name уже существует, то она будет удалена перед вставкой новой строки;
функция setenv присваивает переменной с именем name значение value. Если переменная с именем name уже существует в среде окружения, тогда: а) если аргумент rewrite не равен нулю, то существующее значение переменной заменяется новым; б) если аргумент rewrite равен нулю, то значение переменной не изменяется и функция возвращает управление без признака ошибки;
функция unsetenv удаляет определение переменной с именем name. Если заданной переменной не существует, то это не считается ошибкой.