Учебно-методические материалы для студентов кафедры АСОИУ

Учебные программы » Системы реального времени » Лабораторные работы

Использование набора компиляторов 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++. Синтаксис вызова у них одинаковый:

gcc <options> infile <-o outfile> //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 – интерактивный, поэтому его можно запускать без параметров, а задавать их прямо из него. Если указано имя исполнимого файла (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

/*-----------------------------------------------------------------------------
Программа sample1.c к ЛР №1, которая выполняет запись и чтение файла. 
Программа принимает в качестве параметра командной строки имя рабочего файла. Если файл не
существует, он будет создан.
-------------------------------------------------------------------------------*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>

extern int errno; // код ошибки, если она возникнет
int fd; //дескриптор файла, имя задается из коммандной строки

//запись в файл 10 чисел
int writeToFile() {
static int j = 1;
if (j > 10) return 0;
write(fd, &j, sizeof(int));
printf("Write %i to file (fd %i)\t", j++, fd);
return 1;
}

//чтение из файла 
void readFromFile() {
int i = 0;
lseek(fd,-sizeof(int), 1);
read(fd,&i, sizeof(int));
printf("Read %i from file (fd %i)\n", i, fd);
}

int main(int argc, char *argv[]) {
// Раскомментируйте следующую строку для просмотра 
// списка аргументов командной строки
//printf("Param count: %i \nParam list : %s, %s \n\n", argc, argv[0],argv[1]);
// проверить параметры командной строки
if (argc != 2) { 
	puts("Usage: sample1 <outfile>\n");
	return -1;
}
// проверить, не возникло ли ошибки при открытии файла
if ((fd = open(argv[1], O_CREAT | O_RDWR))==-1) {
	perror("ERROR: ");
	return -1;
}
// цикл записи/чтения файла 
while (writeToFile()) readFromFile(); 
close(fd);
return 0;
}

Контрольные вопросы

  1. Какое значение принимает первый параметр функции main?
  2. Отличаются ли результаты выполнения программы при указании нового файла и при выборе существующего?
  3. С чем связана ошибка в программе из примера №1, возникающая (если это так) при обращении к имеющемуся файлу?
  4. Как можно устранить ошибку (если она возникает), описанную в п. 3 программными средствами (см. описание функции open) и средствами операционной системы?

Анатольев А.Г., 18.09.2012

Постоянный адрес этой страницы:

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