Скачать презентацию Знакомство с GCC Операционные системы и системное программирование Скачать презентацию Знакомство с GCC Операционные системы и системное программирование

OS&SP_Part1.5_GCC.pptx

  • Количество слайдов: 63

Знакомство с GCC Операционные системы и системное программирование Знакомство с GCC Операционные системы и системное программирование

GCC GNU Compiler Collection — набор компиляторов для различных языков программирования, разработанный в рамках GCC GNU Compiler Collection — набор компиляторов для различных языков программирования, разработанный в рамках проекта GNU.

Файл F. с include <stdio. h> int main() { printf( Файл F. с include int main() { printf("Our first program for Linux. n"); return 0; }

Компиляция gcc -c <compile-options> F. c Компиляция gcc -c F. c

Компоновка gcc -o F <link-options> F. o Компоновка gcc -o F F. o

Компиляция и компоновка gcc -o F <compile-and-link-options> F 1. c Компиляция и компоновка gcc -o F F 1. c

Запуск. /F <arguments> Запуск. /F

Результат umax@ubuntu: ~$. /F Our first program for Linux. Результат umax@ubuntu: ~$. /F Our first program for Linux.

Поддержка стандарта С 1999 года По умолчанию компиляция программ C происходит c опцией -std=gnu Поддержка стандарта С 1999 года По умолчанию компиляция программ C происходит c опцией -std=gnu 89, т. е. 1989 года. Для поддержки стандарта С 1999 года используйте опцию -std=gnu 99 Пример: gcc -o F –std=gnu 99 F 1. c

Отладочная информация Вся эта отладочная информация предназначается для отладки программы отладчиком GNU Debugger. Запустить Отладочная информация Вся эта отладочная информация предназначается для отладки программы отладчиком GNU Debugger. Запустить его вы можете командой: gdb. /F

Опции отладки(1) Компилятор gcc может создавать отладочную информацию в различных объемах и форматах, контролировать Опции отладки(1) Компилятор gcc может создавать отладочную информацию в различных объемах и форматах, контролировать которые можно специальными ключами.

Опции отладки(2) • Ключ -g создает отладочную информацию в родном для операционной системы виде, Опции отладки(2) • Ключ -g создает отладочную информацию в родном для операционной системы виде, он выбирает между несколькими форматами: stabs, COFF, XCOFF или DWARF. На многих системах данный ключ позволяет использовать специальную информацию, которую умеет использовать только отладчик gdb. Другие ключи позволяют более тонко контролировать процесс встраивания отладочной информации.

Опции отладки(3) • Ключ -ggdb включает в исполняемый файл отладочную информацию в родном для Опции отладки(3) • Ключ -ggdb включает в исполняемый файл отладочную информацию в родном для ОС виде и дополняет ее специализированной информацией для отладчика gdb.

Опции отладки(4) • Ключ -gstabs создает отладочную информацию в формате stabs без дополнительных расширений Опции отладки(4) • Ключ -gstabs создает отладочную информацию в формате stabs без дополнительных расширений gdb. Данный формат используется отладчиком DBX на большинстве BSD систем. Ключ -gstabs+ дополняет отладочную информацию расширенниями понятными отладчику gdb.

Опции отладки(5) • Ключ -gcoff создает отладочную информацию в формате COFF, которая используется отладчиком Опции отладки(5) • Ключ -gcoff создает отладочную информацию в формате COFF, которая используется отладчиком SDB на большинстве систем System V до версии System V R 4.

Опции отладки(6) • Ключ -gxcoff снабжает файл информацией в формате XCOFF, который используется отладчиком Опции отладки(6) • Ключ -gxcoff снабжает файл информацией в формате XCOFF, который используется отладчиком DBX на системах IBM RS/6000. Использование -gxcoff+ влкючает использование дополнительной информации для gdb.

Опции отладки(7) • Ключ -gdwarf добавляет инфомацию в формате DWARF приняотм в системе System Опции отладки(7) • Ключ -gdwarf добавляет инфомацию в формате DWARF приняотм в системе System V Release 4. Соответственно ключ gdwarf+ прибавляет возможностей отладчику gdb.

Опции отладки(8) • Добавление к этим ключам в конце цифры позволяет увеличить или уменьшить Опции отладки(8) • Добавление к этим ключам в конце цифры позволяет увеличить или уменьшить уровень отладки, т. е. управлять размером требуемой отладочной информации.

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

Команды отладчика (1) • backtrace– выводит весь путь к текущей точке останова, то есть Команды отладчика (1) • backtrace– выводит весь путь к текущей точке останова, то есть названия всех функций, начиная от main(); иными словами, выводит весь стек функций; • break– устанавливает точку останова; параметром может быть номер строки или название функции; • clear– удаляет все точки останова на текущем уровне стека (то есть в текущей функции); • continue– продолжает выполнение программы от текущей точки до конца; • delete– удаляет точку останова или контрольное выражение;

Команды отладчика (2) • display– добавляет выражение в список выражений, значения которых отображаются каждый Команды отладчика (2) • display– добавляет выражение в список выражений, значения которых отображаются каждый раз при остановке программы; • finish– выполняет программу до выхода из текущей функции; отображает возвращаемое значение, если такое имеется; • info breakpoints – выводит список всех имеющихся точек останова; • info watchpoints – выводит список всех имеющихся контрольных выражений; • list– выводит исходный код; в качестве параметра передаются название файла исходного кода, затем, через двоеточие, номер начальной и конечной строки;

Команды отладчика (3) • next– пошаговое выполнение программы, но, в отличие от команды step, Команды отладчика (3) • next– пошаговое выполнение программы, но, в отличие от команды step, не выполняет пошагово вызываемые функции; • print– выводит значение какого-либо выражения (выражение передаётся в качестве параметра); • run– запускает программу на выполнение; • set– устанавливает новое значение переменной • step– пошаговое выполнение программы; • watch– устанавливает контрольное выражение, программа остановится, как только значение контрольного выражения изменится;

Создания релизов • strip -s F Создания релизов • strip -s F

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

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

Файл main. c #include <stdio. h> // описываем функцию f 1() как внешнюю extern Файл main. c #include // описываем функцию f 1() как внешнюю extern int f 1(); // описываем функцию f 2() как внешнюю extern int f 2(); int main() { int n 1, n 2; n 1 = f 1(); n 2 = f 2(); printf("f 1() = %dn", n 1); printf("f 2() = %dn", n 2); } return 0;

Файл f 1. с int f 1() { return 2; } Файл f 1. с int f 1() { return 2; }

Файл f 2. с int f 2() { return 10; } Файл f 2. с int f 2() { return 10; }

Компиляция gcc -c main. c f 1. c f 2. c ИЛИ gcc -c Компиляция gcc -c main. c f 1. c f 2. c ИЛИ gcc -c f 1. c gcc -c f 2. c gcc -c main. c

Результат компиляции main. o f 1. o f 2. o Результат компиляции main. o f 1. o f 2. o

Линковка gcc main. o f 1. o f 2. o -o rezult Линковка gcc main. o f 1. o f 2. o -o rezult

Запуск. /rezult Запуск. /rezult

Результат umax@ubuntu: ~/myfirst$. /rezult f 1() = 2 f 2() = 10 Результат umax@ubuntu: ~/myfirst$. /rezult f 1() = 2 f 2() = 10

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

Программка, которая выводит значения переданных параметров // программа test. c #include <stdio. h> int Программка, которая выводит значения переданных параметров // программа test. c #include int main(int argc, char *argv[]) { int i=0; } for (i=0; i

Типы параметров -h - короткий параметр --help - длинный параметр -s 10 - параметры Типы параметров -h - короткий параметр --help - длинный параметр -s 10 - параметры со значениями --size 10 --size=10

Передача опций в программу getopt #include <unistd. h> int getopt(int argc, char * const Передача опций в программу getopt #include int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt;

optstring Специальная строка optstring, в которой перечисляются названия коротких параметров и признаки того, что optstring Специальная строка optstring, в которой перечисляются названия коротких параметров и признаки того, что параметры должны иметь значение. Например, если программа должна воспринимать три параметра a, b, F , то такая строка бы выглядела как "ab. F". Если параметр должен иметь значение, то после буквы параметра ставится двоеточие, например параметр F и d имеют значения, а параметры e, a и b не имеют, тогда эта строка могла бы выглядеть как "e. F: ad: b". Если параметр может иметь (т. е. может и не иметь) значение, то тогда ставится два знака двоеточия, например "a: : "

optind Индекс текущего параметра optind Индекс текущего параметра

optarg значение параметра помещается optarg значение параметра помещается

opterr Если функция находит параметр не перечисленный в списке, то выводится сообщение об ошибке opterr Если функция находит параметр не перечисленный в списке, то выводится сообщение об ошибке в stderr и код ошибки сохраняется в opterr, при этом в качестве значения возврящается "? ". Вывод ошибки можно запретить, если установить opterr в 0.

Пример #include <stdio. h> #include <unistd. h> int main(int argc, char *argv[]){ int rez=0; Пример #include #include int main(int argc, char *argv[]){ int rez=0; opterr=0; while ( (rez = getopt(argc, argv, "ab: C: : d")) != -1) { switch (rez){ case 'a': printf("found argument "a". n"); break; case 'b': printf("found argument "b = %s". n", optarg); break; case 'C': printf("found argument "C = %s". n", optarg); break; case 'd': printf("found argument "d"n"); break; case '? ': printf("Error found !n"); break; } } }

Передача длинных опций в программу - getopt_long #define _GNU_SOURCE #include <getopt. h> int getopt_long(int Передача длинных опций в программу - getopt_long #define _GNU_SOURCE #include int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex); int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

Для работы функции getopt_long ей нужны следующие данные: • argc - счетчик количества параметров Для работы функции getopt_long ей нужны следующие данные: • argc - счетчик количества параметров командой строки argc. • argv - значения параметров командной строки argv[]. • optstring - список коротких названий параметров, аналогичные как getopt • longopts - специальный массив с названиями длинных параметров. • longindex - указатель на переменную, в которую будет помещен индекс текущего параметра из массива longopts.

Массив longopts состоит из записей struct option имеющих следующий вид struct option { const Массив longopts состоит из записей struct option имеющих следующий вид struct option { const char *name; int has_arg; int *flag; int val; };

has_arg #define no_argument 0 #define required_argument 1 #define optional_argument 2 has_arg #define no_argument 0 #define required_argument 1 #define optional_argument 2

flag задает указатель на флаг, в который помещается значение val, если найден данный параметр flag задает указатель на флаг, в который помещается значение val, если найден данный параметр (сама функция при этом возвращает 0). Если указатель равен NULL, то функция возвращает значение val в качестве результата работы.

longopts должна содержать нулевые значения, для того чтобы функция могла однозначно определить конец массива. longopts должна содержать нулевые значения, для того чтобы функция могла однозначно определить конец массива.

Пример longopt 1. c #include <stdlib. h> #include <stdio. h> #include <getopt. h> int Пример longopt 1. c #include #include #include int main (int argc, char *argv[]) { int flag_a = 0; int flag_b = 0; int flag_c = 0; const char* short_options = "abc"; const struct option long_options[] = { {"opta", no_argument, &flag_a, 1}, {"optb", no_argument, &flag_b, 10}, {"optc", no_argument, &flag_c, -121}, {NULL, 0, NULL, 0} }; while (getopt_long(argc, argv, short_options, long_options, NULL)!=-1); }; printf("flag_a = %dn", flag_a); printf("flag_b = %dn", flag_b); printf("flag_c = %dn", flag_c); printf("n");

Обработку коротких параметров не предусмотрели, если сейчас модифицируем код // добавьте переменную int rez; Обработку коротких параметров не предусмотрели, если сейчас модифицируем код // добавьте переменную int rez; // новый цикл обработки параметров while ((rez=getopt_long(argc, argv, short_options, long_options, NULL))!=-1) { printf("rez: %d = '%c'n", rez); };

Файл longopt 2. c: #include <stdlib. h> #include <stdio. h> #include <getopt. h> int Файл longopt 2. c: #include #include #include int main (int argc, char *argv[]){ const char* short_options = "hs: : f: "; const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"size", optional_argument, NULL, 's'}, {"file", required_argument, NULL, 'f'}, {NULL, 0, NULL, 0} }; int rez; int option_index; while ((rez=getopt_long(argc, argv, short_options, long_options, &option_index))!=-1){ switch(rez){ case 'h': { }; case 's': { printf("This is demo help. Try -h or --help. n"); printf("option_index = %d ("%s", %d, %c)n", option_index, long_options[option_index]. name, long_options[option_index]. has_arg, long_options[option_index]. val ); break; if (optarg!=NULL) else }; case 'f': { }; case '? ': default: { }; return 0; }; break; printf("found size with value %sn", optarg); printf("found size without valuen"); printf("file = %sn", optarg); break; printf("found unknown optionn"); break;

Функция getopt_long_only( ) Является полным аналогом getopt_long() за исключением того, что даже короткие параметры Функция getopt_long_only( ) Является полным аналогом getopt_long() за исключением того, что даже короткие параметры она пытается сравнить с длинными.

Вывод сообщений об ошибках программы Вывод сообщений обычно делается через стандартный поток stderr, который Вывод сообщений об ошибках программы Вывод сообщений обычно делается через стандартный поток stderr, который перенаправляет все данные на консоль. Можно делать это и через stdout, но он может быть перенаправлен в файл или куда-либо еще, к тому же он обладает буфером, который ему не позволяет выводить данные моментально и если программа резко "обрушится", то Вы можете не увидеть нужных сообщений вообще. В потоке stderr буфер отключен, поэтому вызов функции fflush(stderr) не обязателен.

syslogd #include <syslog. h> void openlog( char *ident, int option, int facility) void syslog( syslogd #include void openlog( char *ident, int option, int facility) void syslog( int priority, char *format, . . . ) void closelog( void )

Функция openlog() • • ident - текстовый идентификатор программы, обычно ее название. Он добавляется Функция openlog() • • ident - текстовый идентификатор программы, обычно ее название. Он добавляется к началу каждого сообщения для того, чтобы было видно от какой программы поступают сообщения. option - установки открываемого соединения, которые посредством операции OR могут складываться из следующих: – – • LOG_CONS - вывод напрямую в системную консоль, если вдруг происходит ошибка во время отправления сообщения LOG_NDELAY - открывать соединение сразу, обычно соединение открывается после появления первого сообщения LOG_PERROR - выводить сообщения в stderr LOG_PID - добавлять PID программы в каждое сообщение. Полезно когда может работать одновременно несколько одинаковых программ, в этом случае их можно различить по идентификатору процесса. facility - позволяет задать тип программы, которая выводит сообщение. Это полезно для того, чтобы разделять сообщения от различных программ и записывать их в разные файлы. Все это настраивается для syslogd файлом конфигурации /etc/syslog. conf. А значения этого параметра могут быть следующими: – – – LOG_AUTH - сообщения безопасности/авторизации (рекомендуется использовать LOG_AUTHPRIV) LOG_AUTHPRIV - приватные сообщения безопасности/авторизации LOG_CRON - сообщения от демонов времени (например, cron или at) LOG_DAEMON - сообщения от других демонов системы LOG_KERN - сообщения ядра системы LOG_LOCAL 0. . . LOG_LOCAL 7 - зарезервированы для локального использования LOG_LPR - подсистема принтера LOG_MAIL - почтовая подсистема LOG_NEWS - подсистема новостей USENET LOG_SYSLOG - внутренние сообщения сгенерированные syslogd LOG_USER (по умолчанию) - сообщения пользовательского уровня LOG_UUCP - сообщения системы UUCP

Функцию syslog() • LOG_EMERG - система не работает, грубо говоря в обмороке и требует Функцию syslog() • LOG_EMERG - система не работает, грубо говоря в обмороке и требует госпитализации : ) • LOG_ALERT - необходимо немедленно принять меры • LOG_CRIT - критическое состояние • LOG_ERR - ошибочное состояние • LOG_WARNING - состояние предупреждения • LOG_NOTICE - нормальное, но значимое, состояние • LOG_INFO - информационное сообщение • LOG_DEBUG - сообщение отладки, то что как раз нужно при разработке

#include <stdlib. h> #include <stdio. h> #include <syslog. h> Программа test. c #define DEBUG #include #include #include Программа test. c #define DEBUG int main(){ int i=0; openlog("test", LOG_PID, LOG_USER); #ifdef DEBUG syslog(LOG_DEBUG, "try to sending 10 messages"); #endif for (i=0; i<10; i++){ syslog(LOG_INFO, "info message [i = %d] ", i); }; #ifdef DEBUG syslog(LOG_DEBUG, "try log to stderr"); #endif closelog(); openlog("test_stderr", LOG_PERROR | LOG_PID, LOG_USER); syslog(LOG_INFO, "this is attempt to use stderr for syslog"); closelog(); }; return 0;

/var/log/messages Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 0] Dec /var/log/messages Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 0] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 1] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 2] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 3] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 4] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 5] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 6] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 7] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 8] Dec 20 11: 25: 04 dron-linux test[6222]: info message [i = 9] Dec 20 11: 25: 04 dron-linux test_stderr[6222]: this is attempt to use stderr for syslog

Настроить это можно с помощью файла /etc/syslog. conf # For info about the format Настроить это можно с помощью файла /etc/syslog. conf # For info about the format of this file, see "man syslog. conf" *. =info; *. =notice /var/log/messages *. =debug /var/log/debug *. err /var/log/syslog

Получение информации о пользователе Самые основные настройки для пользователя можно получить из переменных среды: Получение информации о пользователе Самые основные настройки для пользователя можно получить из переменных среды: • USER - имя пользователя • HOME - путь до пользовательской домашней директории • PATH - пути для поиска запускаемых программ (разделены двоеточием)

getenv #include <stdlib. h> char *getenv(const char *name); Данная функция ищет переменную среды с getenv #include char *getenv(const char *name); Данная функция ищет переменную среды с именем name и возвращает на нее указатель в случае удачи, иначе возвращает NULL.

Пример #include <stdlib. h> int main(){ printf( Пример #include int main(){ printf("USER = '%s'n", getenv("USER")); printf("HOME = '%s'n", getenv("HOME")); printf("PATH = '%s'n", getenv("PATH")); return 0; };

The end… The end…