Online Documentation Server
 ПОИСК
ods.com.ua Web
 КАТЕГОРИИ
Home
Programming
Net technology
Unixes
Security
RFC, HOWTO
Web technology
Data bases
Other docs

 

 ПОДПИСКА

 О КОПИРАЙТАХ
Вся предоставленная на этом сервере информация собрана нами из разных источников. Если Вам кажется, что публикация каких-то документов нарушает чьи-либо авторские права, сообщите нам об этом.




Previous | Содержание | Next

ВВЕДЕНИЕ В 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].

Previous | Содержание | Next



With any suggestions or questions please feel free to contact us