Софт-Портал

Gcc Options

Рейтинг: 4.5/5.0 (510 проголосовавших)

Категория: Linux

Описание

Компилятор GCC

Gcc - это свободно доступный оптимизирующий компилятор для языков C, C++, Ada 95, а также Objective C. Его версии существуют для различных реализаций Unix (а также VMS, OS/2 и других систем PC), и позволяют генерировать код для множества процессоров.

Вы можете использовать gcc для компиляции программ в объектные модули и для компоновки полученных модулей в единую исполняемую программу. Компилятор способен анализировать имена файлов, передаваемые ему в качестве аргументов, и определять, какие действия необходимо выполнить. Файлы с именами типа name.cc (или name.C) рассматриваются, как файлы на языке C++, а файлы вида name.o считаются объектными (т.е. внутримашинным представлением).

Чтобы откомпилировать исходный код C++, находящийся в файле F.cc, и создать объектный файл F.o, выполните команду:

gcc -c <compile-options> F .cc

Здесь строка compile-options указывает возможные дополнительные опции компиляции.

Чтобы скомпоновать один или несколько объектных файлов, полученных из исходного кода C++ - F1.o, F2.o. - в единый исполняемый файл F, используйте команду:

gcc -o F <link-options> F1.o F2.o. -lg++ <other-libraries>

Здесь строка link-options означает возможные дополнительные опции компоновки, а строка other-libraries - подключение при компоновке дополнительных разделяемых библиотек.

Вы можете совместить два этапа обработки - компиляцию и компоновку - в один общий этап с помощью команды:

gcc -o F <compile-and-link-options> F1.cc. -lg++ <other-libraries>

После компоновки будет создан исполняемый файл F, который можно запустить с помощью команды

где строка arguments определяет аргументы командной строки Вашей программы.

В процессе компоновки очень часто приходится использовать библиотеки. Библиотекой называют набор объектных файлов, сгруппированных в единый файл и проиндексированных. Когда команда компоновки обнаруживает некоторую библиотеку в списке объектных файлов для компоновки, она проверяет, содержат ли уже скомпонованные объектные файлы вызовы для функций, определенных в одном из файлов библиотек. Если такие функции найдены, соответствующие вызовы связываются с кодом объектного файла из библиотеки.

Библиотеки обычно определяются через аргументы вида -llibrary-name. В частности, -lg++ означает библиотеку стандартных функций C++, а -lm определяет библиотеку различных математических функций (sin, cos, arctan, sqrt, и т.д.). Библиотеки должны быть перечислены после исходных или объектных файлов, содержащих вызовы к соответствующим функциям.

Среди множества опций компиляции и компоновки наиболее часто употребляются следующие: -c

Только компиляция. Из исходных файлов программы создаются объектные файлы в виде name.o. Компоновка не производится.

Определить имя name в компилируемой программе, как значение value. Эффект такой же, как наличие строки #define name value в начале программы. Часть `=value' может быть опущена, в этом случае значение по умолчанию равно 1.

Использовать file-name в качестве имени для создаваемого gcc файла (обычно это исполняемый файл).

Использовать при компоновке указанную библиотеку.

Поместить в объектный или исполняемый файл отладочную информацию для отладчика gdb. Опция должна быть указана и для компиляции, и для компоновки.

Вывести заголовочные файлы (но не стандартные заголовочные файлы), используемые в каждом исходном файле, в формате, подходящем для утилиты make. Не создавать объектные или исполняемые файлы.

Поместить в объектный или исполняемый файл инструкции профилирования для генерации информации, используемой утилитой gprof. Опция должна быть указана и для компиляции, и для компоновки. Профилирование - это процесс измерения продолжительности выполнения отдельных участков Вашей программы. Когда Вы указываете -pg. полученная исполняемая программа при запуске генерирует файл статистики. Программа gprof на основе этого файла создает расшифровку, указывающую время, потраченное на выполнения каждой функции.

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

Оптимизация уровня 1. Оптимизированная трансляции требует несколько больше времени и несколько больше памяти для больших функций. Без указания опций `-O' цель компилятора состoит в том, чтобы уменьшить стоимость трансляции и выдать ожидаемые результаты при отладке. Операторы независимы: если вы останавливаете программу на контрольной точке между операторами, вы можете назначить новое значение любой переменной или поставить счетчик команд на любой другой оператор в функции и получить точно такие результаты, которые вы ожидали из исходного текста. С указанием `-O' компилятор пробует уменьшить размер кода и время исполнения.

Оптимизация уровня 2. GNU CC выполняет почти все поддерживаемые оптимизации, которые не включают уменьшение времени исполнения за счет увеличения длины кода. Компилятор не выполняет раскрутку циклов или подстановку функций, когда вы указываете `-O2'. По сравнения с `-O' эта опция увеличивает как время компиляции, так и эффективность сгенерированного кода.

Оптимизация уровня 3. `-O3' включает все оптимизации, определяемые `-O2', а также включает опцию `inline-functions'.

