Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Системное программирование

Покупка
Основная коллекция
Артикул: 714341.01.99
Приведены сведения о системном и промежуточном программном обеспечении, даны основные понятия и определения системного программирования, изложены вопросы разработки программ, использующих функции, реализующие системные вызовы ядром операционных систем семейства Linux. Особое внимание уделено средствам автоматической сборки программного обеспечения из исходных текстов, а также снижению количества ошибок в системных программах за счет использования инструментов статического и динамического анализа программного кода. Предназначено студентам направления 09.03.04 «Программная инженерия» всех форм обучения.
Кузнецов, А.С. Системное программирование : учеб. пособие / А.С. Кузнецов, И.А. Якимов, П.В. Пересунько. - Красноярск : Сиб. федер. ун-т 2018. - 170с. - ISBN 978-5-7638-3885-5. - Текст : электронный. - URL: https://znanium.com/catalog/product/1032183 (дата обращения: 20.05.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Министерство науки и высшего образования Российской Федерации
Сибирский федеральный университет

А. С. Кузнецов, И. А. Якимов, П. В. Пересунько

СИСТЕМНОЕ  ПРОГРАММИРОВАНИЕ

Учебное пособие 

Красноярск 
СФУ 
2018

УДК 004.45(07)
ББК 32.973.1я73
К891

Р е ц е н з е н т ы: 
Е. П. Моргунов, кандидат технических наук, доцент, доцент кафедры 
информатики и вычислительной техники Сибирского государственного 
университета науки и технологий им. акад. М. Ф. Решетнева;
А. М. Епихин, кандидат физико-математических наук, доцент, старший научный сотрудник СКТБ «Наука» ИВТ СО РАН

Кузнецов, А. С.
К891 
 
Системное программирование : учеб. пособие / А. С. Кузнецов, И. А. Якимов, П. В. Пересунько. – Красноярск : Сиб. федер. 
ун-т, 2018. – 170 с.
ISBN 978-5-7638-3885-5

Приведены сведения о системном и промежуточном программном обеспечении, даны основные понятия и определения системного программирования, 
изложены вопросы разработки программ, использующих функции, реализующие системные вызовы ядром операционных систем семейства Linux.
Особое внимание уделено средствам автоматической сборки программного 
обеспечения из исходных текстов, а также снижению количества ошибок в системных программах за счет использования инструментов статического и динамического анализа программного кода.
Предназначено студентам направления 09.03.04 «Программная инженерия» всех форм обучения.

Электронный вариант издания см.: 
УДК 004.45(07)

http://catalog.sfu-kras.ru 
ББК 32.973.1я73

ISBN 978-5-7638-3885-5 
© Сибирский федеральный
университет, 2018

ОГЛАВЛЕНИЕ

Список сокращений ...................................................................................5
Введение .......................................................................................................6
Рекомендации по использованию литературы ....................................8
1. Введение в системное программирование ........................................9
1.1. Классификация программного обеспечения .................................9
1.2. Модульная разработка программ ................................................ 11
1.3. Обязанности системных программистов ................................... 14
Контрольные вопросы и задания ....................................................... 15
2. Многозадачность в операционных системах ................................ 16
2.1. Многозадачность: процессы........................................................ 16
2.2. Создание процессов ..................................................................... 18
2.3. Завершение процессов ................................................................. 21
2.4. Многозадачность: потоки ............................................................ 26
2.5. Создание потока ........................................................................... 27
2.6. Отмена потока ............................................................................... 34
2.7. Проблема синхронизации потоков ............................................. 37
2.8. Состояние гонки ........................................................................... 38
2.9. Исключающие семафоры, или мьютексы .................................. 39
2.10. Потоковые семафоры ................................................................. 43
2.11. Условные переменные ................................................................ 47
Контрольные вопросы и задания ....................................................... 51
3. Инструментарий анализа кода системных программ ................. 54
3.1. Проблема анализа программного кода ....................................... 54
3.2. Статический анализ программного кода .................................... 55
3.3. Динамический анализ программного кода ................................ 62
Контрольные вопросы и задания ....................................................... 64
4. Управление памятью ......................................................................... 65
4.1. Адресное пространство процесса ............................................... 65
4.2. Распределение динамической памяти ........................................ 68
4.3. Освобождение динамической памяти ........................................ 72
4.4. Распределение памяти на основе стека ...................................... 75
Контрольные вопросы и задания ....................................................... 79
5. Автоматизация сборки программного кода .................................. 81
5.1. Проблема сборки программного кода ........................................ 81

