Системное программирование Линукс. Linux. Системное программирование. Вступление
Скачать 0.65 Mb.
|
Linux. Системное программирование. Вступление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Целевая аудитория и необходимые предпосылки . . . . . . . . . . . . . . . . . . . . . . 19 Краткое содержание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Версии, рассмотренные в книге . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Условные обозначения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Работа с примерами кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Глава 1. Введение и основополагающие концепции . . . . . . . . . . . . . . . . . . . . . . 27 Системное программирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Зачем изучать системное программирование . . . . . . . . . . . . . . . . . . . 28 Краеугольные камни системного программирования . . . . . . . . . . . . . 29 Системные вызовы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Библиотека C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Компилятор C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 API и ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 ABI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Стандарты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 История POSIX и SUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Стандарты языка C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Linux и стандарты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Стандарты и эта книга . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Концепции программирования в Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Файлы и файловая система . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Процессы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Пользователи и группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Права доступа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Оглавление 7 Сигналы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Межпроцессное взаимодействие . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Заголовки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Обработка ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Добро пожаловать в системное программирование . . . . . . . . . . . . . . . . . . . . 53 Глава 2. Файловый ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Открытие файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Системный вызов open() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Владельцы новых файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Права доступа новых файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Функция creat() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Возвращаемые значения и коды ошибок . . . . . . . . . . . . . . . . . . . . . . 61 Считывание с помощью read() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Возвращаемые значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Считывание всех байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Неблокирующее считывание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Другие значения ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Ограничения размера для read() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Запись с помощью write() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Случаи частичной записи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Режим дозаписи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Неблокирующая запись . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Другие коды ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Ограничения размера при использовании write() . . . . . . . . . . . . . . . . 68 Поведение write() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Синхронизированный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 fsync() и fdatasync() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 sync() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Флаг O_SYNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Флаги O_DSYNC и O_RSYNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Непосредственный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Закрытие файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Значения ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Позиционирование с помощью Iseek() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Поиск с выходом за пределы файла . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Ограничения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Позиционное чтение и запись . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Усечение файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 8 Оглавление Мультиплексный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 select() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Системный вызов poll() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Сравнение poll() и select() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Внутренняя организация ядра . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Виртуальная файловая система . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Страничный кэш . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Страничная отложенная запись . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Резюме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Глава 3. Буферизованный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Ввод-вывод с пользовательским буфером . . . . . . . . . . . . . . . . . . . . . . . . . . .100 Стандартный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .102 Открытие файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .103 Открытие потока данных с помощью файлового дескриптора . . . . . . . . . . . .104 Закрытие потоков данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .105 Считывание из потока данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106 Считывание одного символа в момент времени . . . . . . . . . . . . . . . . .106 Считывание целой строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .107 Считывание двоичных данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109 Запись в поток данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .110 Запись отдельного символа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .110 Запись строки символов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .111 Запись двоичных данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .111 Пример программы, в которой используется буферизованный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .112 Позиционирование в потоке данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .113 Сброс потока данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Ошибки и конец файла . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .116 Получение ассоциированного файлового дескриптора . . . . . . . . . . . . . . . . . .117 Управление буферизацией . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117 Безопасность программных потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .119 Блокировка файлов вручную . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .120 Неблокируемые потоковые операции . . . . . . . . . . . . . . . . . . . . . . . . .122 Недостатки стандартного ввода-вывода . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123 Резюме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123 Глава 4. Расширенный файловый ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . .125 Фрагментированный ввод-вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 Системные вызовы readv() и writev() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .126 Оглавление 9 Возвращаемые значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .127 Пример использования writev() . . . . . . . . . . . . . . . . . . . . . . . . . . . . .128 Пример использования readv() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .129 Реализация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .130 Опрос событий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .131 Создание нового экземпляра epoll . . . . . . . . . . . . . . . . . . . . . . . . . . .131 Управление epoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .132 Ожидание событий с помощью epoll . . . . . . . . . . . . . . . . . . . . . . . . . .135 Сравнение событий, запускаемых по фронту и по уровню сигнала . . .136 Отображение файлов в память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .137 mmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .137 Системный вызов munmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .142 Пример отображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .143 Преимущества mmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .144 Недостатки mmap() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .145 Изменение размеров отображения . . . . . . . . . . . . . . . . . . . . . . . . . . .145 Изменение защиты отображения . . . . . . . . . . . . . . . . . . . . . . . . . . . .147 Синхронизация файла с помощью отображения . . . . . . . . . . . . . . . . .147 Извещения об отображении . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .149 Извещения об обычном файловом вводе-выводе . . . . . . . . . . . . . . . . . . . . . .151 Системный вызов posix_fadvise() . . . . . . . . . . . . . . . . . . . . . . . . . . . .151 Системный вызов readahead() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .153 Рекомендации почти ничего не стоят . . . . . . . . . . . . . . . . . . . . . . . . .153 Синхронизированные, синхронные и асинхронные операции . . . . . . . . . . . . .154 Планировщики и производительность ввода-вывода . . . . . . . . . . . . . . . . . . .156 Адресация диска . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Жизненный цикл планировщика ввода-вывода . . . . . . . . . . . . . . . . . .157 Помощь при считывании . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .158 Выбор и настройка планировщика ввода-вывода . . . . . . . . . . . . . . . .162 Оптимизация производительности ввода-вывода . . . . . . . . . . . . . . . .163 Резюме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .170 Глава 5. Управление процессами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171 Программы, процессы и потоки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171 Идентификатор процесса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .172 Выделение идентификатора процесса . . . . . . . . . . . . . . . . . . . . . . . .173 Иерархия процессов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .173 pid_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .174 Получение идентификаторов процесса и родительского процесса . . .174 10 Оглавление Запуск нового процесса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .174 Семейство вызовов exec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175 Системные вызовы fork() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .179 Завершение процесса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .182 Другие способы завершения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .183 atexit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .184 on_exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .185 SIGCHLD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .185 Ожидание завершенных дочерних процессов . . . . . . . . . . . . . . . . . . . . . . . . .185 Ожидание определенного процесса . . . . . . . . . . . . . . . . . . . . . . . . . .188 Еще больше гибкости при ожидании . . . . . . . . . . . . . . . . . . . . . . . . .190 На сцену выходит BSD: wait3() и wait4() . . . . . . . . . . . . . . . . . . . . . . .192 Запуск и ожидание нового процесса . . . . . . . . . . . . . . . . . . . . . . . . . .193 Зомби . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .195 Пользователи и группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .196 Реальные, действительные и сохраненные идентификаторы пользователя и группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .197 Изменение реального или сохраненного идентификатора пользователя или группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .198 Изменение действительного идентификатора пользователя или группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .199 Изменение идентификаторов пользователя и группы согласно стилю BSD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .199 Изменение идентификаторов пользователя и группы согласно стилю HP-UX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .200 Действия с предпочтительными идентификаторами пользователя или группы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .201 Поддержка сохраненных пользовательских идентификаторов . . . . . .201 Получение идентификаторов пользователя и группы . . . . . . . . . . . . .201 Сессии и группы процессов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .202 Системные вызовы сессий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .204 Системные вызовы групп процессов . . . . . . . . . . . . . . . . . . . . . . . . . .205 Устаревшие функции для группы процессов . . . . . . . . . . . . . . . . . . . .206 Демоны . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .207 Резюме . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .209 Глава 6. Расширенное управление процессами . . . . . . . . . . . . . . . . . . . . . . . . .210 Планирование процессов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .210 Кванты времени . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .211 Процессы ввода-вывода против ограниченных процессором . . . . . . . .212 Оглавление 11 Приоритетное планирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .213 Completely Fair Scheduler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .213 Высвобождение ресурсов процессора . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .215 Приоритеты процессов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .216 nice() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .217 getpriority() и setpriority() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .218 Приоритеты ввода-вывода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .219 Привязка процессов к процессору . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .220 Системы реального времени . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .223 Мягкие и жесткие системы реального времени . . . . . . . . . . . . . . . . . .224 Задержка, колебание и временное ограничение . . . . . . . . . . . . . . . . .225 Поддержка реального времени в Linux . . . . . . . . . . . . . . . . . . . . . . . .226 Политики планирования и приоритеты в Linux . . . . . . . . . . . . . . . . . .226 Установка параметров планирования . . . . . . . . . . . . . . . . . . . . . . . . .230 sched_rr_get_interval() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .233 Предосторожности при работе с процессами реального времени . . . .235 Детерминизм . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .235 Лимиты ресурсов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .238 Лимиты по умолчанию . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .242 Установка и проверка лимитов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .243 Коды ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .244 |