ЛАБОРАТОРНАЯ РАБОТА №4 (Метода по выполнению лабораторной работы 4 по СПО)
Описание файла
Документ из архива "Метода по выполнению лабораторной работы 4 по СПО", который расположен в категории "". Всё это находится в предмете "системное программное обеспечение (спо)" из 6 семестр, которые можно найти в файловом архиве МПУ. Не смотря на прямую связь этого архива с МПУ, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "системное программное обеспечение (спо)" в общих файлах.
Онлайн просмотр документа "ЛАБОРАТОРНАЯ РАБОТА №4"
Текст из документа "ЛАБОРАТОРНАЯ РАБОТА №4"
13
ЛАБОРАТОРНАЯ РАБОТА №4
ПРОГРАММИРОВАНИЕ НА С В UNIX/LINUX
3.1 Цель работы
Целью данной работы является получение основных сведений о системных вызовах, базовых средств взаимодействия процессов, (порождение процесса, замена тела процесса, взаимодействие при помощи передачи/приема сигналов), отладка программы на С в UNIX/LINUX (анализ и исправление ошибок на стадии компиляции и в процессе работы программы).
3.2 Задание на выполнение работы
1) Установить компилятор GNU С Compiler под UNIX/LINUX*.
2) Написать и отладить программу, выводящую на экран строку «Hello UNIX»
-
с использованием стандартной библиотеки ввода-вывода;
-
с использованием функции непосредственной записи в стандартный поток вывода.
3) Написать и отладить программу, запрашивающую 2 числа и выводящую их наибольший общий делитель. Использовать алгоритм Евклида.
4) Написать и отладить программу, принимающую из командной строки 2 числа. Если эти числа равны, вывести на экран только одно число, если нет – вывести числа в порядке возрастания.
5) Написать и отладить программу, определяющую является ли файл исполняемым файлом формата ELF. Программа должна запросить у пользователя имя файла. Если файл не удастся открыть, проанализировать ошибку и выдать соответствующее сообщение.
6) Написать пример программы, которая запускает и связывает каналом два процесса: вывод содержимого каталога и подсчет количества строк (ls и wc).
7) Написать пользовательскую функцию обработки сигнала. Установка обработки сигнала происходит одноразово (обрабатывается только одно событие, связанное с появлением данного сигнала SIG_ALRM). Возврат из функции-обработчика происходит в точку прерывания процесса.
3.3 Краткие теоретические сведения
3.3.1 Установка компилятора
Компилятор GNU С Compiler представляет собой набор исполняемых файлов и библиотек. В дистрибутиве ASPLinux 7.3 он находится в пакете gсс-2.96-112asp.i386.rpm на диске 2. Для того чтобы поставить любой rpm-пакет в консоли надо набрать команду
rрт -i [имя_пакета] ,
в KDE следует использовать программу KPackager. Следует помнить, что между пакетами может существовать зависимость, т.е. один пакет не возможно поставить без предварительной установки другого. В случае с ASPLinux 7.3, при использовании типичной комплектации, при установке операционной системы gcc не ставится.
3.3.2 Компиляция
Процедура создания большинства приложений является общей. Первой фазой является стадия компиляции, когда файлы с исходными текстами программы, включая файлы заголовков, обрабатываются компилятором сс. Параметры компиляции задаются либо с помощью файла makefile, либо явным указанием необходимых опций компилятора в командной строке. В итоге компилятор создает набор промежуточных объектных файлов. Традиционно имена созданных объектных файлов имеют суффикс « .о».
На следующей стадии эти файлы с помощью редактора связей ld связываются друг с другом и с различными библиотеками, включая стандартную библиотеку по умолчанию и библиотеки, указанные пользователем в качестве параметров. При этом редактор связей может выполняться в двух режимах: статическом и динамическом, что задается соответствующими опциями. В статическом, наиболее традиционном режиме связываются все объектные модули и статические библиотеки (их имена имеют суффикс «.а»), производится разрешение всех внешних ссылок модулей и создается единый исполняемый файл, содержащий весь необходимый для выполнения код. Во втором случае, редактор связей по возможности подключает разделяемые библиотеки (имена этих библиотек имеют суффикс «.so»). В результате создается исполняемый файл, к которому в процессе запуска на выполнение будут подключены все разделяемые объекты. В обоих случаях по умолчанию создается исполняемый файл с именем a.out.
В UNIX/LINUX при использовании компилятора gcc исходник программы пишется в обычном текстовом редакторе (например встроенный в тс редактор) и сохраняется с расширением .с. Далее исходник транслируется:
$ сс -с [имя__исходного_файла]
после данной команды получается объектный файл с расширением .о (если не было ошибок) и компилируется:
$ сс -о [имя_исполняемого_файла] [имя_объектного файла]
после данной команды получается исполняемый файл.
Для достаточно простых задач все фазы автоматически выполняются вызовом команды:
$ make [имя исходного файла без расширения]
Заметим, что команда cc является программной оболочкой и компилятора, и редактора связей, которую и рекомендуется использовать при создании программ.
3.3.3 Форматы исполняемых файлов
В большинстве современных операционных систем UNIX используются два стандартных формата исполняемых файлов – COFF (Common Object File Format) и ELF (Executable and Linking Format).
Описание форматов исполняемых файлов необходимо для описания базовой функциональности ядра операционной системы. Информация, хранящаяся в исполняемых файлах форматах COFF и ELF позволяет получить информацию для работы приложения и системы в целом: какие части программы необходимо загрузить в память; как создается область неинициализированных данных; где в памяти располагаются инструкции и данные программы, какие библиотеки необходимы для выполнения программы; как связан исполняемый файл на диске; образ программы в памяти и дисковая область свопинга.
Базовая структура памяти для процессов, загруженных из исполняемых файлов форматов COFF и ELF содержит одни и те же основные компоненты (сегменты кода, данных, стека), хотя расположение сегментов различно. Независимо от формата исполняемого файла виртуальные адреса процесса не могут выходить за пределы 3 Гбайт.
Формат ELF
Формат ELF имеет файлы нескольких типов. Стандарт ELF различает следующие типы:
-
Перемещаемый файл (relocatable file), хранящий инструкции и данные, которые могут быть связаны с другими объектными файлами. Результатом такого связывания может быть исполняемый файл или разделяемый объектный файл.
-
Разделяемый объектный файл (shared object file) также содержит инструкции и данные, но может быть использован двумя способами. В первом случае, он может быть связан с другими перемещаемыми файлами и разделяемыми объектными файлами, в результате чего будет создан новый объектный файл. Во втором случае, при запуске программы на выполнение операционная система может динамически связать его с исполняемым файлом программы, в результате чего будет создан исполняемый образ программы. В последнем случае речь идет о разделяемых библиотеках.
-
Исполняемый файл хранит полное описание, позволяющее системе создать образ процесса. Он содержит инструкции, данные, описание необходимых разделяемых объектных файлов, а также необходимую символьную и отладочную информацию.
ELF-файл
Заголовок ELF-файла имеет фиксированное расположение. Остальные компоненты размещаются в соответствии с информацией, хранящейся в заголовке. Таким образом, заголовок содержит общее описание структуры файла, расположение отдельных компонентов и их размеры. Поскольку заголовок ELF-файла определяет его структуру, в табл. 3.1 приведены более подробно поля заголовка.
Таблица 3.1 –Поля заголовка ELF-файла
Поле | Описание |
1 | 2 |
e_ident [ ] | Массив байт, каждый из которых определяет некоторую общую характеристику файла: формат файла (ELF), номер версии, архитектуру „ системы (32-разрядная или 64-разрядная) и т. д. |
e_type | Тип файла |
e_machine | Архитектура аппаратной платформы, для которой создан данный файл |
e_version | Номер версии ELF-формата. Обычно определяется как EV_CURRENC (текущая), что означает последнюю версию |
e_entry | Виртуальный адрес, по которому системой будет передано управление после загрузки программы (точка входа) |
e_phoff | Р Расположение (смещение от начала файла) таблицы заголовков программы |
e_shof f | Расположение таблицы заголовков секций |
1 | 2 |
e_ehsize | Размер заголовка |
e_phentsize | Размер каждого заголовка программы |
e_phnum | Число заголовков программы |
e_shentsize | Размер каждого заголовка сегмента (секции) |
e_shnum | Число заголовков сегментов (секций) |
e_shstrndx | Расположение сегмента, содержащего таблицу строк |
Информация, содержащаяся в таблице заголовков программы, указывает ядру, как создать образ процесса из сегментов. Большинство сегментов копируются (отображаются) в память и представляют собой соответствующие сегменты процесса при его выполнении, например, сегменты кода или данных.
Каждый заголовок сегмента программы описывает один сегмент и содержит следующую информацию:
- тип сегмента и действия операционной системы с данным сегментом;
-
расположение сегмента в файле;
-
стартовый адрес сегмента в виртуальной памяти процесса;
-
размер сегмента в файле;
-
размер сегмента в памяти;
- флаги доступа к сегменту (запись, чтение, выполнение).
Часть сегментов имеет тип LOAD, предписывающий ядру при запуске программы на выполнение создать соответствующие этим сегментам структуры данных, называемые областями, определяющие непрерывные участки виртуальной памяти процесса и связанные с ними атрибуты. Сегмент, расположение которого в ELF-файле указано в соответствующем заголовке программы, будет отображен в созданную область, виртуальный адрес начала которой также указан в заголовке программы. К сегментам такого типа относятся, например, сегменты, содержащие инструкции программы (код) и ее данные. Если размер сегмента меньше размера области, неиспользованное пространство может быть заполнено нулями. Такой механизм, в частности используется при создании неинициализированных данных процесса (BSS).
В сегменте типа INTERP хранится программный интерпретатор. Данный тип сегмента используется для программ, которым необходимо динамическое связывание. Суть динамического связывания заключается в том, что отдельные компоненты исполняемого файла (разделяемые объектные файлы) подключаются не на этапе компиляции, а на этапе запуска программы на выполнение. Имя файла, являющегося динамическим редактором связей, хранится в данном сегменте. В процессе запуска программы на выполнение ядро создает образ процесса, используя указанный редактор связей. Таким образом, первоначально в память загружается не исходная программа, а динамический редактор связей. На следующем этапе динамический редактор связей совместно с ядром UNIX создают полный образ исполняемого файла. Динамический редактор загружает необходимые разделяемые объектные файлы, имена которых хранятся в отдельных сегментах исходного исполняемого файла, и производит требуемое размещение и связывание. В заключение управление передается исходной программе.
Завершает файл таблица заголовков разделов или секций (section). Разделы (секций) определяют разделы файла, используемые для связывания с другими модулями в процессе компиляции или при динамическом связывании. Соответственно, заголовки содержат всю необходимую информацию для описания этих разделов. Как правило, разделы содержат более детальную информацию о сегментах. Так, например, сегмент кода может состоять из нескольких разделов, таких как хэш-таблица для хранения индексов используемых в программе символов, раздел инициализационного кода программы, таблица связывания, используемая динамическим редактором, а также раздел, содержащий собственно инструкции программы.
Следует обратить внимание на то, что в начале ELF-файла стоит сигнатура 'Ox7fELF' , по которой можно определить формат файла (массив байт, каждый из которых определяет некоторую общую характеристику файла: формат файла (ELF), номер версии, архитектуру системы (32-разрядная или 64-разрядная) и т. д.).