2. Реализуйте getopt(). Для первой версии вы можете не беспокоиться насчет случая 'optstring[0] == ':''. Можете также игнорировать opterr.

3. Добавьте код для 'optstring[0] == ':'' и opterr к своей версии getopt().

4. Распечатайте и прочтите файлы GNU getopt.h, getopt.с и getopt1.с.

5. Напишите программу, которая объявляет как environ, так и envp, и сравните их значения.

6. Разбор аргументов командной строки и опций является тем колесом, которое многие люди не могут не изобретать вновь. Вы можете захотеть познакомиться с различными анализирующими аргументы пакетами, помимо getopt() и getopt_long(), такими, как:

 • библиотека анализа аргументов Plan 9 From Bell Labs arg(2)[31],

 • Argp[32],

 • Argv[33],

 • Autoopts[34],

 • GNU Gengetopt[35],

 • Opt[36],

 • Popt[37]. См. также справочную страницу popt(3) системы GNU/Linux.

7. Дополнительный балл, почему компилятор С не может полностью игнорировать ключевое слово register? Подсказка: какие действия невозможно совершать с регистровой переменной?

<p>Глава 3</p><p>Управление памятью на уровне пользователя</p>

Без памяти для хранения данных программа не может выполнить никакую работу (Или, скорее, невозможно выполнить никакую полезную работу.) Реальные программы не могут позволить себе полагаться на буферы и массивы структур данных фиксированного размера. Они должны быть способны обрабатывать вводимые данные различных размеров, от незначительных до больших. Это, в свою очередь, ведет к использованию динамически выделяемой памяти — памяти, выделяемой в ходе исполнения, а не при компиляции. Вот как вводится в действие принцип GNU «никаких произвольных ограничений».

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

<p>3.1. Адресное пространство Linux/Unix</p>

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

Код

Часто называемая сегментом текста область, в которой находятся исполняемые инструкции. Linux и Unix организуют вещи таким образом, что несколько запушенных экземпляров одной программы по возможности разделяют свой код; в любое время в памяти находится лишь одна копия инструкций одной и той же программы (Это прозрачно для работающих программ.) Часть исполняемого файла, содержащая сегмент текста, называется секцией текста.

Инициализированные данные

Статически выделенные и глобальные данные, которые инициализированы ненулевыми значениями, находятся в сегменте данных. У каждого процесса с одной и той же запущенной программой свой собственный сегмент данных. Часть исполняемого файла, содержащая сегмент данных, является секцией данных.

Инициализированные нулями данные[38]

Глобальные и статически выделенные данные, которые по умолчанию инициализированы нулями, хранятся в области процесса, который называют областью BSS[39]. У каждого процесса, в котором запущена одна и та же программа, своя область BSS. При запуске данные BSS помещаются в сегмент данных. В исполняемом файле они хранятся в секции BSS.

Формат исполняемого файла Linux/Unix таков, что пространство исполняемого файла на диске занимают лишь переменные, инициализированные ненулевыми значениями. Поэтому большой массив, объявленный как 'static char somebuf[2048];', который автоматически заполняется нулями, не занимает 2 Кб пространства на диске. (Некоторые компиляторы имеют опции, позволяющие вам помещать инициализированные нулями данные в сегмент данных.)

Куча (heap)

Куча является местом, откуда выделяется динамическая память (получаемая с помощью функции malloc() и подобными ей). Когда из кучи выделяется память, адресное пространство процесса растет, что вы можете заметить, отслеживая запущенный процесс с помощью команды ps.

Хотя память можно вернуть обратно системе и сократить адресное пространство процесса, этого почти никогда не происходит. (Мы различаем освобождение больше не использующейся динамической памяти и сокращение адресного пространства; подробнее это обсуждается далее в этой главе.)

Перейти на страницу:

Похожие книги