Не оптимизировать. Если вы используете многочисленные `-O' опции с номерами или без номеров уровня, действительной является последняя такая опция.


Alex Otwagin 2002-12-16

Gcc options:

  • скачать
  • скачать
  • Другие статьи, обзоры программ, новости

    Gcc: compiler alignment options

    Roman Kirjanov <***@sinn.ru> wrote:

    RK> Подскажите пожалуйста, какие рычаги есть в компиляторе языка C (не С++, если
    RK> отличаются)? Версия 2.92.

    Точно 2.92? Тогда менять немедленно. Либо на 2.95.последний, либо на
    3.3.5 или 3.4.последний.

    RK> Нужно выравнивание членов структур и самих структур.

    RK> PS
    RK> В гугле искали, в мане искали. Не нашли :(

    gcc документирован в info. Там это точно есть.

    Например, pragma pack там описана.

    Но вообще говоря, стоит внимательно подумать, а надо ли оно вам.

    Задайте себе следующие вопросы:

    1. Что будет если кто-то попробует собрать вашу программу под
    какой-нибудь 64-битный процессор (Itanium, AMD64, Sparc v9, PPC)
    где sizeof(long int)==8 и sizeof(char *)==8.

    2. Что будет если кто-нибудь попробует собрать вашу программу под
    BigEndian процессор (Sparc любой версии, PPC, Motorola 68K)

    Заметим что у спарка (и PPC по-моему тоже) есть еще та засада, что
    попытка обратиться к типу x по адресу, не кратному sizeof(x) приводит к
    SIGBUS.

    Поэтому стоит не играться с выравниванием структур, а написать
    собственные, независимые от байт-ордера и размера типов процедуры
    преобразования бинарных форматов входных данных в структуры и обратно.

    --
    Предоставив определенным мыслям убежище у себя в голове, я не
    могу их выдавать.
    --- С.Е. Лец

    Пересборка программ apt-build и вручную

    apt-build

    Ещё раз коротко. Apt-build это программа из комплекса сервисных программ для установки и обслуживания пакетов для debian-based систем, т.е. и для ubuntu тоже. Устанавливается как и всё в debian 'apt-get install apt-build' либо поиск&уcтановка в synaptic пакетном менеджере.

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

    Настройка

    Можно настроить программу apt-build двуми способами.

    1. dpkg-reconfigure apt-build
    2. Классический - ручная правка файлов конфигурации - /etc/apt/apt-build.conf

    Кроме назначения уровня оптимизации от -Оs до -О3 совсем нелишним будет вписать для опций компилятора gcc пару другую флагов если вы хотите увидеть более явный результат. Но помните что разные версии gcc,процессоры и программы уживаются с разными флагами по разному! К примеру, firefox не любит сборку уровня -O3, а gcc версии 4.4 может колбасить на флагах типа -ftree-vectorize или некоторые флаги будут выкинуты(устареют) для новой версии.

    Я не хочу использовать apt-build.

    Предположим кому то захотелось просто собрать и запустить программу из-под пользовательского аккаунта, не трогать систему администраторские рут привилегии. Как же тогда настроить флаги и прочее?

    • Первое примечание. Обычно сырцы программ на языке Си (src) которые вы скачиваете содержат файлик 'configure' который надо запустить из терминала с ключиком --help или -h или -help, чтобы увидеть с какими параметрами можно собрать программу.

    *Второе примечание - флаги для компилятора gcc можно прописать в файл /home/user_name/.bashrc любым текстовым редактором "навечно"(см.ниже пример), или, если вам неохота туда лезть можно прописать их на один терминальный сеанс командой
    export CFLAGS=" -O3 -march=athlon64-sse3 -funroll-all-loops"
    . где в кавычках вы уже проставите свои флаги опимизации.
    команда(или строка в .bashrc)
    export CC=/usr/bin/gcc-4.4
    Указывает какую из версий из имеющихся у вас компиляторов gcc надо использовать.

    Флаги для gcc.

    Шаг 3. Дополнительные флаги оптимизации.

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

    Оптимизация по скорости.
    • Loop Optimization using -Munroll, -Mvect, and -Mconcur. Loop performance may be
      improved through vectorization or unrolling options, and, on systems with multiple processors, by
      using parallelization options.
    • -Munroll unrolls loops. Executing multiple instances during each loop iteration reduces branch
      overhead, improving execution speed by creating better opportunities for instruction scheduling.
      Using -Munroll sub-options c:number and n:number, or using -Mnounroll can control whether
      and how loops are unrolled.
    • Mvect option triggers the vectorizer to scan code searching for loops that are candidates for high-
      level transformations such as loop distribution, loop exchange, cache tiling, and idiom recognition
      (replacement of a recognizable code sequence, such as a reduction loop, with optimized code
      sequences or function calls). The vectorizer transformation can be controlled by arguments to the
    • -Mvect option. By default, -Mvect without sub-options is equivalent to -Mvect=assoc,
      cachesize:262144. Vectorization sub-options are assoc, cachesize:number, sse, and prefetch.
    • -Mconcur option instructs the compiler to scan code searching for loops that are candidates for auto -
      parallelization. -Mconcur must be used at compile-time and link-time. The parallelizer performs
      various operations that are controlled by arguments to the -Mconcur option. By default, -Mconcur
      without sub-options is equivalent to -Mconcur=dist:block. Auto-Parallelization sub-options are
      altcode:number, dist:block, dist:cycle, cncall, noassoc, and innermost.

    Рекомендации для amd процессоров

    FSF GCC 4.2.0 and Red Hat GCC 4.2.0

    Step 1.Compile the program with -fprofile-generate.
    Step 2.Run the executable produced in Step 1. Running the
    executable generates several files with profile
    information (*.da).
    Step 3.Recompile the program with -fprofile-use.

    • -fstrict-aliasing - включает оптимизацию, основываясь на типе выражения. Считается что указатели разных типов указываю на разные участки памяти. Исключение составляют поля в объединениях.
    • -funroll-loops - оптимизация по раскрытию циклов с заранее известным количеством итераций. Может приводить к увеличению размера кода.
      или!
    • -funroll-all-loops - оптимизация по раскрытию всех циклов. Может приводить к увеличению размера и увеличению времени выполнения кода.
    • -fprofile-use задействует обратную связь (profile feedback) и оказывает воздействие на следующие ключи оптимизации, которые обязательно должны быть указаны в командной строке (или заданы уровнем оптимизации от O1 до O3), иначе вместо ожидаемого выхлопа мы получим "пшик":
    • -fpeel-loops:
      "шелушение циклов" (разновидность разворота) будет выполняться в соответствии с показаниями профилировщика;
    • -fvpt:
      заставляет профилировщик запоминать значения переменных, собираемые по ходу выполнения программы, которые в дальнейшем могут быть использованы для более эффективной оптимизации;
    • -fbranch-probabilities:
      в комбинации с ключом -fvpt форсирует подсчет частоты "срабатывания" каждого условного перехода, записывая полученные данные в файл sourcename.gcda, после чего оптимизатор сможет реорганизовать код таким образом, чтобы сократить накладные расходы на ветвления и уменьшить трассу выполнения (примечание: в текущих версиях gcc оптимизатор ограничивается лишь более эффективным распределением переменных по регистрам, но даже это дает существенный прирост производительности);
    • -ftracer:
      форсирует хвостовую дубликацию (tail duplication) - довольно прогрессивный, и, кстати говоря, запатентованный метод оптимизации, подробнее о котором можно прочитать на http://www.freepatentsonline.com/20050183079.html (см. также рис. 2).
    • -fprofile-generate задействует дополнительные возможности, заставляя профилировщик собирать еще больше данных, что позволяет использовать следующие ключи оптимизации:
    • -fprofile-arcs:
      собирает информацию о ходе выполнения программы, записывая ее в AUXNAME.da, и воздействует на следующие ключи оптимизатора, позволяющие генерировать более эффективный код: -fno-guess-branch-probability, -fbranch-probabilities и -freorder-functions - все эти ключи автоматически задействуются на уровнях оптимизации от O2 и выше, а потому нет никакой необходимости дописывать их вручную;
    • -fprofile-values:
      в комбинации с ключом -fprofile-arcs форсирует сбор значений переменных и выражений, позволяя отыскивать инварианты (т.е. значения, независимые от обрабатываемых программой данных) и оптимизировать процедуру вычисления многих вещественных выражений
    Оптимизация по размеру кода.
    • -fno-builtin - для таких функций, как abort, abs, alloca, cos, exit, fabs, ffs, labs, memcmp, memcpy, sin, sqrt, strcmp, strcpy и strlen gcc по умолчанию вместо вызова библиотечных функций генерирует inline код. Данный флаг предотвращает это, уменьшая размер кода, но при этом увеличивая время выполнения.
    • -fomit-frame-pointer - без этого флага для каждой функции генерируется пролог и эпилог примерно следующего вида:
      push ebp
      mov ebp,esp
      .
      mov esp,ebp
      pop ebp
      Использование данного флага позволяет исключить генерацию пролога и эпилога без необходимости. Что при большом числе функций в проекте, позволяет получить видимый выигрыш в размере.

    ". В случае "-Os" наблюдается как отставание, так и опережение по сравнению с режимами "-O2" и "-O3", при этом провалы иногда ощутимые, но с другой стороны и затраты оперативной памяти для работы программы при режиме "-Os" - минимальны."
    Ссылки:
    gcc: компиляция на форсаже с турбо-наддувом
    Профилятор gprof

    Оптимальные опции для x86 GCC - Версия для печати

    Оптимальные опции для x86 GCC

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

    Какие опции в GCC по умолчанию?

    (1) По умолчанию в GCC используется уровень оптимизаций “-O0”. Он явно не оптимален с точки зрения производительности и не рекомендуется для компиляции конечного продукта.
    GCC не распознает архитектуру, на которой запускается компиляция, пока не передана опция ”-march=native”. По умолчанию GCC использует опцию, заданную при его конфигурации. Чтобы узнать конфигурацию GCC, достаточно запустить:

    gcc -v
    «Configured with: [PATH]/configure … --with-arch=corei7 --with-cpu=corei7…»

    Это означает что GCC добавит “-march=corei7” к вашим опциям (если не будет указана другая архитектура).
    Большинство GCC компиляторов для x86 (базовый для 64 битного Linux) добавляет: “-mtune=generic -march=x86-64” к заданным опциям, так как при конфигурации не были заданы опции, определяющие архитектуру. Вы всегда можете узнать все опции, передаваемые при запуске GCC, а также его внутренние опции при помощи команды:

    echo «int main » | gcc [OPTIONS] -x c -v -Q –

    В итоге, часто используемое:

    построит “test.c” без каких-либо специфичных архитектурных оптимизаций. Это может привести к существенному спаду производительности (относительно архитектурно оптимизированного кода). Отключенная или ограниченная векторизация и неоптимальное планирование кода являются наиболее распространенными причинами спада производительности, если не указать или указать неправильную архитектуру.
    Для указания текущей архитектуры надо компилировать так:

    gcc -O2 test.c -march=native

    Указание используемой архитектуры важно для производительности. Единственным исключением можно считать те программы, где вызов библиотечных функций занимает почти все время запуска. GLIBC может выбрать оптимальную для данной архитектуры функцию во время исполнения. Важно отметить, что при статической линковке некоторые GLIBC функции не имеют версий под различные архитектуры. То есть динамическая сборка лучше, если важна быстрота GLIBC функций. .
    (2) По умолчанию большинство GCC компиляторов для x86 в 32 битном режиме используют x87 модель вычислений с плавающей точкой, так как были сконфигурированы без “-mfpmath=sse”. Только если GCC конфигурация содержит “--with-mfpmath=sse”:

    gcc -v
    «Configured with: [PATH]/configure … --with-mfpmath=sse…»

    компилятор будет использовать SSE модель по умолчанию.Во всех остальных случаях лучше добавлять опцию “-mfpmath=sse” к сборке в 32 битном режиме.
    Так, часто используемое:

    gcc -O2 -m32 test.c

    может привести к существенным потерям производительности в коде с вещественной арифметикой. Потому правильный вариант:

    gcc -O2 -m32 test.c -mfpmath=sse

    Добавление опции ”-mfpmath=sse” важно в 32 битном режиме! Исключением является компилятор, в конфигурации которого есть “--with-mfpmath=sse".

    32 битный режим или 64 битный?

    32 битный режим обычно используется для сокращения объема используемой памяти и как следствие ускорения работы с ней (больше данных помещается в кеш).
    В 64 битном режиме (по сравнению с 32 битным) количество доступных регистров общего пользования увеличивается с 6 до 14, XMM регистров с 8 до 16. Также все 64 битные архитектуры поддерживают SSE2 расширение, поэтому в 64 битном режиме не надо добавлять опцию “-mfpmath=sse”.
    Рекомендуется использовать 64 битный режим для счетных задач, а 32 битный режим для мобильных приложений.

    Как получить максимальную производительность?

    Определенного набора опций для получения максимальной проивзодительности не существует, однако в GCC есть много опций, которые стоит попробовать использовать. Ниже представлена таблица с рекомендуемыми опциями и прогнозами прироста для процессоров Intel® Atom™ и 2nd Generation Intel® Core™ i7 относительно опции “-O2”. Прогнозы основаны на среднем геометрическом результатов определенного набора задач, скомпилированных GCC версии 4.7. Также предполагается, что конфигурация компилятора была проведена для x86-64 generic.
    Прогноз увеличения производительности на мобильных приложениях относительно “-O2” (только в 32 битном режиме, так как он основной для мобильного сегмента):

    Преимущество 64 битного режима над 32 битным для вычислительных задач при опциях “-O2 -mfpmath=sse” составляет около

    5%
    Все данные в статье являются прогнозом, основанном на результатах определенного набора бенчмарков.
    Ниже представлено описание используемых в статье опций. Полное описание (на английском): http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Optimize-Options.html [1] "

    • "-Ofast" аналогично "-O3 -ffast-math" включает более высокий уровень оптимизаций и более агрессивные оптимизации для арифметических вычислений (например, вещественную реассоциацию)
    • "-flto" межмодульные оптимизации
    • "-m32" 32 битный режим
    • "-mfpmath=sse" включает использование XMM регистров в вещественной арифметике (вместо вещественного стека в x87 режиме)
    • "-funroll-loops" включает развертывание циклов

    URLs in this post:

    [1] http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Optimize-Options.html: http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Optimize-Options.html

    [2] Источник: http://habrahabr.ru/post/158939/

    Нажмите здесь для печати.

    Кросс-компиляция под Linux Vovanium

    Что же у нас есть для кросс-компиляции? Если не считать коммерческих продуктов и мелких поделок, то для того, чтобы скомпилировать любой проект под любую платформу, понадобится Gnu Compiler Collection, или, кратко, GCC. GCC — это один большой набор исходников, но собирать из него кросс-компилятор на каждую новую целевую платформу придётся отдельно.

    Надо сказать, список целевых платформ довольно внушителен.

    Вообще, для того, чтобы работать с GGC надо собрать т. н. Toolchain, набор утилит для компиляции. В toolchain входит помимно GCC, ещё Binutils, предназначенные для манипуляций с объектными и бинарными файлами. Для голого железа (если планируется работать не под ОС на целевой платформы, весьма полезной будет также NewLib — сборник стандартных процедур.

    В Binutils входят:

    Утилита определения места в исходнике по адресу.

    Утилита работы с объектными архивами.

    Дешифратор имён перегруженных функций и методов для языков C++ и Java.

    Генератор файлов для сборки и использования DLL.

    Библиотекарь — утилита для работы с динамическими и статическими библиотеками.

    Конвертер объектных файлов в NLM.

    Генератор списка символов.

    Копировщик и преобразователь объектных файлов.

    Утилита вывода информации по объектным файлам.

    Утилита индексирования объектных архивов.

    Утилита вывода информации по ELF-файлам.

    Измеритель размера секций и программ в целом.

    Извлекатель символьных строк из объектных файлов.

    Утилита для отфильтровывания символических имён, отладочной информации из бинарных файлов.

    Компилятор файлов сообщений для Windows.

    Компилятор ресурсов Windows.

    В составе GCC большой набор разнообразных инструментов, однако, скорее всего иметь дело придётся с frontend, который так и называется, gcc. Он сам определяет тип исходного файла и вызывает соответствующий компилятор, а также, по необходимости, линковщик или библиотекарь.

    NewLib — специальная подборка стандартных функций для встраиваемых систем. Она включает в себя libc (функци работы со строками, файлами и т. д.), libm (разнообразные математические функции). Также она обладает широкими возможностями конфигурирования под разнообразные требования.

    Надо сказать, NewLib далеко не единственный выбор. В принципе, если не пользоваться библиотечными функциями, можно вообще без библиотек обойтись, но этот путь сложен и тернист — стандарт си не требует наличия их в т. н. standalone environment 1). Вполне возможно, есть другие подходящие варианты

    GNU Debugger — стандартное средство отладки программ, и, в принципе, необязательно. Возможно, вы предпочтёте графический отладчик или вовсе пользуетесь исключительно printf-style-debug 2).

    Также стоит определить путь, куда будет всё установлено. В терминах GCC это называется prefix. По умолчанию этот путь — /usr/local. Однако по ряду различных причин иногда стоит специально указать другой. Первая причина — поставить в собственную домашнюю директорию, например, если нет root-полномочий на машине или просто его поставить только для себя (впрочем, лучше так не делать). Другая причина — бывает нужда с специальных вариантах сборки, и тогда это стоит делать, чтобы не спутать такую сборку с обычной. Стоит отметить, что компиляторы под различные платформы не перепутываются, так как имеют различные имена: gcc для ARM, например, будет именоваться arm-elf-gcc 3) или arm-linux-gcc. и именно его придётся указывать при компиляции (либо указывать target, тогда gcc сам вызовет нужный). Если же оставить путь по-умолчанию, сборка попадёт в стандартный путь поиска исполняемых файлов — /usr/local/bin. и может вызываться без специального указания пути или модификации $path.

    Для указания prefix у configure есть соответствующая опция: - -prefix=…

    Сборка тулчейна в описанной конфигурации состоит из следующих этапов:

    подготовка пространства для сборки, скачивание и распаковка исходников и т. п.;

    сборка и установка Binutils;

    сборка и установка предварительного варианта GCC для сборки NewLib;

    сборка и установка NewLib;

    сборка и установка окончательного варианта GCC (с поддержкой NewLib).

    Прежде всего нужно сделать себе „сборочную площадку“ для тулчейна. Пусть это будет директория.

    /toolchain. Создадим её и перейдём туда:

    Для инсталляции требуются свежие исходники.

    Binutils берётся с http://ftp.gnu.org/gnu/binutils/. файл типа binutils-n.n.n .tar.gz (n.n.n — версия, последняя на момент написания — 2.20.1)

    GCC качается с сайта http://gcc.gnu.org/mirrors.html. нужен файл типа gcc-n.n.n .tar.bz2 (последний на момент написания — 4.3.5).

    Newlib качается с сайта ftp://sources.redhat.com/pub/newlib/index.html. нужен файл типа newlib-n.n.n .tar.gz (последний на момент написания – 1.18.0)

    Маленькое замечание: в качестве последней версии GCC указана 4.3.5, несмотря на наличие 4.5.1. Дело в том, что это две параллельных ветки компилятора, однако 4.5.1 при этом мне собрать не удалось — возникала ошибка configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES.

    В дальнейшем в качестве примеров я буду приводить данные версии и целевую платформу arm-elf. так как собирал именно их. Полагаю, описание также подойдёт и к другим версиям и платформам. Сборка проивзводилась на дистрибутиве Ubuntu 10.04 LTS, поэтому замечания, касающиеся дополнительных бинарных пакетов, будут касаться именно его. однако, думаю, нет никаких сложностей найти аналогичные пакеты для любого другого.

    Распаковка сходников проста и элементарна для любого знакомого с командной строкой Linux:

    Для сборки тулчейна также необходимы дополнительные пакеты:

    Набор средств для сборки пакетов Debian, нужен, так как включает в себя всё необходимое для компиляции.

    Cредства подготовки документации в формате texinfo. Вроде бы, опциональный пакет, судя по тому, что выдаётся только предупреждение о его желательности, но компиляция binutils прерывается.

    Если какого-либо из этих пакетов, то сборка тулчейна прерывается с какой-нибудь ошибкой, причём из-за чего «лыжи не едут», бывает неочевидным. 4)

    Для сборки Binutils необходима отдельная пустая директория. И всё следует делать находясь в ней. Стандартную подготовку можно сделать так:

    Затем необходимо запустить скрипт конфигурации:

    Что значат эти опции:

    Наша целевая платформа

    Специфичная для ARM опция, обеспецивающая взаимодействие режимов ARM и THUMB.

    Также специфичная для ARM опция, необходимая для работы в нескольких режимах (LE, BE).

    Отключает интернационализацию. Обычно оно не нужно.

    Надо сказать, я сначала по ошибке скачал версию 2.9.1, и она отказалась собираться — configure выдавал ошибку под предлогом BFD does not support target arm-unknown-elf.

    После этого происходит собственно сборка:

    Впрочем, для ускорения можно указать опцию make -j n. где n — число потоков, в которых будет производиться сборка. Это ускорит сборку на многопроцессорных машинах, правда несколько сложнее будет разобрать вывод на экране в случае ошибки сборки.

    Затем установка в систему:

    ( sudo — команда, запускающая команду с правами root, если в вашей системе другой способ получения прав, используйте его).

    Если префикс сохранён по умолчанию, можно убедиться, что команды доступны из консоли — если набрать arm-elf- и нажать Tab, шелл предложит на выбор команды из пакета — arm-elf-ar, arm-elf-ld и т. д.

    Теперь стоит не забыть покинуть директорию сборки

    Так же, как и в случае с Binutils, процесс сборки GCC стоит проивзводить в отдельной директории

    Снова стоит разобрать опции конфигурации: 5)

    Всё то же, однако утверждают, что эта опция включена по умолчанию 6). так что её указывать не нужно, более того, обработка этой опции сломана в некоторых версиях GCC (4.5.1 например).

    Для сборки NewLib ничего не нужно, кроме компилятора си.

    Хитрая опция совместимости с NewLib. Что она делает, читайте в документации к GCC, но делает она совсем немного.

    Отключает установку стандартных хедеров, для сборки NewLib они не требуются.

    Отключает поддержку динамических библиотек, на встраиваемой системе оно и не нужно.

    Способ работы с числами с плавающей запятой — если нет FPU, ставится эта опция.

    Сборка NewLib начинается подобным одбразом:

    А дальше следует заметить, что у NewLib огромное количество конфигурационных параметров. О них подробно можно почитать в статье «konfiguracija_newlib ».

    ARM отличается разнообразием вариантов исполнения, подчас несовместимых с собой — little / big endian, наборами инструкций ARM, Thumb, Thumb2, JAVA и т. д, без или с блоком плавающей арифметики и т. д. Если только вы не собираетесь всегда работать с одним и тем же чипом, вам понадобится держать по крайней мере несколько вариантов библиотек. Так что здесь как нигде полезна будет опция Multilib.

    При сборке GCC обязательно укажите - -enable-multilib. а также набор необходимых вариантов 7).

    Multilib конфигурируется в файле gcc-n.n.n /gcc/config/arm/t-arm-elf из архива исходников. В нём следует раскомментировать соответствующие нужным опциям строки (убрав решётку и пробел в начале).

    Архитектура ARMv7 (Cortex, набор инструкций Thumb2):

    Способы передачи чисел с плавающей запятой:

    Разный порядок байтов:

    С и без блока плавающей арифметики:

    Поддержка Cortex (armv7) конфликтует с поддержкой hard-float ( make возвращает «configure: error: cannot compute suffix of object files: cannot compile»), видимо требуется добавить некоторые исключения, но понять, какие, мне не удалось. Так что либо FPU, либо Cortex, либо ковырять дальше.

    Строки, касающиеся поддержки разных ABI нужны, если их действительно нужно использовать.

    Версии, поддерживающие и не поддерживающие перекрёстные вызовы (режимы ARM/Thumb):

    Разные способы именования:

    Строки, касающиеся отдельных чипов, старых архитектур обычно можно не раскомментировать.

    Чипы Faraday Tech:

    Чипы Cirrus Logic

    ARMv3 и более ранние:

    Если сборка binutils или gcc обрывается странными ошибками компиляции, может помочь опция - -disable-werror.

    С libssp иногда не собирается gcc. К configure можно добавить ключ –disable-libssp.

    Про сборке ( make ) сообщение «configure: error: cannot compute suffix of object files: cannot compile» может говорить о том, что используются несовместимые опции, например в конфигурации Multilib (см. выше). Файл config.log при этом приходится искать в поддиректориях (можно использовать find. поиск в mc по указанному сообщению).

    В GCC есть поддержка дробной арифметики с фиксированной запятой согласно TR 18037: Embedded C. которая включается опцией конфигурации - -enable-fixed-point (и выключается соответстветственно - -disable-fixed-point ), однако она сделана только для платформы MIPS.

    Использование набора компиляторов gcc и отладчика gdb

    Использование набора компиляторов gcc и отладчика gdb

    Лабораторная работа №1

    Цель работы

    Ознакомиться с набором компиляторов gcc и отладчиком gdb; написать, скомпилировать с помощью gcc (с различными опциями сборки) программу на языке С; отладить программу в gdb.

    Содержание работы
    1. Ознакомиться с назначением, возможностями и особенностями работы с набором компиляторов gcc;
    2. Ознакомиться с назначением, возможностями и режимами работы отладчика gdb;
    3. Составить программу на языке С, реализующую требуемые действия.
    4. Скомпилировать, отладить и протестировать составленную программу, используя gcc и gdb;
    5. Ответить на контрольные вопросы.
    Методические указания к лабораторной работе

    Особенностью UNIX является то, что это была первая ОС, написанная на языке, отличном от ассемблера. Для целей написания UNIX и системного ПО для нее, параллельно велись работы по созданию эффективного языка высокого уровня, которые закончились созданием языка C (Си). В 1973 году ОС UNIX была переписана окончательно на языке С. В результате появилась ОС, 90% кода которой было написано на языке высокого уровня, языке, не зависящем от архитектуры машины и системы команд, а 10% было написано на ассемблере, в эти 10% входят наиболее критичные к реализации по времени части ядра ОС.

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

    В UNIX-системах для компиляции программ традиционно используется набор компиляторов gcc (GNU compiler collection). который включает компиляторы С и С++. В этом же наборе имеется еще несколько компиляторов, в том числе и ассемблер.

    Для компиляции программ на С предназначен компилятор cc. а для программ на языке С++ — компилятор g++. Синтаксис вызова у них одинаковый:

    1. infile – имя файла с исходным текстом;
    2. options – список необязательных параметров;
    3. outfile (с параметром -o) – выходной файл. Если параметр не указан, то будет создан исполняемый файл с именем a.out.
    Компиляторы из набора gcc имеют много различных опциональных параметров, что позволяет очень тонко настраивать процесс компиляции. Список общих параметров доступен при вызове программы с ключом --help (-v --help – для отображения всех, а их очень много, параметров). Подробную информацию о их назначении можно получить в man gcc или в Руководстве пользователя gcc (часть 1. часть 2 ). Здесь же перечислим только некоторые параметры:
    • -с – не ассемблировать, но создавать объектный файл (.о);
    • -S – не ассемблировать, но создавать файл с ассемблерным кодом (.s);
    • -I <path> — включить дополнительные файлы;
    • -L <path> — включить дополнительные библиотеки;
    • -g (или -ggdb) – включить в исполняемый файл отладочную информацию (при указании -ggdb будет представлена расширенная отладочная информация).

    Для отладки программ используется отладчик gdb. Синтаксис его вызова следующий:

    Отладчик gdb – интерактивный, поэтому его можно запускать без параметров, а задавать их прямо из него. Если указано имя исполнимого файла (executable_file), то он будет сразу же загружен в отладчик.

    Приведем несколько интерактивных команд gdb:
    • help – вывести справку о gdb;
    • b <line_num> — установить точку останова в строке line_num;
    • run – запустить программу на исполнение;
    • start – начать пошаговое выполнение;
    • next – выполнить следующую строку с обходом функций;
    • step – выполнить следующую строку со входом в функцию;
    • kill – прекратить выполнение отлаживаемой программы;
    • print <var_name> — показать значение переменной var_name;
    • q – выход из отладчика.

    Подробнее ознакомиться с использованием gdb можно на страницах руководств, например, этого .

    Задания к работе (общий вариант)
    1. Написать исходный код программы, приведенной в листинге №1, ознакомиться с описанием (руководство man, см. раздел 3 «Library functions» и раздел 2 «Linux Programmer’s Manual») используемых в программе системных функций (open, read, write, printf, close);
    2. Cкомпилировать написанную программу, включив в объектный модуль отладочную информацию;
    3. Запустить скомпилированную программу;
    4. Перекомпилировать программу без ассемблирования, ознакомиться с полученным ассемблерным кодом
    5. Переписать программу, исключив процедуру запроса имени файла, скомпилировать полученную программу с включением отладочной информации;
    6. Перекомпилировать новую программу без ассемблирования, сравнить ассемблерный код полученный при компиляции с кодом, полученным в п. 4. Какой из них компактней и почему (ответ привести в списке ответов на контрольные вопросы)?;
    Контрольные вопросы
    1. Какое значение принимает первый параметр функции main?
    2. Отличаются ли результаты выполнения программы при указании нового файла и при выборе существующего?
    3. С чем связана ошибка в программе из примера №1, возникающая (если это так) при обращении к имеющемуся файлу?
    4. Как можно устранить ошибку (если она возникает), описанную в п. 3 программными средствами (см. описание функции open) и средствами операционной системы?

    Глава 1 Приступая к работе

    Глава 1

    Приступая к работе

    В этой главе вы узнаете, что такое ОС Linux и как она связана со своим прообразом — ОС UNIX, познакомитесь с функциями и средствами, предоставляемыми средой разработки программ в ОС Linux, и напишите и выполните свою первую программу. Попутно вы получите представление о:

    □ UNIX, Linux и проекте GNU;

    □ программах и языках программирования в ОС Linux;

    □ способах поиска ресурсов разработки;

    □ статических и совместно используемых библиотеках;

    □ теоретических основах ОС UNIX.

    Введение в UNIX, Linux и проект GNU

    В последние годы ОС Linux стала заметным явлением. И дня не проходит без того или иного упоминания Linux в электронных средствах массовой информации. Мы потеряли счет приложениям, которые стали доступны в ОС Linux и внедрившим ее организациям, включая некоторые министерства и городские администрации. Основные поставщики компьютерного оборудования, такие как корпорации IBM и Dell, поддерживают ОС Linux, а крупнейшие разработчики программного обеспечения, например компания Oracle, обеспечивают выполнение своих программ в ОС Linux. Linux стала по-настоящему конкурентоспособной операционной системой, особенно на серверном рынке.

    Своим успехом она обязана системам и приложениям — предшественникам: ОС UNIX и программному обеспечению GNU. В этом разделе рассматривается, как появилась ОС Linux и каковы ее корни.

    Что такое ОС UNIX?

    Операционная система UNIX первоначально была разработана в компании Bell Laboratories, бывшей в то время частью телекоммуникационного гиганта, компании AT&T. Разработанная в 1970-х гг. для мини-компьютеров PDP корпорации Digital Equipment ОС UNIX стала очень популярной многопользовательской, многозадачной операционной системой для самых разных аппаратных платформ, начиная с рабочих станций PC и заканчивая многопроцессорными серверами и суперкомпьютерами.

    Краткая история ОС UNIX

    Строго говоря, UNIX — это торговое название, контролируемое организацией Open Group и относящееся к компьютерной операционной системе, соответствующей определенной спецификации. В этой спецификации, именуемой "The Single UNIX Specification" ("Единая спецификация UNIX"), определены имена, интерфейсы и поведение всех обязательных функций операционной системы UNIX. Данная спецификация в значительной степени представляет собой расширенный набор более ранних спецификаций, стандартов Р1003 или POSIX (Portable Operating System Interface, интерфейс переносимой операционной системы), разработанных IEEE (Institute of Electrical and Electronic Engineers, Институт инженеров по электротехнике и радиоэлектронике).

    Существует много коммерческих UNIX-подобных систем, таких как AIX корпорации IBM, UX компании HP и Solaris компании Sun Microsystems. Некоторые системы, например FreeBSD и Linux, свободно распространяются. В настоящее время спецификации Open Group удовлетворяют лишь несколько операционных систем, что позволяет предлагать их на рынке с названием UNIX.

    В прошлом совместимость разных систем UNIX была реальной проблемой, хотя стандарт POSIX и оказывал неоценимую помощь в ее решении. В наши дни следование нескольким простым правилам сделало возможным создание приложений, работающих под управлением всех UNIX и UNIX-подобных систем. Более подробную информацию о стандартах ОС Linux и UNIX вы сможете найти в главе 18.

    В последующих главах мы надеемся представить особенности программирования в ОС Linux (а следовательно, и в UNIX). Несмотря на то, что в большинстве своем программирование на языке С одинаково на разных платформах, у разработчиков Linux и UNIX есть свой взгляд на разработку программ и операционных систем.

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

    □ Простота. Многие из наиболее полезных утилит UNIX очень просты и как результат малы и понятны. KISS (Keep It Small and Simple, сохраняйте программу маленькой и простой) — отличный подход, которому следует научиться. Чем больше и сложнее система, тем наверняка в ней больше сложных ошибок, и отладка превращается в тяжелую работу, которой хотелось бы избежать.

    Узкая направленность. Зачастую лучше сделать программу, хорошо выполняющую одну задачу, чем включать в каждую функцию полный набор нужного и ненужного. "Раздутую" программу трудно использовать и поддерживать ее работоспособность. Одноцелевые программы легче усовершенствовать при появлении улучшенных алгоритмов или интерфейсов. В ОС UNIX при необходимости выполнения трудных задач чаще комбинируются маленькие утилиты, чем делается попытка в одной большой программе предусмотреть все потребности пользователя.

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

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

    Открытые файловые форматы. Наиболее удачные и популярные UNIX- программы применяют файлы конфигурации и файлы данных в виде обычного текста ASCII или файла на языке XML. Если в разрабатываемой вами программе можно использовать любой из этих форматов — это хороший выбор. Он позволит другим пользователям применить стандартные средства при изменении или поиске элементов конфигурации и разрабатывать новые средства для выполнения новых функций обработки файлов данных. Хорошим примером такого подхода может служить система перекрестных ссылок исходного кода ctags, записывающая сведения о местоположении символа в. виде регулярного выражения, подходящего для использования программами поиска.

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

    Что такое Linux?

    Как вы уже, возможно, знаете, Linux — это свободно распространяемая реализация UNIX-подобного ядра, низкоуровневой сердцевины операционной системы. Поскольку прообразом ОС Linux стала система UNIX, Linux- и UNIX-программы очень похожи. В действительности почти все программы, написанные для ОС UNIX, могут быть скомпилированы и выполнены в ОС Linux. Кроме того, некоторые коммерческие приложения, продаваемые для коммерческих версий UNIX, могут выполняться без изменения их двоичного кода в системах под управлением Linux.

    ОС Linux была разработана Линусом Торвальдсом (Linus Torvalds) из Университета г. Хельсинки совместно с программистами UNIX, оказывавшими ему помощь по Интернету. Работа начиналась как хобби, а вдохновителем стала ОС Minix Энди Таненбаума (Andy Tanenbaum), маленькая UNIX-подобная система. Со временем Linux выросла, превратившись в сложную самостоятельную систему. Ее цель — отказ от патентованного кода и применение только свободно распространяемого программного кода.

    В настоящее время ОС Linux существует для широкого набора компьютерных систем с разными типами процессоров, включая PC на 16- и 32-битных процессорах Intel x86 и совместимых с ними процессорах; рабочие станции и серверы на процессорах Sun SPARC, IBM PowerPC, AMD Opteron и Intel Itanium и даже некоторые карманные компьютеры PDA и игровые приставки Playstation 2 и 3 фирмы Sony. Если у устройства есть процессор, кто-то где-нибудь пытается добыть ОС Linux, выполняющуюся на этом процессоре!

    Проект GNU и Фонд свободного ПО

    ОС Linux обязана своим существованием совместным усилиям множества людей. Ядро операционной системы само по себе образует лишь малую часть пригодной к использованию системы разработки. Коммерческие системы UNIX традиционно снабжаются приложениями, обеспечивающими системные сервисы и средства. Для систем Linux подобные дополнительные программы написаны множеством разных программистов и распространяются они свободно.

    Linux-сообщество (совместно с другими людьми) поддерживает идею свободного программного обеспечения (ПО), т.е. свободного от ограничений и подчиняющегося Общедоступной лицензии проекта GNU (GNU General Public License, GPL). (GNU означает GNU's Not UNIX (GNU не UNIX).) Несмотря на то, что получение программного обеспечения может быть небесплатным, это ПО может использоваться как угодно и обычно распространяется в виде исходного программного кода.

    Фонд свободного программного обеспечения (Free Software Foundation) был организован Ричардом Столлменом (Richard Stallman) — автором GNU Emacs, одного из самых известных текстовых редакторов для ОС UNIX и других систем. Столлмен — автор концепции свободного программного обеспечения и организатор проекта GNU, попытки создания операционной системы и среды разработки, совместимой с ОС UNIX, но не подверженной ограничениям, связанным с торговой маркой UNIX и предоставлением исходного программного кода. В любой момент может оказаться, что проект GNU сильно отличается от UNIX способами поддержки аппаратных средств и управления исполняемыми программами, но он будет продолжать поддерживать приложения в стиле UNIX.

    Проект GNU уже снабдил программистское сообщество множеством приложений, сильно напоминающих, компоненты, входящие в системы UNIX. Все эти программы, называемые программным обеспечением GNU, распространяются в соответствии с Общедоступной лицензией GNU (GPL), копию которой можно найти на сайте http://www.gnu.org. В этой лицензии вводится понятие "авторского "лева" (copyleft)" (в противоположность авторскому праву ("copyright")). Авторское "лево" задумано как препятствие установлению каких-либо ограничений на использование свободного программного обеспечения.

    Далее приведены основные примеры ПО проекта GNU, распространяемого в соответствии с лицензией GPL:

    □ пакет компиляторов GCC (GNU Compiler Collection), включающий компилятор GNU С;

    □ G++ — компилятор С++, включающий как часть GCC;

    □ GDB — отладчик на уровне исходного кода;

    □ GNU make — версия UNIX-автосборщика make;

    □ Bison — генератор синтаксических анализаторов, совместимый с генератором компиляторов UNIX yacc;

    □ bash — командная оболочка;

    □ GNU Emacs — текстовый редактор и среда разработки.

    Кроме того, было разработано и распространено на принципах свободного ПО и под контролем лицензии GPL множество других пакетов, включая электронные таблицы, средства управления программным кодом, компиляторы, интерпретаторы, интернет-средства, программы обработки графических объектов, например, графический редактор Gimp и две законченные объектно-ориентированные среды разработки: GNOME и KDE. Мы обсудим GNOME и KDE в главах 16 и 17.

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

    Более подробную информацию о концепции свободного программного обеспечения можно получить на Web-сайте http://www.gnu.org.

    Дистрибутивы Linux

    Как мы уже упоминали, Linux — это только ядро. Вы можете получить исходный программный код ядра, откомпилировать его и установить на машину, а затем получить и установить много другого свободного программного обеспечения для завершения установки ОС Linux. Такие установки часто называют системами Linux, т.к. они содержат много программ помимо ядра. Большинство утилит приходит от проекта GNU Фонда свободного ПО.

    Понятно, что создание системы Linux только из исходного программного кода — трудное дело. К счастью, многие люди подготовили готовые к установке дистрибутивы (часто называемые разновидностями (flavor)), обычно загружаемые из Интернета или с CD/DVD-накопителей и содержащие не только ядро, но и множество других программных средств и утилит. Часто в их состав входит реализация X Window System — графической оболочки, общей для множества систем UNIX. Дистрибутивы обычно снабжаются программой установки и дополнительной документацией (как правило, все на компакт-дисках), чтобы помочь вам установить собственную систему Linux. К некоторым хорошо известным дистрибутивам, в особенности для семейства процессоров Intel х86, относятся дистрибутивы Red Hat Enterprise Linux и его усовершенствованный сообществом родственник Fedora, Novell SUSE Linux и свободно распространяемый вариант openSUSE, Ubuntu Linux, Slackware, Gentoo и Debian GNU/Linux. Подробную информацию о множестве других дистрибутивов можно найти на Web-сайте DistroWatch по адресу http://distrowatch.com.

    Программирование в ОС Linux

    Многие думают, что программирование в Linux означает применение языка программирования С. Известно, что ОС UNIX первоначально была написана на С и что большинство UNIX-приложений были написаны на языке С. Но для программистов ОС Linux, или UNIX, С — не единственно возможный вариант. Далее в книге мы назовем пару альтернатив.

    На самом деле первая версия UNIX была написана в 1969 г. на ассемблере PDP 7. Язык С был задуман Деннисом Ритчи (Dennis Ritchie) примерно в это время, и в 1973 г. он вместе с Кеном Томпсоном (Ken Tompson) по существу переписал на С все ядро UNIX, совершив настоящий подвиг в эпоху разработки системного программного обеспечения на языке ассемблера.

    В системах Linux доступен широкий диапазон языков программирования, многие из них свободно распространяются и есть на компакт-дисках или в архивах на FTP- сайтах в Интернете. Далее перечислена часть языков программирования, доступных программистам Linux:

    □ Bourne Shell.

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

    Linux-программы

    Linux-приложения представлены файлами двух типов: исполняемыми (executable) и сценариями или пакетными файлами (script). Исполняемые файлы — это программы, которые могут непосредственно выполняться на компьютере; они соответствуют файлам ОС Windows с расширением exe. Сценарии или пакетные файлы — это наборы команд для выполнения другой программой, интерпретатором. Они соответствуют в ОС Windows файлам с расширением bat или cmd или интерпретируемым программам на языке Basic.

    ОС Linux не требует, чтобы исполняемые или пакетные файлы имели определенные имена или какие-либо расширения. Для обозначения файла как способной выполняться программы применяются атрибуты файловой системы, которые будут обсуждаться в главе 2. В ОС Linux вы можете заменять пакетные файлы откомпилированными программами (и наоборот), не оказывая влияния на другие программы или пользователей, которые обращаются к ним. На уровне пользователя, по сути, между ними нет разницы.

    В процессе регистрации в системе Linux вы взаимодействуете с программой командной оболочки (часто bash), которая запускает программы так же, как это делает оболочка командной строки в ОС Windows. Она находит запрашиваемые вами программы по имени, выполняя поиск файла с тем же именем в заданном наборе каталогов. Каталоги, предназначенные для поиска, хранятся в переменной оболочки PATH. так же как в ОС Windows. Путь поиска (который вы можете пополнять) настраивается вашим системным администратором и обычно содержит стандартные каталоги, в которых сохраняются системные программы. К ним относятся:

    □ /bin — бинарные файлы (binaries), программы, применяемые для загрузки системы;

    □ /usr/bin — пользовательские библиотеки, стандартные программы, доступные пользователям;

    □ /usr/local/bin — локальные библиотеки, программы, относящиеся к этапу инициализации.

    Если войти в систему как администратор, например с именем root. можно использовать переменную PATH. которая включает каталоги с хранящимися системными программами, такие как /sbin и /usr/sbin.

    Необязательные компоненты операционной системы и приложения сторонних производителей могут устанавливаться в подкаталоги /opt, а добавить инсталляционные программы в вашу переменную PATH можно через пользовательские инсталляционные сценарии.

    Не стоит удалять каталоги из переменной PATH. пока нет полной уверенности в результате, который будет получен.

    Обратите внимание на то, что в ОС Linux, как и UNIX, для разделения отдельных элементов в переменной PATH применяется символ двоеточия (:) в отличие от символа точки с запятой, используемого в ОС MS-DOS и Windows. (ОС UNIX сделала выбор первой, поэтому спрашивайте, почему отличается Windows, а не почему в UNIX все не так!) Далее приведен пример переменной PATH :

    В этой переменной PATH содержатся каталоги для хранения стандартных программ, текущий каталог (.), исходный каталог пользователя и каталог графической оболочки X Window System.

    Запомните, в ОС Linux используется прямой слэш (/) для отделения имен каталогов в полном имени файла в отличие от обратного слэша (\), применяемого в ОС Windows. И снова ОС UNIX выбирала первой.

    Текстовые редакторы

    Для ввода и набора примеров программного кода, приведенных в книге, вам понадобится текстовый редактор. В типовых системах Linux есть большой выбор таких программ. У многих пользователей популярен редактор vi.

    Оба автора предпочитают Emacs, поэтому мы предлагаем потратить немного времени на знакомство с основными функциями этого мощного редактора. Почти во все дистрибутивы ОС Linux Emacs включен как необязательный пакет, который можно установить. Кроме того, вы можете получить его на Web-сайте GNU по адресу http://www.gnu.org или же взять версию для графических сред разработки на Web-сайте XEmacs по адресу http://www.xemacs.org.

    Для того чтобы узнать больше о редакторе Emacs, можно воспользоваться его интерактивным средством обучения. Начните с выполнения команды emacs. затем нажмите комбинацию клавиш <Ctrl>+<H> с последующим вводом символа t для доступа к этому средству. У редактора Emacs есть также полное руководство. Для получения дополнительной информации о нем в редакторе Emacs нажмите комбинацию клавиш <Ctrl>+<H> с последующим вводом символа i. В некоторых версиях Emacs может быть меню, предоставляющее доступ к средству обучения и полному руководству.

    Компилятор языка С

    В системах, соответствующих стандарту POSIX, компилятор языка С называется с89. Раньше компилятор языка С назывался просто сс. Шли годы, разные поставщики продавали UNIX-подобные системы с компиляторами С, обладающими разными функциями и параметрами, но очень часто все также названными сс.

    Когда создавался стандарт POSIX, выяснилось, что невозможно определить стандартную команду cc. которая была бы совместима со всеми этими разработками.

    Вместо этого комитет решил создать новую стандартную команду для компилятора языка С — с89. Если эта команда представлена, она всегда использует одни и те же опции независимо от машины.

    В системах Linux, которые на деле пытаются следовать стандартам, можно обнаружить, что все или некоторые из команд с89. cc и gcc ссылаются на системный компилятор языка С, обычно компилятор GNU С или gcc. В системах UNIX компилятор языка С почти всегда называется cc.

    В этой книге мы используем gcc, поскольку он поставляется в дистрибутивах Linux и потому что он поддерживает для языка С синтаксис стандарта ANSI. Если когда-нибудь вы обнаружите, что в вашей системе нет gcc, мы советуем получить его и установить. Найти его вы можете по адресу http://www.gnu.org. Всюду, где мы используем в книге команду gcc. просто заменяйте ее подходящей командой вашей системы.

    Упражнение 1.1. Ваша первая Linux-программа на языке C

    В этом примере вы начнете разработку в ОС Linux с помощью языка С, написав, откомпилировав и выполнив свою первую Linux-программу. Ею, кстати, может стать самая известная из всех программ для начинающих — программа, выводящая сообщение "Hello World" ("Привет, мир").

    1. Далее приводится текст файла hello.c:

    2. Теперь откомпилируйте, скомпонуйте и выполните вашу программу.

    $ gcc -о hello.c $ ./hello

    Как это работает

    Вы запустили компилятор GNU С (в Linux, вероятнее всего, он будет доступен и как cc ), который оттранслировал исходный код на языке С в исполняемый файл, названный hello. Вы выполнили программу, и она вывела на экран приветствие. Это наипростейший из существующих примеров, но если вы смогли с помощью вашей системы добраться до этого места, то сможете откомпилировать и выполнить и остальные примеры из книги. Если же программа не сработала, убедитесь в том, что в вашей системе установлен компилятор языка С. Например, во многих дистрибутивах Linux есть установочная опция, названная Software Development (Разработка ПО) (или что-то похожее), которую следует выбрать для установки необходимых пакетов.

    Поскольку это первая выполненная вами программа, самое время обратить внимание на некоторые основные положения. Программа hello, вероятно, должна быть в вашем исходном каталоге. Если в переменную PATH не включена ссылка на ваш исходный каталог, оболочка не сможет найти программу hello. Более того, если один из каталогов в переменной PATH содержит другую программу, названную hello, вместо вашей будет выполнена эта программа. То же самое произойдет, если такой каталог упомянут в переменной path раньше вашего исходного каталога. Для решения этой потенциальной проблемы можно снабдить имена программ префиксом ./ (например. /hello ). Данный префикс сообщает оболочке о необходимости выполнить программу с заданным именем, находящуюся в текущем каталоге. (Точка — это условное название текущего каталога.)

    Если вы забыли опцию -o name. которая указывает компилятору, куда поместить исполняемый файл, компилятор поместит его в файл с именем a.out (что означает ассемблерный вывод). Не забудьте поискать файл с именем a.out, если вы уверены, что скомпилировали программу, а найти ее не можете! Когда ОС UNIX только появилась, пользователи, хотевшие играть в ней в игры, часто запускали их как файл с именем a.out, чтобы не быть пойманными системным администратором, и некоторые установки ОС UNIX традиционно удаляют каждый вечер все файлы с именем a.out.

    Маршрутная карта системы разработки

    Разработчику ОС Linux важно знать кое-что о том, где размещаются средства и ресурсы разработки. В следующих разделах дан краткий обзор некоторых важных каталогов и файлов.

    Приложения обычно хранятся в отведенных для них каталогах. Приложения, предоставляемые системой для общего использования, включая средства разработки программ, находятся в каталоге /usr/bin. Приложения, добавленные системными администраторами для конкретного хост-компьютера или локальной сети, часто хранятся в каталоге /usr/local/bin или /opt.

    Администраторы предпочитают /opt и /usr/local, потому что они хранят предоставляемые конкретными поставщиками файлы и свежие дополнения отдельно от приложений, предоставляемых системой. Подобная организация хранения файлов может помочь, когда придет время обновлять операционную систему, т.к. в этом случае потребуется сберечь только каталоги /opt и /usr/local. Мы рекомендуем компилировать в ветви иерархии /usr/local только системные приложения общего назначения, предназначенные для запуска и доступа к требуемым файлам. Для разрабатываемых программ и личных приложений лучше всего применять папку в вашем исходном каталоге.

    Дополнительные средства и системы программирования могут иметь собственные структуры каталогов и каталоги программ. Важнейшая среди них — графическая оболочка X Window System, которая обычно устанавливается в каталог /usr/X11 или каталог /usr/bin/X11. В дистрибутивах Linux, как правило, применяется версия X.Org Foundation графической оболочки X Window System, базирующаяся на модификации Revision 7 (X11R7). В других UNIX-подобных системах могут быть выбраны иные версии X Window System, устанавливаемые в другие каталоги, например, каталог /usr/openwin для оболочки Open Windows компании Sun в системе Solaris.

    Программа системного драйвера компилятора GNU, gcc (которую вы использовали в предыдущем упражнении) обычно помещается в каталог usr/bin или usr/local/bin, но она будет запускать различные поддерживающие компиляцию приложения из других каталогов. Эти каталоги задаются во время компиляции самого компилятора и зависят от типа хост-компьютера. В системах Linux это может быть зависящий от конкретной версии подкаталог /usr/lib/gcc/. На одной из машин одного из авторов во время написания книги это был подкаталог /usr/lib/gcc/i586-suse-linux/4.1.3. В нем хранятся отдельные проходы компилятора GNU C/C++ и специфические заголовочные файлы GNU.

    В процессе программирования на языке С и других языках вам потребуются заголовочные файлы или файлы заголовков для включения определений констант и объявлений вызовов системных и библиотечных функций. В случае языка С эти файлы почти всегда находятся в каталоге /usr/include и его подкаталогах. Заголовочные файлы, зависящие от конкретного воплощения запущенной вами ОС Linux, вы, как правило, найдете в каталогах /usr/include/sys и /usr/include/linux.

    У других систем программирования тоже есть заголовочные файлы, хранящиеся в каталогах, которые автоматически находятся соответствующим компилятором. Примерами могут служить каталоги /usr/include/X11 для графической оболочки X Window System и /usr/include/c++ для языка GNU С++.

    Вы можете использовать заголовочные файлы из подкаталогов или нестандартных мест хранения, указав флаг -I (для include) в строке вызова компилятора языка С. Например, команда

    $ gcc -I/usr/openwin/include fred.c

    заставит искать заголовочные файлы, использованные в программе fred.c, в стандартных каталогах и в каталоге /usr/openwin/include. Для получения дополнительных сведений обратитесь к руководству компилятора С ( man gcc ).

    Искать заголовочные файлы с конкретными определениями и прототипами конкретных функций часто удобно с помощью команды grep. Предположим, вам нужно знать имя из директив #define. используемое для возврата из программы статуса завершения. Просто замените каталог на /usr/include и примените grep для поиска предполагаемой части имени следующим образом:

    stdlib.h#define EXIT_FAILURE 1 /*Failing exit status. */

    stdlib.h#define EXIT_SUCCESS 0 /*Successful exit status. */

    В этом случае команда grep ищет в каталоге все файлы с именами, заканчивающимися на .h, со строкой EXIT _. В данном примере она нашла (среди прочих) нужное вам определение в файле stdlib.h.

    Библиотеки — это наборы заранее откомпилированных функций, написанных в расчете на многократное использование. Обычно они состоят из наборов связанных функций, предназначенных для решения общей задачи. Примерами могут служить библиотеки функций работы с экраном (библиотеки curses и ncurses) и процедуры доступа к базе данных (библиотека dbm). В последующих главах мы познакомим вас с некоторыми библиотеками.

    Стандартные системные библиотеки обычно хранятся в каталогах /lib и /usr/lib. Компилятору языка С (или, точнее, компоновщику) необходимо сообщить, в каких библиотеках искать, поскольку по умолчанию он ищет только в стандартной библиотеке С. Это пережиток, пришедший к нам из того времени, когда компьютеры были медленными и циклы ЦПУ были дороги. Недостаточно поместить библиотеку в стандартный каталог и ждать, что компилятор найдет ее; библиотеки должны следовать очень специфическим правилам именования и быть упомянуты в командной строке.

    Имя файла библиотеки всегда начинается с символов lib. Далее следует часть, указывающая на назначение библиотеки (например, с для библиотеки С или m для математической библиотеки). Последняя часть имени начинается с точки (.) и задает тип библиотеки:

    □ а — для традиционных статических библиотек;

    □ .so — для совместно используемых библиотек (см. далее).

    Обычно библиотеки существуют в статическом и совместно используемом форматах, как покажет быстрый просмотр каталога командой ls /usr/lib. Вы можете заставить компилятор искать библиотеку, задав полное имя ее файла или применив флаг -l. Например, команда

    $ gcc -о fred fred.c /usr/lib/libm.a

    сообщает компилятору о необходимости компилировать файл fred.c и искать разрешения ссылок на функции в библиотеке математических функций в дополнение к стандартной библиотеке С. Аналогичного результата можно добиться с помощью следующей команды:

    $ gcc -о fred fred.c -lm

    -lm (без пробела между символами l и m ) — это сокращенное обозначение (сокращенные формы очень ценятся в UNIX-кругах) библиотеки с именем libm.a, хранящейся в одном из стандартных библиотечных каталогов (в данном случае /usr/lib). Дополнительное преимущество обозначения -lm в том, что компилятор автоматически выберет совместно используемую библиотеку, если она существует.

    Несмотря на то что библиотеки, как и заголовочные файлы, обычно хранятся в стандартных каталогах, вы можете добавить каталоги для поиска, указав флаг -L (заглавная буква) в команде вызова компилятора. Например, команда

    $ gcc -о x11fred -L/usr/openwin/lib x11fred.c -lX11

    будет компилировать и компоновать программу x11fred, используя версию библиотеки libX11, найденную в каталоге /usr/openwin/lib.

    Простейшая форма библиотеки — это коллекция объектных файлов, хранящихся вместе в виде, готовом к использованию. Когда программе нужна функция, содержащаяся в библиотеке, в нее включают заголовочный файл, объявляющий эту функцию. За соединение программного кода и библиотеки в единый исполняемый файл отвечают компилятор и компоновщик. Вы только должны применить опцию -l для указания нужных библиотек, отличных от стандартной библиотеки С исполняющей системы.

    Статические библиотеки, также называемые архивами, в соответствии с принятыми соглашениями имеют окончание .а. Например, lib/libc.а и /usr/lib/libX11 для библиотек С и X11 соответственно.

    Вы можете очень легко создавать и поддерживать собственные статические библиотеки с помощью программы ar (для создания архивов) и отдельно компилировать функции с помощью команды gcc -с. Старайтесь, насколько это возможно, хранить функции в отдельных исходных файлах. Если функциям нужен доступ к общим данным, вы можете поместить данные в один исходный файл и использовать статические переменные, объявленные в этом файле.

    Упражнение 1.2. Статические библиотеки

    В этом упражнении вы создадите свою маленькую библиотеку, содержащую две функции, и затем используете одну из функций в примере программы. Функции называются fred и bill и просто выводят приветствия.

    1. Сначала создайте отдельные исходные файлы (как не удивительно, названные fred.c и bill.c) для каждой функции.

    Далее приведен первый из них:

    void fred(int arg) <

    printf("fred: you passed %d\n", arg);

    void bill(char *arg) <

    printf("bill: you passed %s\n", arg);

    2. Вы можете отдельно откомпилировать эти функции и создать объектные файлы, готовые к включению в библиотеку. Для этого запустите компилятор С с опцией -с. которая помешает компилятору создать законченную программу. Попытка создать законченную программу окажется безуспешной, т.к. вы не определили функцию с именем main.

    $ gcc -с bill.с fred.c

    3. Теперь напишите программу, вызывающую функцию bill. Прежде всего, хорошо бы создать заголовочный файл для вашей библиотеки. В нем будут объявлены функции из вашей библиотеки, и он будет включаться во все приложения, которые захотят применить вашу библиотеку. В файлы fred.c и bill.c тоже хорошо бы включить заголовочный файл, чтобы помочь компилятору обнаружить любые ошибки.

    Это файл lib.h. В кем объявлены пользовательские функции fred and bill

    4. Вызывающая программа (program.с) может быть очень простой. Она включает заголовочный файл и вызов из библиотеки одной из функций.

    5. Теперь можно откомпилировать и протестировать программу. Для этого задайте компилятору явно объектные файлы и попросите его откомпилировать ваш файл и связать его с ранее откомпилированным объектным модулем bill.o.

    $ gcc -о program program.о bill.о

    bill: we passed Hello World

    6. Для создания архива и включения в него ваших объектных файлов используйте программу ar. Программа называется ar, поскольку она создает архивы или коллекции отдельных файлов, помещая их все в один большой файл. Имейте в виду, что программу ar можно применять для создания архивов из файлов любого типа. (Как многие утилиты UNIX, ar — универсальное средство.)

    $ ar crv libfоо.a bill.о fred.о

    а - bill.о а - fred.о

    7. Библиотека создана, и в нее добавлены два объектных файла. Для того чтобы успешно применять библиотеку в некоторых системах, в особенности в производных от Berkeley UNIX, требуется создать для библиотеки индекс содержимого архива или список вложенных в библиотеку функций и переменных (table of contents). Сделайте это с помощью команды ranlib. В ОС Linux при использовании программных средств разработки GNU этот шаг не является необходимым (но и не приносит вреда).

    Теперь ваша библиотека готова к использованию. Вы можете добавить следующий список файлов, которые должен обработать компилятор для создания вашей программы:

    $ gcc -о program program.о libfоо.а

    bill: we passed Hello world

    Можно было бы применить для доступа к библиотеке флаг -l. но т.к. она хранится не в одном из стандартных каталогов, вы должны сообщить компилятору место поиска с помощью флага -L следующим образом:

    $ gcc -о program .program.о -L. -lfoo

    Опция -L заставляет компилятор искать библиотеки в текущем каталоге (.). Опция -lfoo сообщает компилятору, что нужно использовать библиотеку с именем libfoo.a (или совместно используемую библиотеку libfoo.so, если она есть). Для того чтобы посмотреть, какие функции включены в объектный файл, библиотеку или исполняемую программу, можно применить команду nm. Если вы взглянете на файлы program и libfoo.a, то увидите, что библиотека содержит обе функции: fred и bill. а файл program — только функцию bill. Когда создается программа, в нее включаются из библиотеки только те функции, которые ей действительно нужны. Вставка заголовочного файла, содержащего объявления всех функций библиотеки, не вызывает включения в конечную программу целиком всей библиотеки.

    Если вы знакомы с разработкой программ в ОС Windows, то поймете, что в ОС UNIX существует ряд прямых аналогий, перечисленных в табл. 1.1.

    Совместно используемые библиотеки

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

    Устранить этот недостаток могут многие системы UNIX и Linux с поддержкой совместно используемых или разделяемых библиотек. Подробное обсуждение совместно используемых библиотек и их реализации в разных ОС не входило в нашу задачу, поэтому ограничимся только реализацией их в ОС Linux.

    Совместно используемые библиотеки хранятся в тех же каталогах, что и статические, но у имен файлов совместно используемых библиотек другой суффикс. В типовой системе Linux имя совместно используемой версии стандартной библиотеки математических функций — /lib/libm.so.

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

    В этом случае система предоставляет возможность многим приложениям одновременно использовать единственную копию совместно используемой библиотеки и хранить ее на диске в единственном экземпляре. Дополнительным преимуществом служит возможность обновления совместно используемой библиотеки независимо от базирующихся на ней приложений. Применяются символические ссылки из файла /lib/libm.so на текущую версию библиотеки (/lib/libm.so.N. где N — основной номер версии — 6 во время написания книги). Когда ОС Linux запускает приложение, она учитывает номер версии библиотеки, требующийся приложению, чтобы не дать ведущим новым версиям библиотеки испортить более старые приложения.

    Вывод в следующем примере получен из дистрибутива SUSE 10.3. Если вы применяете другой дистрибутив, ваш вывод может слегка отличаться.

    В системах Linux программа (динамический загрузчик), отвечающая за загрузку совместно используемых библиотек и разрешение ссылок на функции в клиентских программах, называется ld.so и может присутствовать в системе как ld-linux.so.2, или li-lsb.so.2, или li-lsb.so.3. Дополнительные каталоги поиска совместно используемых библиотек настраиваются в файле /etc/ld.so.conf, который после внесения изменений (например, если добавляются совместно используемые библиотеки X11 при установке графической оболочки X Window System) следует обработать командой ldconfig .

    Запустив утилиту ldd. вы можете увидеть, какие совместно используемые библиотеки требуются программе. Например, если вы попытаетесь выполнить утилиту для приложения из нашего примера, то получите следующие строки:

    linux-gate.so.1 => (0xffffe000)

    libc.so.6 => /lib/libc.so.6 (0xb7db4000)

    В этом случае вы видите стандартную библиотеку С (libc) как совместно используемую (.so). Программе требуется основная версия 6. В других системах UNIX принимаются аналогичные меры для получения доступа к совместно используемым библиотекам. Подробную информацию можно найти в системной документации.

    Во многом совместно используемые библиотеки аналогичны динамически подключаемым библиотекам в ОС Windows. Библиотеки с расширением .so соответствуют файлам с расширением dll и требуются во время выполнения, а библиотеки с расширением .а аналогичны файлам с расширением lib, которые включаются в исполняемые программы.

    Получение справки

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

    Доступ к интерактивным справочным руководствам обеспечивает команда man. Эти справочные руководства отличаются качеством и деталями. Одни могут просто переадресовать читателя к другой, более полной документации, в то время как другие дают полный перечень всех опций и команд, поддерживаемых утилитой. В любом случае справочные руководства — подходящий способ знакомства с приложением.

    Комплект программного обеспечения проекта GNU и другое свободное ПО используют интерактивную систему документации, названную info. Вы можете просмотреть всю документацию в интерактивном режиме с помощью специальной программы info или команды info редактора emacs. Достоинство системы info в том, что вы можете перемещаться по разделам документации с помощью связей и перекрестных ссылок, переходя непосредственно к нужному вам разделу. Для разработчика документации преимущество в том, что справочные файлы могут автоматически генерироваться из того же источника, что и печатные или набранные на клавиатуре страницы документации.

    Упражнение 1.3. Справочные руководства и система info

    Давайте познакомимся с документацией для компилятора GNU С (gcc).

    1. Сначала посмотрим на справочное руководство.

    gcc — GNU project С and С++ compiler

    gcc [-с|-S|-E] [-std=standard]

    Резюме