Введение в UNIX

Дегтярев Е.К.

Оглавление

11. Средства разработки программ

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

11.1 Вызов компиляторов

В начало страницы

 
   В системе 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
   $

11.2. Линкер

В начало страницы


   На практике программы создаются  из  множества  раздельно
транслируемых модулей,  каждый из которых занимает отдельный
файл.  Результатом компиляции каждого модуля  является  файл
объектного (перемещяемого) кода, имя которого получается за-
меной .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 в командах вызова компилято-
ра.

11.3. Библиотеки

В начало страницы


   Как мы показали выше, на вход линкера могут подаваться не
только файлы объектного кода, но и библиотечные файлы, кото-
рые оказываются очень удобным средством  хранения  объектных
модулей, если их становится очень много.

   Имя библиотечного файла обычно оканчивается на .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.

11.4. Символьный отладчик

В начало страницы

   Как правило, имеется единый символьный отладчик для прог-
рамм на нескольких языках программирования,  компиляторы ко-
торых вырабатывают объектный код и таблицы символов в едине-
ом формате.  Символьный отладчик обычно имеет альтернативные
имена для разных языков, например, cdb, fdb и pdb для языков
C,  ФОРТРАН-77 и PASCAL соответственно. Вызов отладчика про-
изводится  одноименной командой,  в которой указывается файл
кода отлаживаемой программы, по умолчанию a.out. Для генера-
ции  и  сохранения  отладочной информации (таблиц символов и
т.п.) компиляция программы должна производиться с ключом -g.

   Пример:
 
   $ fc -g test.f check.f prove.f
   $ fdb
   >
   
   Знак > - подсказка отладчика, приглашающая вводить коман-
	ды отладчика. Команды отладчика позволяют:
	
   - посмотреть  текущие  значения  переменных  выполняемого
	оператора,  строки исходного текста, процедуры, файла в ука-
	занном формате;
	
   - устанавливать и сбрасывать точки прерывания для пошаго-
	вого  выполнения отлаживаемой программы между точками преры-
	вания и/или с постоянным шагом;
	
   - задавать  утверждения,  проверяемые  перед  выполнением
	каждого оператора для останова перед теми  операторами,  для
	которых утверждение истинно;
	
   - копировать все сигналы,  связанные с отлаживаемой прог-
	раммой;
	
   - записывать и повторно использовать команды  сеанса  от-
	ладки (командный файл на входе отладчика).
	
   Более подробную информацию о символьном  отладчике  можно
	найти в руководстве по команде cdb.

11.5. Средства оценки эффективности исполнения программы

В начало страницы

   Имеются средства, позволяющие выяснить, сколько времени и
места  требуется  для выполнения программы и ее частей.  Эти
средства полезны для сравнения качества реализации программы
на  разных языках программирования или в разных версиях сис-
темы 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

11.6. Сопровождение программ: make

В начало страницы

   Если программный продукт велик,  содержит много исходных,
объектных и исполняемых модулей,  задача его сопровождения и
модификации может быть облегчена утилитой 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].

11.7. Средства реализации языков программирования

В начало страницы

   До сих пор речь шла о разработке программ на языках прог-
раммирования, реализованных в системе (т.е. имеющих компиля-
тор и линкер).  Если вас, как опытного пользователя, не уст-
раивают  эти  предопределенные языки и вы хотите реализовать
свой язык,  то и в этом вам поможет система UNIX, предостав-
ляя утилиты lex и yacc.

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

   Утилита yacc (yet another compiler compiler) конвертирует
безконтекстную грамматику в таблицы,  управляющие  граммати-
ческим разбором посредством LR(1)-автомата.  Формируемые при
этом правила предшествования позволяют избавиться  от  двус-
мысленностей исходной грамматики.

   Совместное использование утилит lex и yacc является  мощ-
ным подспорьем для быстрой реализации языковых процессоров в
среде системы UNIX [9,10,11].


В начало страницы


<<< Оглавление Страницы: 11  12 >>>