5.2. Цели, зависимости и команды..................................................... 81
5.3. Автосборка программного кода .................................................. 88
Контрольные вопросы и задания ....................................................... 96
6. Подсистема ввода-вывода ................................................................. 98
6.1. Файлы и файловые системы ........................................................ 98
6.2. Файловые операции ................................................................... 101
6.3. Операции над каталогами .......................................................... 111
6.4. Принципы и механизмы взаимодействия процессов .............. 114
6.5. Совместно используемая память .............................................. 115
6.6. Семафоры .................................................................................... 119
6.7. Конвейеры ................................................................................... 123
6.8. FIFO-файлы ................................................................................ 128
6.9. Сокеты ......................................................................................... 130
Контрольные вопросы и задания ..................................................... 146
7. Архитектуры вычислительных машин и систем.   
Прочие системные вызовы ............................................................. 149
7.1. Организация вычислительной системы ................................... 149
7.2. Системные вызовы ..................................................................... 152
7.3. Очистка дисковых буферов ....................................................... 153
7.4. Высокоточная пауза .................................................................... 154
7.5. Системные часы ......................................................................... 155
7.6. Интервальные таймеры .............................................................. 157
7.7. Лимиты ресурсов ........................................................................ 158
7.8. Статистика процессов ................................................................ 160
7.9. Системная статистика ................................................................ 161
7.10. Информация о системе ............................................................ 162
7.11. Передача файлов ....................................................................... 163
7.12. Блокирование физической памяти .......................................... 164
Контрольные вопросы и задания ..................................................... 166
Заключение ............................................................................................. 168
Библиографический  список ............................................................... 169

СПИСОК  СОКРАЩЕНИЙ

ПО – программное обеспечение.
ОС – операционная система, например Debian, Android, Windows 10.
UNIX – семейство переносимых, многозадачных и многопользовательских операционных систем.
PID, или Process Identifier – идентификатор процесса.
PPID, или Parent Process Identifier – идентификатор родительского процесса.
PATH – переменная окружения, добавляемая к короткому имени 
файла при выполнении некоторых файловых операций.
API, или Application Programming Interface – прикладной программный интерфейс.
POSIX, или Portable Operating System Interface – переносимый 
интерфейс операционных систем. Набор стандартов, описывающих 
интерфейсы между ОС и прикладной программой (системный API), 
библиотеку языка C и набор приложений и их интерфейсов, который 
разработан для обеспечения совместимости различных UNIX-подобных 
операционных систем и переносимости прикладных программ на уровне исходного кода, но может быть использован и для не-UNIX систем.
ВАП – виртуальное адресное пространство процесса.
MMU – блок управления  памятью процессора.
ФС – файловая система.
FIFO – стратегия обслуживания объектов ОС по принципу «Первый пришел – первый обслужен».
Unix Epoch, или «эпоха» – начальное значение времени для ОС 
UNIX (01.01.1970, 00:00:00).

ВВЕДЕНИЕ

Область системного программирования возникла как результат 
усилий многих программистов, создавших множество практически полезных методов, моделей и программ. Потребность в них остро ощущается в стремительно развивающейся индустрии разработки программного обеспечения.
В учебном плане образовательной программы 09.03.04 «Программная инженерия» СФУ дисциплина «Системное программирование» обеспечивает освоение двух компетенций, среди которых одна 
профессиональная – ПК-2 «Владение навыками использования операционных систем, сетевых технологий, средств разработки программного интерфейса, применения языков и методов формальных спецификаций, систем управления базами данных». Таким образом, от студентов 
требуется получение навыков использования и построения компонент 
операционных систем и прикладных программных интерфейсов на примере какой-либо из известных современных ОС. Следует рассмотреть 
практические вопросы системного программирования, охватывающие 
основные функциональные возможности операционных систем семейства Linux. Эта система выбрана по многим причинам. Приведем некоторые из них.
Во-первых, очень развитые средства командной строки. Именно путем подачи команд совершается большинство действий в UNIXподобных ОС.
Во-вторых, многие программы в Linux распространяются в исходных текстах и часто собираются уже на вычислительной системе 
конечного пользователя, что делает, например, компилятор языка C 
обязательной частью почти любого дистрибутива ОС Linux, которая является в дальнейшем основным инструментом программирования для 
читателей.
Учебное пособие состоит из семи глав, посвященных различным 
аспектам разработки системного и промежуточного программного обеспечения.
В первой главе представлена классификация системного программного обеспечения, уделено внимание вопросам преобразования 

Введение

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

РЕКОМЕНДАЦИИ  ПО  ИСПОЛЬЗОВАНИЮ  
ЛИТЕРАТУРЫ

