- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Операционная система UNIX - Андрей Робачевский
Шрифт:
Интервал:
Закладка:
Функция, которая потребуется для нашего примера, позволяет получить запись файла паролей по имени пользователя. Она имеет следующий вид:
#include <pwd.h>
struct passwd *getpwnam(const char *name);
Итак, перейдем к фрагменту программы:
...
struct passwd *pw;
char logname[MAXNAME];
/* Массив аргументов при запуске
командного интерпретатора */
char *arg[MAXARG];
/* Окружение командного интерпретатора */
char *envir[MAXENV];
...
/* Проведем поиск записи пользователя с именем logname,
которое было введено на приглашение "login:" */
pw = getpwnam(logname);
/* Если пользователь с таким именем не найден, повторить
приглашение */
if (pw == 0)
retry();
/* В противном случае установим идентификаторы процесса
равными значениям, полученным из файла паролей и запустим
командный интерпретатор */
else {
setuid(pw->pw_uid);
setgid(pw->pw_gid);
execve(pw->pw_shell, arg, envir);
}
...
Вызов execve(2) запускает на выполнение программу, указанную в первом аргументе. Мы рассмотрим эту функцию в разделе "Создание и управление процессами" далее в этой главе.
Выделение памяти
При обсуждении формата исполняемых файлов и образа программы в памяти мы отметили, что сегменты данных и стека могут изменять свои размеры. Если для стека операцию выделения памяти операционная система производит автоматически, то приложение имеет возможность управлять ростом сегмента данных, выделяя дополнительную память из хипа (heap — куча). Рассмотрим этот программный интерфейс.
Память, которая используется сегментами данных и стека, может быть выделена несколькими различными способами как во время создания процесса, так и динамически во время его выполнения. Существует четыре способа выделения памяти:
1. Переменная объявлена как глобальная, и ей присвоено начальное значение в исходном тексте программы, например:
char ptype = "Unknown file type";
Строка ptype размещается в сегменте инициализированных данных исполняемого файла, и для нее выделяется соответствующая память при создании процесса.
2. Значение глобальной переменной неизвестно на этапе компиляции, например:
char ptype[32];
В этом случае место в исполняемом файле для ptype не резервируется, но при создании процесса для данной переменной выделяется необходимое количество памяти, заполненной нулями, в сегменте BSS.
3. Переменные автоматического класса хранения, используемые в функциях программы, используют стек. Память для них выделяется при вызове функции и освобождается при возврате. Например:
func1() {
int a;
char *b;
static int с = 4;
...
}
В данном примере переменные а и b размещаются в сегменте стека. Переменная с размешается в сегменте инициализированных данных и загружается из исполняемого файла либо во время создания процесса, либо в процессе загрузки страниц по требованию. Более подробно страничный механизм описан в главе 3.
4. Выделение памяти явно запрашивается некоторыми системными вызовами или библиотечными функциями. Например, функция malloc(3C) запрашивает выделение дополнительной памяти, которая в дальнейшем используется для динамического размещения данных. Функция ctime(3C), предоставляющая системное время в удобном формате, также требует выделения памяти для размещения строки, содержащей значения текущего времени, указатель на которую возвращается программе.
Напомним, что дополнительная память выделяется из хипа (heap) — области виртуальной памяти, расположенной рядом с сегментом данных, размер которой меняется для удовлетворения запросов на размещение. Следующий за сегментом данных адрес называется разделительным или брейк-адресом (break address). Изменение размера сегмента данных по существу заключается в изменении брейк-адреса. Для изменения его значения UNIX предоставляет процессу два системных вызова — brk(2) и sbrk(2).
#include <unistd.h>
int brk(void *endds);
void *sbrk(int incr);
Системный вызов brk(2) позволяет установить значение брейк-адреса равным endds и, в зависимости от его значения, выделяет или освобождает память (рис. 2.11). Функция sbrk(2) изменяет значение брейк-адреса на величину incr. Если значение incr больше 0, происходит выделение памяти, в противном случае, память освобождается.[23]
Рис 2.11. Динамическое выделение памяти с помощью brk(2)
Существуют четыре стандартные библиотечные функции, предназначенные для динамического выделения/освобождения памяти.
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nelem, size_t elsize);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
Функция malloc(3C) выделяет указанное аргументом size число байтов.
Функция calloc(3C) выделяет память для указанного аргументом nelem числа объектов, размер которых elsize. Выделенная память инициализируется нулями.
Функция realloc(3C) изменяет размер предварительно выделенной области памяти (увеличивает или уменьшает, в зависимости от знака аргумента size). Увеличение размера может привести к перемещению всей области в другое место виртуальной памяти, где имеется необходимое свободное непрерывное виртуальное адресное пространство.
Функция free(3C) освобождает память, предварительно выделенную с помощью функций malloc(3C), calloc(3C) или realloc(3C), указатель на которую передается через аргумент ptr.
Указатель, возвращаемый функциями malloc(3C), calloc(3C) и realloc(3C), соответствующим образом выровнен, таким образом выделенная память пригодна для хранения объектов любых типов. Например, если наиболее жестким требованием по выравниванию в системе является размещение переменных типа double по адресам, кратным 8, то это требование будет распространено на все указатели, возвращаемыми этими функциями.
Упомянутые библиотечные функции обычно используют системные вызовы sbrk(2) или brk(2). Хотя эти системные вызовы позволяют как выделять, так и освобождать память, в случае библиотечных функций память реально не освобождается, даже при вызове free(3C). Правда, с помощью функций malloc(3C), calloc(3C) или realloc(3C) можно снова выделить и использовать эту память и снова освободить ее, но она не передается обратно ядру, а остается в пуле malloc(3C).
Для иллюстрации этого положения приведем небольшую программу, выделяющую и освобождающую память с помощью функций malloc(3C) и free(3C), соответственно. Контроль действительного значения брейк-адреса осуществляется с помощью системного вызова sbrk(2):
#include <unistd.h>
#include <stdlib.h>
main() {
char *obrk;
char *nbrk;
char *naddr;
/* Определим текущий брейк-адрес */
obrk = sbrk(0);
printf("Текущий брейк-адрес= 0x%xn", obrk);
/* Выделим 64 байта из хипа */
naddr = malloc(64);
/* Определим новый брейк-адрес */
nbrk = sbrk(0);
printf("Новый адрес области malloc= 0x%x,"
" брейк-адрес= 0х%x (увеличение на %d байтов)n",
naddr, nbrk, nbrk — obrk);
/* "Освободим" выделенную память и проверим, что произошло
на самом деле */
free(naddr);
printf("free(0x%x)n", naddr);
obrk = sbrk(0);
printf("Новый брейк-адрес= 0x%x (увеличение на %d байтов)n",
obrk, obrk — nbrk);
}
Откомпилируем и запустим программу:
$ a.out
Текущий брейк-адрес= 0x20ac0
malloc(64)
Новый адрес области malloc = 0x20ac8, брейк-адрес = 0x22ac0
(увеличение на 8192 байтов)
free(0x20ac8)
Новый брейк-адрес = 0x22ac0 (увеличение на 0 байтов)
$
Как видно из вывода программы, несмотря на освобождение памяти функцией free(3C), значение брейк-адреса не изменилось. Также можно заметить, что функция malloc(3C) выделяет больше памяти, чем требуется. Дополнительная память выделяется для необходимого выравнивания и для хранения внутренних данных malloc(3C), таких как размер области, указатель на следующую область и т.п.

