Введение в UNIX
Дегтярев Е.К.
Оглавление
11. Средства разработки программ
Система UNIX обеспечивает богатый набор средств для раз-
работки программ, включающий компиляторы, линкер, символьный
отладчик, средства ведения программных проектов и разработки
языковых процессоров, архивные средства и другие.
В начало страницы
В системе UNIX имеются компиляторы с языков C, ФОРТРАН-77
и ПАСКАЛЬ и другие. Команды вызова компилятора имеют вид cc,
f77 или fc, pc и т.п.
Параметрами этих команд являются файлы с текстами прог-
рамм на исходных языках, имена которых должны оканчиваться
на .c, .f, .p и т.п. соответственно.
Примеры:
$ cc program.c
$ fc test.f
$ pc example.p
Результатом работы компилятора является файл исполняемого
кода, имеющий по умолчанию имя a.out. Если вы хотите другое
имя, его можно указать явно ключом -o <имя> при вызове ком-
пилятора.
Пример:
$ fc -o test test.f
$ ls
test
test.f
$
В начало страницы
На практике программы создаются из множества раздельно
транслируемых модулей, каждый из которых занимает отдельный
файл. Результатом компиляции каждого модуля является файл
объектного (перемещяемого) кода, имя которого получается за-
меной .c (или .f, .p и т.д.) на .c. Затем все объектные фай-
лы объединяются в единую программу, помещаемую в файл испол-
няемого кода, посредством линкера. Линкер может вызываться
как независимой командой ld, так и автоматически при выпол-
нении команд вызова компилятора cc, fc, pc и т.д. В послед-
нем случае эти команды могут иметь несколько параметров-фай-
лов, имена которых могут оканчиваться не только на .c, .f,
.p, ..., но и на .o. Файлы исходного текста компилируются, а
затем все файлы объектного кода, как полученные в результате
компиляции, так и параметры команды вызова компилятора, пе-
редаются линкеру. Результатом по-прежнему является файл с
именем по умолчанию a.out, если вы не указали явно другое
имя.
При этом, как правило, объектные файлы уничтожаются. Что-
бы сохранить их, можно подавить автоматический вызов линкера
ключом -c (только компиляция) в команде вызова компилятора.
Пример:
$ fc -c test.f check prove.f
$ ld /lib/frt0.o *.o -lF77
$ ls
a.out
check.f
check.o
prove.f
prove.o
test.f
test.o
$
Здесь добавлены файл /lib/frt0.o стартового модуля для
программы на ФОРТРАНе (для C /lib/crt0.o) и библиотека -
lF77 подпрограмм для ФОРТРАНа (для C - lc); могут быть до-
бавлены и другие библиотеки. Обозначение -lx является сокра-
щением для /lib/libx.a для любого x. Следует заметить, что
библиотеки указываются последними (не являются ключами ко-
манды ld). При автоматическом вызове линкера стартовый мо-
дуль и ряд библиотек вызываются по умолчанию. Чтобы их уви-
деть, следует применить ключ -v в командах вызова компилято-
ра.
В начало страницы
Как мы показали выше, на вход линкера могут подаваться не
только файлы объектного кода, но и библиотечные файлы, кото-
рые оказываются очень удобным средством хранения объектных
модулей, если их становится очень много.
Имя библиотечного файла обычно оканчивается на .a. Имеет-
ся команда ar (архив) для создания, пополнения и просмотра
библиотечных файлов.
Пример создания библиотеки из трех объектных файлов:
$ ar rcv exam.a test.o check.o prove.o
a - test.o
a - check.o
a - prove.o
$
Здесь ключи команды ar означают:
r - заменить (replace) модули в библиотеке;
c - создать (create) библиотеку;
v - печатать включаемые модули (verbose).
Теперь мы можем распечатать содержимое библиотеки ко-
мандой ar с ключом t (table of content):
$ ar t exam.a
test.o
check.o
prove.o
$
и ссылаться на библиотеку в командах вызова компиляторов
или линкера, например:
$ ld -o test /lib/frt0.o exam.a -lF77
Следует помнить, что порядок размещения модулей в библио-
теке существенен.
Например, если подпрограмма test вызывает подпрограмму
check, то test.o должен предшествовать check.o в библиотеке.
Для выявления и печати таких зависимостей предназначена ко-
манда lorder.
В начало страницы
Как правило, имеется единый символьный отладчик для прог-
рамм на нескольких языках программирования, компиляторы ко-
торых вырабатывают объектный код и таблицы символов в едине-
ом формате. Символьный отладчик обычно имеет альтернативные
имена для разных языков, например, cdb, fdb и pdb для языков
C, ФОРТРАН-77 и PASCAL соответственно. Вызов отладчика про-
изводится одноименной командой, в которой указывается файл
кода отлаживаемой программы, по умолчанию a.out. Для генера-
ции и сохранения отладочной информации (таблиц символов и
т.п.) компиляция программы должна производиться с ключом -g.
Пример:
$ fc -g test.f check.f prove.f
$ fdb
>
Знак > - подсказка отладчика, приглашающая вводить коман-
ды отладчика. Команды отладчика позволяют:
- посмотреть текущие значения переменных выполняемого
оператора, строки исходного текста, процедуры, файла в ука-
занном формате;
- устанавливать и сбрасывать точки прерывания для пошаго-
вого выполнения отлаживаемой программы между точками преры-
вания и/или с постоянным шагом;
- задавать утверждения, проверяемые перед выполнением
каждого оператора для останова перед теми операторами, для
которых утверждение истинно;
- копировать все сигналы, связанные с отлаживаемой прог-
раммой;
- записывать и повторно использовать команды сеанса от-
ладки (командный файл на входе отладчика).
Более подробную информацию о символьном отладчике можно
найти в руководстве по команде cdb.
В начало страницы
Имеются средства, позволяющие выяснить, сколько времени и
места требуется для выполнения программы и ее частей. Эти
средства полезны для сравнения качества реализации программы
на разных языках программирования или в разных версиях сис-
темы UNIX.
Команда time позволяет выяснить три значения потраченного
на решение указанной программы времени в секундах: реально-
го, равного времени, замеренному по секундомеру, зависящего
от количества пользователей в данный момент; пользователь-
ского, равного времени счета программы по командам пользова-
теля, и системного, равного времени системы при обслуживании
этой программы. Команда time в Shell и в C-Shell имеет раз-
ные формы выдачи.
Пример (в Shell):
$ time test
real 30.0
user 27.6
sys 0.5
$
Команда size показывает размер памяти в байтах трех раз-
личных частей программы: выполняемого кода (называемого
текстом), области инициируемых данных и области неинициируе-
мых данных.
Пример:
$ size test
1356 + 260 + 613 = 2226 b = 004265 b
Общий размер программы test равен 4265 байтов.
Если имя оцениваемого файла отсутствует, подразумевается
a.out.
Для программы на языке C есть более тонкое средство, поз-
воляющее получить профиль программы, показывающий для каждой
подпрограммы долю времени ее выполнения в процентах (%
time), суммарное время ее выполнения в секундах (cumsecs),
количество ее вызовов (# call) и время, потраченное на один
вызов в миллисекундах (ms/call). Для получения профиля сле-
дует перетранслировать программу с ключом -p (профиль), а
после запуска программы, во время которого статистическая
информация будет собрана в файле mon.out, выполнить команду
prof для обработки указанного файла.
Пример:
$ cc -p program.c
$ mv a.out program
$ program
$ ls
mon.out
program
program.c
$ prof program
name % time cumsecs # call ms/call
conv 58.6 11.38 2000 5.69
strcat 30.1 9.50 100 95.0
main 1.1 2.1 1 2.1
. . . . . . . . . . . . . . . . . . . . .
atoi 0.0 0.1 1 0.0
В начало страницы
Если программный продукт велик, содержит много исходных,
объектных и исполняемых модулей, задача его сопровождения и
модификации может быть облегчена утилитой make, которая поз-
воляет автоматизировать все рутинные операции по перетранс-
ляции и перелинкированию всех или части модулей при внесении
в них изменений.
Утилита make работает с файлом Makefile, в который запи-
сывается необходимая информация о всех файлах программы и
связях между ними.
Пример:
$ cat Makefile
FILES = test.f check.f prove.f
OBJECTS = test.o check.o prove.o
test: $ {OBJECTS}
ld -o test/lib/frt0.o ${OBJECTS} -lF77
$
Как видно из примера, в файле Makefile помещаются макро-
определения, имеющие вид:
строка1 = строка2
и правила, имеющие вид:
конечный файл : исходные файлы
команда
Первая строка правила называется зависимостью. Зависи-
мость указывает, что конечный файл является результатом ра-
боты команды, указанной во второй строке правила, над исход-
ными файлами. Внутри зависимости можно ссылаться на макрооп-
ределения в форме $(строка1).
Подготовив такой Makefile, можно модифицировать прог-
рамму test одним вызовом команды make, например:
$ make
fc -c test.f
fc -c check.f
fc -c prove.f
ld -o test/lib/frt0.o check.o prove.o -lF77
$
Команда выполняется только в том случае, если дата созда-
ния или модификации конечного файла меньше, чем соответству-
ющая дата хотя бы одного исходного файла (то есть если ко-
нечный файл устарел).
Возможно изменить только часть программы, например:
$ make prove.o
fc -c prove.f
$
В данном случае утилита make по умолчанию "знает", что
файл prove.o зависит от файла prove.f и реализация этой за-
висимости есть указанный вызов компилятора.
Полезный ключ -n утилиты make позволяет не выполняя пред-
писанных действий предварительно посмотреть, что было бы вы-
полнено, если бы ключ не был подан.
Подробнее о make можно узнать из руководства по команде
make и книг [7,8].
В начало страницы
До сих пор речь шла о разработке программ на языках прог-
раммирования, реализованных в системе (т.е. имеющих компиля-
тор и линкер). Если вас, как опытного пользователя, не уст-
раивают эти предопределенные языки и вы хотите реализовать
свой язык, то и в этом вам поможет система UNIX, предостав-
ляя утилиты lex и yacc.
Утилита lex является текстовым процессором, реализующим
лексический анализ, необходимый при создании компиляторов и
других языковых процессоров.
Утилита yacc (yet another compiler compiler) конвертирует
безконтекстную грамматику в таблицы, управляющие граммати-
ческим разбором посредством LR(1)-автомата. Формируемые при
этом правила предшествования позволяют избавиться от двус-
мысленностей исходной грамматики.
Совместное использование утилит lex и yacc является мощ-
ным подспорьем для быстрой реализации языковых процессоров в
среде системы UNIX [9,10,11].
В начало страницы
|