Системное программирование Линукс. Linux. Системное программирование. Вступление
Скачать 0.65 Mb.
|
Глава 7. Поточность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .245 Бинарные модули, процессы и потоки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .245 Многопоточность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .246 Издержки многопоточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .248 Альтернативы многопоточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . .248 Поточные модели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .249 Поточность на уровне пользователя . . . . . . . . . . . . . . . . . . . . . . . . .249 Комбинированная поточность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .250 Сопрограммы и фиберы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .251 Шаблоны поточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .251 Поток на соединение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .251 Поток, управляемый событием . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .252 Конкурентность, параллелизм и гонки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .253 Синхронизация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .256 Мьютексы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257 Взаимные блокировки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .258 Р-потоки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .260 12 Оглавление Реализация поточности в Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261 API для работы с Р-потоками . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261 Связывание Р-потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .262 Создание потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .262 Идентификаторы потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .264 Завершение потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .265 Самозавершение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .265 Завершение других потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .266 Присоединение и отсоединение потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . .268 Присоединение потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .268 Отсоединение потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .269 Пример поточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .269 Мьютексы Р-потоков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .270 Инициализация мьютексов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .270 Запирание мьютексов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .271 Отпирание мьютексов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .271 Пример использования мьютексов . . . . . . . . . . . . . . . . . . . . . . . . . . .272 Дальнейшее изучение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .273 Глава 8. Управление файлами и каталогами . . . . . . . . . . . . . . . . . . . . . . . . . . .275 Файлы и их метаданные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .275 Семейство stat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .276 Разрешения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .280 Владение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .281 Расширенные атрибуты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284 Перечисление расширенных атрибутов файла . . . . . . . . . . . . . . . . . .289 Каталоги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .292 Текущий рабочий каталог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .293 Создание каталогов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .298 Удаление каталогов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .299 Чтение содержимого каталога . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .300 Ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .303 Жесткие ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .304 Символические ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .305 Удаление ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .307 Копирование и перемещение файлов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .308 Копирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .308 Перемещение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .309 Узлы устройств . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .311 Оглавление 13 Специальные узлы устройств . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .311 Генератор случайных чисел . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .312 Внеполосное взаимодействие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .312 Отслеживание файловых событий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .314 Инициализация inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .315 Стражи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .316 События inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .317 Расширенные события отслеживания . . . . . . . . . . . . . . . . . . . . . . . . .321 Удаление стража inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .321 Получение размера очереди событий . . . . . . . . . . . . . . . . . . . . . . . . .322 Уничтожение экземпляра inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . .323 Глава 9. Управление памятью . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .324 Адресное пространство процесса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .324 Страницы и их подкачка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .324 Области памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .326 Выделение динамической памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .327 Выделение массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .329 Изменение размера выделенных областей . . . . . . . . . . . . . . . . . . . . .331 Освобождение динамической памяти . . . . . . . . . . . . . . . . . . . . . . . . .332 Выравнивание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .335 Управление сегментом данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .339 Анонимные отображения в памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .340 Создание анонимных отображений в памяти . . . . . . . . . . . . . . . . . . .342 Отображение /dev/zero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .344 Расширенное выделение памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .345 Отладка при операциях выделения памяти . . . . . . . . . . . . . . . . . . . . . . . . . .348 Выделение памяти на основе стека . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .349 Дублирование строк в стеке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .351 Массивы переменной длины . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .352 Выбор механизма выделения памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .353 Управление памятью . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .354 Установка байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .354 Сравнение байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .355 Перемещение байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .356 Поиск байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .357 Перещелкивание байтов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .358 Блокировка памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .358 Блокировка части адресного пространства . . . . . . . . . . . . . . . . . . . . .359 14 Оглавление Блокировка всего адресного пространства . . . . . . . . . . . . . . . . . . . . .360 Разблокировка памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .361 Лимиты блокировки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .362 Находится ли страница в физической памяти . . . . . . . . . . . . . . . . . . .362 Уступающее выделение памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .363 Глава 10. Сигналы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .365 Концепции, связанные с сигналами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .366 Идентификаторы сигналов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .366 Сигналы, поддерживаемые в Linux . . . . . . . . . . . . . . . . . . . . . . . . . . .367 Основы управления сигналами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .372 Ожидание любого сигнала . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .373 Примеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .374 Выполнение и наследование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .376 Сопоставление номеров сигналов и строк . . . . . . . . . . . . . . . . . . . . .377 Отправка сигнала . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .378 Права доступа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .378 Примеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .379 Отправка сигнала самому себе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .379 Отправка сигнала целой группе процессов . . . . . . . . . . . . . . . . . . . . .380 Реентерабельность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .380 Наборы сигналов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .382 Блокировка сигналов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .384 Получение сигналов, ожидающих обработки . . . . . . . . . . . . . . . . . . .385 Ожидание набора сигналов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385 Расширенное управление сигналами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385 Структура siginfo_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .388 Удивительный мир si_code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .389 Отправка сигнала с полезной нагрузкой . . . . . . . . . . . . . . . . . . . . . . . . . . . .391 Изъян в UNIX? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .393 Глава 11. Время . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .394 Структуры данных, связанные с представлением времени . . . . . . . . . . . . . . .397 Оригинальное представление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .397 А теперь — с микросекундной точностью! . . . . . . . . . . . . . . . . . . . . .397 И еще лучше: наносекундная точность . . . . . . . . . . . . . . . . . . . . . . . .398 Разбиение времени . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .398 Тип для процессного времени . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .399 Оглавление 15 Часы POSIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .400 Получение текущего времени суток . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .401 Более удобный интерфейс . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .402 Продвинутый интерфейс . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .403 Получение процессного времени . . . . . . . . . . . . . . . . . . . . . . . . . . . . Установка текущего времени суток . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .405 Установка времени с заданной точностью . . . . . . . . . . . . . . . . . . . . .405 Продвинутый интерфейс для установки времени . . . . . . . . . . . . . . . .406 Эксперименты с временем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .406 Настройка системных часов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .408 Засыпание и ожидание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .411 Засыпание с микросекундной точностью . . . . . . . . . . . . . . . . . . . . . .412 Засыпание с наносекундной точностью . . . . . . . . . . . . . . . . . . . . . . .413 Продвинутая работа со спящим режимом . . . . . . . . . . . . . . . . . . . . . .415 Переносимый способ засыпания . . . . . . . . . . . . . . . . . . . . . . . . . . . . .416 Превышение пределов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .417 Альтернативы засыпанию . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Таймеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Простые варианты сигнализации . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Интервальные таймеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .419 Функции для расширенной работы с таймерами . . . . . . . . . . . . . . . . .421 Приложение A. Расширения GCC для языка C . . . . . . . . . . . . . . . . . . . . . . . . .427 GNU C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .427 Встраиваемые функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .428 Подавление встраивания . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .429 Чистые функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .429 Постоянные функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .430 Невозвращаемые функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .430 Функции, выделяющие память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .430 Принудительная проверка возвращаемого значения вызывающей стороной . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .431 Как пометить функцию как устаревшую . . . . . . . . . . . . . . . . . . . . . . . . . . . . .431 Как пометить функцию как используемую . . . . . . . . . . . . . . . . . . . . . . . . . . .431 Как пометить функции или параметры как неиспользуемые . . . . . . . . . . . . . .432 Упаковка структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .432 Увеличение границы выравнивания переменной . . . . . . . . . . . . . . . . . . . . . .433 Помещение глобальных переменных в регистр . . . . . . . . . . . . . . . . . . . . . . .434 16 Оглавление Аннотирование ветвей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .434 Получение типа выражения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .435 Получение границы выравнивания типа . . . . . . . . . . . . . . . . . . . . . . . . . . . .436 Смещение члена внутри структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .437 Получение возвращаемого адреса функции . . . . . . . . . . . . . . . . . . . . . . . . . .437 Диапазоны оператора case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .438 Арифметика указателей типа void и указателей на функции . . . . . . . . . . . . . .438 Более переносимо и красиво . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .439 Данная книга рассказывает о системном программировании в Linux. Системное программирование — это практика написания системного ПО, низкоуровневый код которого взаимодействует непосредственно с ядром и основными системными библиотеками. Иными словами, речь далее пойдет в основном о системных вызовах Linux и низкоуровневых функциях, в частности тех, которые определены в биб лиотеке C. Есть немало пособий, посвященных системному программированию для UNIX систем, но вы почти не найдете таких, которые рассматривают данную тему доста точно подробно и фокусируются именно на Linux. Еще меньше подобных книг учитывают новейшие релизы Linux и продвинутые интерфейсы, ориентированные исключительно на Linux. Эта книга не только лишена всех перечисленных недос татков, но и обладает важным достоинством: дело в том, что я написал массу кода для Linux, как для ядра, так и для системных программ, расположенных непосред ственно «над ядром». На самом деле я реализовал на практике ряд системных вызовов и других функций, описанных далее. Соответственно книга содержит богатый материал, рассказывая не только о том, как должны работать системные интерфейсы, но и о том, как они действительно работают и как вы сможете использовать их с максимальной эффективностью. Таким образом, данная книга одновременно является и руководством по системному программированию для Linux, и справочным пособием, описывающим системные вызовы Linux, и под робным повествованием о том, как создавать более интеллектуальный и быстрый код. Текст написан простым, доступным языком. Независимо от того, является ли создание системного кода вашей основной работой, эта книга научит полезным приемам, которые помогут вам стать понастоящему высокопрофессиональным программистом. Целевая аудитория и необходимые предпосылки Пособие предназначается для читателей, знакомых с программированием на язы ке C и с применяемой в Linux экосистемой программирования. Не обязательно быть экспертом в этих темах, но в них нужно как минимум ориентироваться. Если вам не приходилось работать с текстовыми редакторами для UNIX — наиболее извест ными и хорошо себя зарекомендовавшими являются Emacs и vim , — поэксперимен тируйте с ними. Кроме того, следует в общих чертах представлять работу с gcc , gdb , 20 make и др. Существует еще множество инструментов и практикумов по программи рованию для Linux; в приложении Б в конце перечислены некоторые полезные источники. Кроме того, я ожидаю от читателя определенных знаний в области системного программирования для Linux и UNIX. Эта книга начинается с самых основ, ее темы постепенно усложняются вплоть до обсуждения наиболее продвинутых интерфей сов и приемов оптимизации. Надеюсь, пособие понравится читателям с самыми разными уровнями подготовки, научит их чемуто ценному и новому. Пока писал книгу, я сам узнал немало интересного. У меня были определенные предположения об убеждениях и мотивации чита теля. Инженеры, желающие (более качественно) программировать на системном уровне, являются основной целевой аудиторией, но книга будет интересна и про граммистам, которые специализируются на высокоуровневом коде и желают при обрести более солидные базовые знания. Любознательным хакерам пособие также понравится, утолит их жажду нового. Книга задумывалась так, чтобы заинтересо вать большинство программистов. В любом случае, независимо от ваших мотивов, надеюсь, что чтение окажется для вас интересным! Краткое содержание Книга разделена на 11 глав и 2 приложения. |