Главными читателями учебного пособия должны стать разработчики системного и промежуточного программного обеспечения, обладающие некоторым опытом развертывания и использования ОС. Тем не 
менее рекомендуется предварительное знакомство с пользовательскими 
аспектами работы в ОС Linux, описанными в книге Г. В. Курячего [1] 
или К. Петцке [2].
Материал, относящийся ко второй, четвертой и шестой главам, 
требует знания классификации и подходов к структурированию операционных систем, а также их основных подсистем, что подробно описано в учебном пособии [3].
В параграфе 6.9 упоминается сетевой стек протоколов TCP/IP. 
За получением дополнительных сведений об этом стеке рекомендуется 
обратиться к [4].
Более подробно концепции и средства системного программирования в Linux изложены в [5], к чтению этой книги можно перейти после 
ознакомления с текстом настоящего учебного пособия, которое можно 
рассматривать как введение в проблематику системного программирования в Linux.

1.  ВВЕДЕНИЕ  В  СИСТЕМНОЕ  ПРОГРАММИРОВАНИЕ

1.1. Классификация программного обеспечения

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

1.  Введение  в  системное  программирование

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

1.2. Модульная разработка программ

Система (среда) программирования – система, образуемая языком программирования, компилятором или интерпретатором программ, 
представленных на этом языке, соответствующей документацией, а также вспомогательными средствами для подготовки программ к форме, 
пригодной для выполнения.
При разработке программ, а тем более – сложных, используется 
принцип модульности, разбиения сложной программы на составные части, каждая из которых может подготавливаться отдельно. Модульность 
является основным инструментом структурирования программного 
обеспечения, облегчающим его разработку, отладку и сопровождение.

1.2. Модульная разработка программ

Программный модуль – программа (или функционально завершенный фрагмент программы), предназначенная(ый) для хранения, 
трансляции, объединения с другими программными модулями и загрузки в оперативную память. 
При выборе модульной структуры должны учитываться следующие основные соображения: 
• функциональность (модуль должен выполнять законченную 
функцию);
• слабая связность (модуль должен иметь минимум связей с другими модулями, связь через глобальные переменные и области памяти 
нежелательна);
• специфицируемость (входные и выходные параметры модуля 
должны четко формулироваться).
Программа пишется в виде исходного модуля.
Исходный модуль – программный модуль на исходном языке, обрабатываемый транслятором и представляемый для него как целое, достаточное для проведения трансляции.
Следующим этапом является трансляция.
Трансляция – преобразование программы, представленной на одном языке, в другое ее представление. Под ним, как правило, понимают 
другой язык программирования. Иначе говоря, мы должны получить 
программу, равносильную по смыслу первой, или, как еще говорят, се
1.  Введение  в  системное  программирование

мантически эквивалентную ей. Однако, как правило, выходным языком 
транслятора является машинный язык целевой вычислительной машины, т. е. тот, на котором программа будет выполняться.
Машинный язык – язык программирования, предназначенный для 
представления программы в форме, позволяющей выполнять ее непосредственно на вычислительной машине.
Трансляторы – общее название для программ, осуществляющих 
трансляцию. Их иногда подразделяют на компиляторы и интерпретаторы – в зависимости от исходного языка программы, которую они обрабатывают. Компиляторы обычно работают с языками высокого уровня. 
Ассемблеры, как правило, работают с языками ассемблера.
Язык ассемблера – язык программирования, который представляет собой символьную форму машинного языка с рядом возможностей, 
характерных для языка высокого уровня (обычно включает в себя макросредства). 
Язык высокого уровня – как известно, язык программирования, 
понятия и структура которого удобны для восприятия человеком.
Объектный модуль – программный модуль, получаемый в результате компиляции исходного модуля. 
Поскольку результатом компиляции является модуль на языке, 
близком к машинному, в нем уже не остается признаков того языка, на 
каком был написан программный модуль. Это дает принципиальную 
возможность создавать программы из модулей, написанных на разных 
языках. Специфика исходного языка, однако, может сказываться на физическом представлении базовых типов данных, способах обращения 
к процедурам/функциям и т. п. В целях совместимости разноязыковых 
модулей должны выдерживаться общие соглашения. Большая часть 
объектного модуля – это команды и данные машинного языка именно 
в той форме, в какой они будут существовать во время выполнения программы. Однако программа в общем случае состоит из многих модулей. 
Поскольку компилятор обрабатывает только один конкретный модуль, 
он не может должным образом обработать те части этого модуля, в которых производятся обращения к данным или процедурам, определенным 
в другом модуле. Такие обращения называются внешними ссылками. 
Те места в объектном модуле, где содержатся внешние ссылки, преобразуются в некоторую промежуточную форму, подлежащую дальнейшей