Реферат Курсовая Конспект
Мультифайловое программирование - раздел Программирование, Программирование для операционной системы Linux Как Уже Говорилось Выше, Если Исходный Код Сколько-Нибудь Серьезной Программы...
|
Как уже говорилось выше, если исходный код сколько-нибудь серьезной программы уместить в одном файле, то такой код станет просто нечитаемым. К тому же если программа компилируется достаточно долго (особенно это относится к языку C++), то после исправления одной ошибки, нужно перекомпилировать весь код.
Куда лучше разбросать исходный код по нескольким файлам (осмысленно, по какому-нибудь критерию), и компилировать каждый такой файл отдельно. Как вы вскоре узнаете, это очень даже просто.
Давайте сначала разберемся, как из исходного файла получается бинарник. Подобно тому, как гусеница не сразу превращается в бабочку, так и исходный файл не сразу превращается в бинарник. После компиляции создается объектный код. Это исполняемый код с некоторыми "вкраплениями", из-за которых объектный код еще не способен к выполнению.
Вернемся к объектному коду. Эти самые "вкрапления" (самое главное среди них - таблица символов) позволяют объектному коду "пристыковываться" к другому объектному коду. Такой фокус делает компоновщик (линковщик) - программа, которая объединяет объектный код, полученный из "разных мест", удаляет все лишнее и создает полноценный бинарник. Этот процесс называется компоновкой или линковкой.
Итак, чтобы откомпилировать мультифайловую программу, надо сначала добыть объектный код из каждого исходного файла в отдельности. Каждый такой код будет представлять собой объектный модуль. Каждый объектный модуль записывается в отдельный объектный файл. Затем объектные модули надо скомпоновать в один бинарник.
В Linux в качестве линковщика используется программа ld, обладающая приличным арсеналом опций. К счастью gcc самостоятельно вызывает компоновщик с нужными опциями, избавляя нас от "ручной" линковки.
Попробуем теперь, вооружившись запасом знаний, написать мультифайловый HelloWorld. Создадим первый файл с именем main.c:
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
/* main.c */
int main (void)
{
print_hello ();
}
Теперь создадим еще один файл hello.c со следующим содержимым:
/* hello.c */
#include <stdio.h>
void print_hello (void)
{
printf ("Hello Worldn");
}
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Здесь функция main() вызывает функцию print_hello(), находящуюся в другом файле. Функция print_hello() выводит на экран заветное приветствие. Теперь нужно получить два объектных файла. Опция -c компилятора gcc заставляет его отказаться от линковки после компиляции. Если не указывать опцию -o, то в имени объектного файла расширение .c будет заменено на .o (обычные объектные файлы имеют расширение .o):
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
$ gcc -c main.c
$ gcc -c hello.c
$ ls
hello.c hello.o main.c main.o
$
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Итак, мы получили два объектных файла. Теперь их надо объединить в один бинарник:
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
$ gcc -o hello main.o hello.o
$ ls
hello* hello.c hello.o main.c main.o
$ ./hello
HelloWorld
$
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Компилятор "увидел", что вместо исходных файлов (с расширением .c) ему подбросили объектные файлы (с расширением .o) и отреагировал согласно ситуации: вызвал линковщик с нужными опциями.
Давайте разберемся, что же все-таки произошло. В этом нам поможет утилита nm. Объектные файлы содержат таблицу символов. Утилита nm как раз позволяет посмотреть эту таблицу в читаемом виде. Те, кто пробовал программировать на ассемблере знают, что в исполняемом файле буквально все (функции, переменные) стоит на своей позиции: стоит только вставить или убрать из программы один байт, как программа тут же превратиться в груду мусора из-за смещенных позиций (адресов). У объектных файлов особая роль: они хранят в таблице символов имена некоторых позиций (глобально объявленных функций, например). В процессе линковки происходит стыковка имен и пересчет позиций, что позволяет нескольким объектным файлам объединиться в один бинарник. Если вызвать nm для файла hello.o, то увидим следующую картину:
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
$ nm hello.o
Uprintf
00000000 Tprint_hello
$
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
О смысловой нагрузке нулей и литер U,T мы будем говорить при изучении библиотек. Сейчас же важным является то, что в объектном файле сохранилась информация об использованных именах. Своя информация есть и в файле main.o:
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
$ nm main.o
00000000 Tmain
Uprint_hello
$
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Таблицы символов объектных файлов содержат общее имя print_hello. В процессе линковки высчитываются и подставляются в нужные места адреса, соответствующие именам из таблицы. Вот и весь секрет.
– Конец работы –
Эта тема принадлежит разделу:
Министерство образования и науки РФ... Федеральное агентство по образованию... Государственное образовательное учреждение высшего профессионального образования...
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Мультифайловое программирование
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов