Программирование для Linux. Профессиональный подход.
- Об авторах. ⇢
- О научных консультантах.
- Благодарности.
- Введение. ⇢
- GNU и Linux.
- Общая лицензия GNU.
- Для кого предназначена эта книга.
- Соглашения, принятые в книге.
- Часть I. Сложные вопросы программирования в среде UNIX/Linux. ⇢
- Глава 1. Начало. ⇢
- 1.1. Редактор Emacs. ⇢
- Несколько слов о Emacs.
- 1.1.1. Открытие исходного файла C/C++ ⇢
- 1.1.2. Автоматическое форматирование. ⇢
- 1.1.3. Синтаксические выделения. ⇢
- 1.2. Компиляторы GCC. ⇢
- Листинг 1.1. (main.c) Исходный файл на языке С.
- Листинг 1.2. (reciprocal.cpp) Исходный файл на языке C++
- Листинг 1.3. (reciprocal.hpp) Файл заголовков.
- 1.2.1. Компиляция одного исходного файла. ⇢
- 1.2.2. Компоновка объектных файлов. ⇢
- 1.3. Автоматизация процесса с помощью GNU-утилиты make. ⇢
- 1.4. GNU-отладчик gdb. ⇢
- 1.4.1. Компиляция с включением отладочной информации. ⇢
- 1.4.2. Запуск отладчика. ⇢
- 1.5. Поиск дополнительной информации. ⇢
- 1.5.1. Интерактивная документация. ⇢
- 1.5.2. Система Info. ⇢
- 1.5.3. Файлы заголовков. ⇢
- 1.5.4. Исходные тексты. ⇢
- Глава 2. Написание качественных программ для среды GNU/Linux. ⇢
- 2.1. Взаимодействие со средой выполнения. ⇢
- 2.1.1. Список аргументов. ⇢
- Листинг 2.1. (arglist.c) Использование параметров argc и argv.
- 2.1.2. Соглашения по работе с командной строкой в GNU/Linux. ⇢
- 2.1.3. Функция getopt_long(). ⇢
- Листинг 2.2. (getopt_long.c) Использование функции getopt_long().
- 2.1.4. Стандартный ввод-вывод. ⇢
- 2.1.5. Коды завершения программы. ⇢
- 2.1.6. Среда выполнения. ⇢
- Листинг 2.3. (print-env.c) Вывод переменных среды.
- Листинг 2.4. (client.с) Часть сетевой клиентской программы.
- 2.1.7. Временные файлы. ⇢
- Функция mkstemp().
- Листинг 2.5. (temp_file.c) Использование функции mkstemp().
- Функция tmpfile().
- 2.2. Защита от ошибок. ⇢
- 2.2.1. Макрос assert(). ⇢
- 2.2.2. Ошибки системных вызовов. ⇢
- 2.2.3. Коды ошибок системных вызовов. ⇢
- 2.2.4. Ошибки выделения ресурсов. ⇢
- Листинг 2.6. (readfile.c) Освобождение ресурсов при возникновении аварийных ситуаций.
- 2.3. Создание и использование библиотек. ⇢
- 2.3.1. Архивы. ⇢
- Листинг 2.7. (test.c) Первый исходный файл.
- Листинг 2.8. (app.c) Второй исходный файл.
- 2.3.2. Совместно используемые библиотеки. ⇢
- Позиционно-независимый код.
- Переменная LD_LIBRARY_PATH.
- 2.3.3. Стандартные библиотеки. ⇢
- 2.3.4. Зависимости между библиотеками. ⇢
- Листинг 2.9. (tifftest.c) Применение библиотеки libtiff.
- 2.3.5. Преимущества и недостатки библиотек. ⇢
- 2.3.6. Динамическая загрузка и выгрузка. ⇢
- Глава 3. Процессы. ⇢
- 3.1. Знакомство с процессами. ⇢
- 3.1.1. Идентификаторы процессов. ⇢
- Листинг 3.1. (print-pid.c) Вывод идентификатора процесса.
- 3.1.2. Получение списка активных процессов. ⇢
- Форматы вывода команды ps.
- 3.1.3. Уничтожение процесса. ⇢
- 3.2. Создание процессов. ⇢
- 3.2.1. Функция system(). ⇢
- Листинг 3.2. (system.c) Использование функции system().
- 3.2.2. Функции fork() и exec(). ⇢
- Вызов функции fork().
- Листинг 3.3. (fork.c) Ветвление программы с помощью функции fork().
- Семейство функций exec().
- Совместное использование функций fork() и exec().
- Листинг 3.4. (fork-exec.с) Совместное использование функций fork() и exec().
- 3.2.3. Планирование процессов. ⇢
- 3.3. Сигналы. ⇢
- Листинг 3.5. (sigusr1.c) Корректное применение обработчика сигнала.
- 3.4. Завершение процесса. ⇢
- 3.4.1. Ожидание завершения процесса. ⇢
- 3.4.2. Системные вызовы wait(). ⇢
- 3.4.3. Процессы-зомби. ⇢
- Листинг 3.6. (zombie.c) Создание процесса-зомби.
- 3.4.4. Асинхронное удаление дочерних процессов. ⇢
- Листинг 3.7. (sigchld.c) Удаление дочерних процессов в обработчике сигнала SIGCHLD.
- Глава 4. Потоки. ⇢
- 4.1. Создание потока. ⇢
- Листинг 4.1. (thread-create.c) Создание потока.
- 4.1.1. Передача данных потоку. ⇢
- Листинг 4.2. (thread-create2.c) Создание двух потоков.
- 4.1.2. Ожидание завершения потоков. ⇢
- Листинг 4.3. Исправленная функция main() из файла thread-create.c.
- 4.1.3. Значения, возвращаемые потоками. ⇢
- Листинг 4.4. (primes.с) Вычисление простых чисел в потоке.
- 4.1.4. Подробнее об идентификаторах потоков. ⇢
- 4.1.5. Атрибуты потоков. ⇢
- Листинг 4.5. (detached.c) Шаблон программы, создающей отсоединенный поток.
- 4.2. Отмена потока. ⇢
- 4.2.1. Синхронные и асинхронные потоки. ⇢
- 4.2.2. Неотменяемые потоки. ⇢
- Листинг 4.6. (critical_section.c) Защита банковской транзакции с помощью критической секции.
- 4.2.3. Когда необходимо отменять поток. ⇢
- 4.3. Потоковые данные. ⇢
- Листинг 4.7. (tsd.c) Создание отдельного журнального файла для каждого потока с помощью области потоковых данных.
- 4.3.1. Обработчики очистки. ⇢
- Листинг 4.8. (cleanup.c) Фрагмент программы, содержащий обработчик очистки потока.
- 4.3.2. Очистка потоковых данных в C++ ⇢
- Листинг 4.9. (cxx-exit.cpp) Безопасное завершение потока в C++
- 4.4. Синхронизация потоков и критические секции. ⇢
- 4.4.1. Состояние гонки. ⇢
- Листинг 4.10. (job-queue1.c) Потоковая функция, работающая с очередью заданий.
- 4.4.2. Исключающие семафоры. ⇢
- Листинг 4.11. (job-queue2.c) Работа с очередью заданий, защищенной исключающим семафором.
- 4.4.3. Взаимоблокировки исключающих семафоров. ⇢
- 4.4.4. Неблокирующие проверки исключающих семафоров. ⇢
- 4.4.5. Обычные потоковые семафоры. ⇢
- Листинг 4.12. (job-queue3.c) Работа с очередью заданий с применением семафора.
- 4.4.6. Сигнальные (условные) переменные. ⇢
- Листинг 4.15. (spin-condvar.c) Простейшая реализация сигнальной переменной.
- Листинг 4.14. (condvar.c) Управление работой потока с помощью сигнальной переменной.
- 4.4.7. Взаимоблокировки двух и более потоков. ⇢
- 4.5. Реализация потоков в Linux. ⇢
- Листинг 4.15. (thread-pid.c) Вывод идентификаторов потоков.
- Сообщения интерпретатора команд» касающиеся управления заданиями.
- 4.5.1. Обработка сигналов. ⇢
- 4.5.2. Системный вызов clone(). ⇢
- 4.6. Сравнение процессов и потоков. ⇢
- Глава 5. Взаимодействие процессов. ⇢
- 5.1. Совместно используемая память. ⇢
- 5.1.1. Быстрое локальное взаимодействие. ⇢
- 5.1.2. Модель памяти. ⇢
- 5.1.3. Выделение сегментов памяти. ⇢
- 5.1.4. Подключение и отключение сегментов. ⇢
- 5.1.5. Контроль и освобождение совместно используемой памяти. ⇢
- 5.1.6. Пример программы. ⇢
- Листинг 5.1. (shm.c) Пример совместного использования памяти.
- 5.1.7. Отладка. ⇢
- 5.1.8. Проблема выбора. ⇢
- 5.2. Семафоры для процессов. ⇢
- 5.2.1. Выделение и освобождение семафоров. ⇢
- Листинг 5.2. (sem_all_deall.c) Выделение и освобождение двоичного семафора.
- 5.2.2. Инициализация семафоров. ⇢
- Листинг 5.3. (sem_init.c) Инициализация двоичного семафора.
- 5.2.3. Операции ожидания и установки. ⇢
- Листинг 5.4. (sem_pv.c) Ожидание и установка двоичного семафора.
- 5.2.4. Отладка семафоров. ⇢
- 5.3. Отображение файлов в памяти. ⇢
- 5.3.1. Отображение в памяти обычного файла. ⇢
- 5.3.2. Примеры программ. ⇢
- Листинг 5.5. (mmap-write.c) Запись случайного числа в файл, отображаемый в памяти.
- Листинг 5.6. (mmap-read.c) Чтение случайного числа из файла, отображаемого в памяти.
- 5.3.3. Совместный доступ к файлу. ⇢
- 5.3.4. Частные отображаемые области. ⇢
- 5.3.5. Применения функции mmap(). ⇢
- 5.4. Каналы. ⇢
- 5.4.1. Создание каналов. ⇢
- 5.4.2. Взаимодействие родительского и дочернего процессов. ⇢
- Листинг 5.7. (pipe.c) Общение с дочерним процессом посредством канала.
- 5.4.3. Перенаправление стандартных потоков ввода, вывода и ошибок. ⇢
- Листинг 5.8. (dup2.c) Перенаправление выходного потока канала с помощью функции dup2().
- 5.4.4. Функции popen() и pclose(). ⇢
- Листинг 5.9. (popen.c) Использование функций popen() и pclose().
- 5.4.5. Каналы FIFO. ⇢
- Создание FIFO-файла.
- Доступ к FIFO-файлу.
- Отличия от именованных каналов в Windows.
- 5.5. Сокеты. ⇢
- 5.5.1. Концепции сокетов. ⇢
- 5.5.2. Системные вызовы. ⇢
- Создание и уничтожение сокетов.
- Вызов функции connect().
- Передача данных.
- 5.5.3. Серверы. ⇢
- 5.5.4. Локальные сокеты. ⇢
- 5.5.5. Примеры программ, работающих с локальными сокетами. ⇢
- Листинг 5.10. (socket-server.c) Сервер локального сокета.
- Листинг 5.11. (socket-client.c) Клиент локального сокета.
- 5.5.6. Internet-сокеты. ⇢
- DNS-имена.
- Листинг 5.12. (socket-inet.c) Чтение страницы с Web-сервера.
- Стандартные номера портов.
- 5.5.7. Пары сокетов. ⇢
- Часть II. Секреты Linux. ⇢
- Глава 6. Устройства. ⇢
- Будьте осторожны при доступе к устройствам!
- 6.1. Типы устройств. ⇢
- Опасность доступа к блочному устройству.
- 6.2. Номера устройств. ⇢
- 6.3. Файловые ссылки на устройства. ⇢
- 6.3.1. Каталог /dev. ⇢
- 6.3.2. Доступ к устройству путем открытия файла. ⇢
- 6.4. Аппаратные устройства. ⇢
- 6.5. Специальные устройства. ⇢
- 6.5.1. /dev/null. ⇢
- 6.5.2. /dev/zero. ⇢
- 6.5.3. /dev/full. ⇢
- 6.5.4. Устройства генерирования случайных чисел. ⇢
- Листинг 6.1. (random_number.c) Генерирование случайного числа с помощью файла /dev/random.
- 6.5.5. Устройства обратной связи. ⇢
- 6.6. Псевдотерминалы. ⇢
- 6.6.1. Пример работы с псевдотерминалом. ⇢
- 6.7. Функция ioctl(). ⇢
- Листинг 6.2. (cdrom-eject.c) Извлечение компакт-диска из дисковода.
- Глава 7. Файловая система /proc. ⇢
- 7.1. Извлечение информации из файловой системы /proc. ⇢
- Листинг 7.1. (clock-speed.c) Определение частоты процессора путем анализа файла /proc/cpuinfo.
- 7.2. Каталоги процессов. ⇢
- 7.2.1. Файл /proc/self. ⇢
- Листинг 7.2. (get-pid.c) Получение идентификатора процесса из файла /proc/self.
- 7.2.2. Список аргументов процесса. ⇢
- Листинг 7.3. (print-arg-list.c) Отображение списка аргументов указанного процесса.
- 7.2.3. Переменные среды процесса. ⇢
- Листинг 7.4. (print-environment.c) Отображение переменных среды процесса.
- 7.2.4. Исполняемый файл процесса. ⇢
- Листинг 7.5. (get-exe-path.c) Определение путевого имени текущего исполняемого файла.
- 7.2.5. Дескрипторы файлов процесса. ⇢
- Листинг 7.6. (open-and-spin.c) Открытие файла для чтения.
- 7.2.6. Статистика использования процессом памяти. ⇢
- 7.2.7. Статистика процесса. ⇢
- 7.3. Аппаратная информация. ⇢
- 7.3.1. Центральный процессор. ⇢
- 7.3.2. Аппаратные устройства. ⇢
- 7.3.3. Шина PCI. ⇢
- 7.3.4. Последовательные порты. ⇢
- 7.4. Информация о ядре. ⇢
- 7.4.1. Версия ядра. ⇢
- 7.4.2. Имя компьютера и домена. ⇢
- 7.4.3. Использование памяти. ⇢
- 7.5. Дисководы, точки монтирования и файловые системы. ⇢
- 7.5.1. Файловые системы. ⇢
- 7.5.2. Диски и разделы. ⇢
- 7.5.3. Точки монтирования. ⇢
- 7.5.4. Блокировки. ⇢
- 7.6. Системная статистика. ⇢
- Листинг 7.7. (print-uptime.c) Отображение времени работы и времени простоя системы.
- Глава 8. Системные вызовы Linux. ⇢
- 8.1. Команда strace. ⇢
- 8.2. Функция access(): проверка прав доступа к файлу. ⇢
- Листинг 8.1. (check-access.c) Проверка прав доступа к файлу.
- 8.3. Функция fcntl(): блокировки и другие операции над файлами. ⇢
- Листинг 8.2. (lock-file.c) Установка блокировки записи с помощью функции fcntl().
- 8.4. Функции fsync() и fdatasync(): очистка дисковых буферов. ⇢
- Листинг 8.3. (write_journal_entry.c) Запись строки в журнальный файл с последующей синхронизацией.
- 8.5. Функции getrlimit() и setrlimit(): лимиты ресурсов. ⇢
- Листинг 8.4. (limit-cpu.c) Задание ограничения на использование нейтрального процессора.
- 8.6. Функция getrusage(): статистика процессов. ⇢
- Листинг 8.5. (prinf-cpu-times.c) Определение пользовательского и системного времени, затраченного на выполнение текущего процесса.
- 8.7, Функция gettimeofday(): системные часы. ⇢
- Листинг 8.6. (print-time.c) Отображение даты и времени.
- 8.8. Семейство функций mlock(): блокирование физической памяти. ⇢
- 8.9. Функция mprotect(): задание прав доступа к памяти. ⇢
- Корректное выделение памяти.
- Листинг 8.7. (mprotect.c) Обнаружение попыток доступа к памяти благодаря функции mprotect().
- 8.10. Функция nanosleep(): высокоточная пауза. ⇢
- Листинг 8.8. (better_sleep.c) Высокоточная реализация функции sleep().
- 8.11. Функция readlink(): чтение символических ссылок. ⇢
- Листинг 8.9. (print-symlink.с) Отображение адресата символической ссылки.
- 8.12. Функция sendfile(): быстрая передача данных. ⇢
- Листинг 8.10. (сору.с) Копирование файла с помощью функции sendfile().
- 8.13. Функция setitimer(): задание интервальных таймеров. ⇢
- Листинг 8.11. (itimer.c) Пример создания таймера.
- 8.14. Функция sysinfo(): получение системной статистики. ⇢
- Листинг 8.12. (sysinfo.c) Вывод системной статистики.
- 8.15. Функция uname(). ⇢
- Листинг 8.15. (print-uname.c) Вывод информации о ядре и платформе.
- Глава 9. Встроенный ассемблерный код. ⇢
- 9.1. Когда необходим ассемблерный код. ⇢
- 9.2. Простая ассемблерная вставка. ⇢
- 9.2.1. Преобразование функции asm() в ассемблерные инструкции. ⇢
- 9.3. Расширенный синтаксис ассемблерных вставок. ⇢
- 9.3.1. Ассемблерные инструкции. ⇢
- 9.3.2. Выходные операнды. ⇢
- 9.3.3. Входные операнды. ⇢
- 9.3.4. Модифицируемые регистры. ⇢
- 9.4. Пример. ⇢
- Листинг 9.1. (bit-pos-loop.c) Нахождение позиции старшего значащего бита в цикле.
- Листинг 9.2. (bit-pos-asm.c) Нахождение позиции старшего значащего бита с помощью инструкции bsrl.
- 9.5. Вопросы оптимизации. ⇢
- 9.6. Вопросы сопровождения и переносимости. ⇢
- Глава 10. Безопасность. ⇢
- 10.1. Пользователи и группы. ⇢
- 10.1.1. Суперпользователь. ⇢
- 10.2. Идентификаторы пользователей и групп, закрепленные за процессами. ⇢
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы.
- 10.3. Права доступа к файлам. ⇢
- Листинг 10.2. (stat-perm.c) Проверка того, имеет ли владелец право записи в файл.
- 10.3.1. Проблема безопасности: программы без права выполнения. ⇢
- 10.3.2. Sticky-бит. ⇢
- 10.4. Реальные и эффективные идентификаторы. ⇢
- 10.4.1. Программы с установленным битом SUID. ⇢
- Листинг 10.3. (setuid-test.c) Проверка идентификаторов.
- 10.5. Аутентификация пользователей. ⇢
- Листинг 10.4. (pam.c) Пример использования модулей РАМ.
- 10.6. Дополнительные проблемы безопасности. ⇢
- 10.6.1. Переполнение буфера. ⇢
- 10.6.2. Конкуренция доступа к каталогу /tmp. ⇢
- Листинг 10.5. (temp-file.c) Безопасное создание временного файла.
- 10.6.3. Функции system() и popen(). ⇢
- Листинг 10.6. (grep-dictionary.c) Поиск слова в словаре.
- Глава 11. Демонстрационное Linux-приложение. ⇢
- 11.1. Обзор. ⇢
- 11.1.1. Существующие ограничения. ⇢
- Протокол HTTP.
- 11.2. Реализация. ⇢
- Листинг 11.1. (server.h) Объявления функций и переменных.
- 11.2.1. Общие функции. ⇢
- Листинг 11.2. (common.c) Функции общего назначения.
- 11.2.2. Загрузка серверных модулей. ⇢
- Листинг 11.3. (module.c) Загрузка и выгрузка серверных модулей.
- 11.2.3. Сервер. ⇢
- Листинг 11.4. (server.c) Реализация HTTP-сервера.
- 11.2.4. Основная программа. ⇢
- Листинг 11.5. (main.c) Главная серверная функция, выполняющая анализ аргументов командной строки.
- 11.3. Модули. ⇢
- 11.3.1. Отображение текущего времени. ⇢
- Листинг 11.6. (time.c) серверный модуль, отображающий текущее время.
- 11.3.2. Отображение версии Linux. ⇢
- Листинг 11.7. (issue.c) Серверный модуль, отображающий информацию о дистрибутиве Linux.
- 11.3.3. Отображение объема свободного дискового пространства. ⇢
- Листинг 11.8. (diskfree.c) Серверный модуль, отображающий информацию о свободном дисковом пространстве.
- 11.3.4. Статистика выполняющихся процессов. ⇢
- Листинг 11.9. (processes.c) Серверный модуль, отображающий таблицу процессов.
- 11.4. Работа с сервером. ⇢
- 11.4.1. Файл Makefile. ⇢
- Листинг 11.10. (Makefile) Файл конфигурации сервера.
- 11.4.2. Создание сервера. ⇢
- 11.4.3. Запуск сервера. ⇢
- 11.5. Вместо эпилога. ⇢
- Часть III. Приложения. ⇢
- Приложение А. Вспомогательные инструменты разработки. ⇢
- А.1. Статический анализ программы. ⇢
- Листинг А.1. (hello.c) Простейшая программа.
- А.2. Поиск ошибок в динамической памяти. ⇢
- А.2.1. Программа для тестирования динамической памяти. ⇢
- А.2.2. Проверка функции malloc(). ⇢
- А.2.3. Поиск потерянных блоков памяти с помощью утилиты mtrace. ⇢
- А.2.4. Библиотека ccmalloc. ⇢
- А.2.5. Библиотека Electric Fence. ⇢
- А.2.6. Выбор средств отладки. ⇢
- А.2.7. Исходный текст программы, работающей с динамической памятью. ⇢
- Листинг А.2. (malloc-use.c) Пример работы с динамической памятью.
- A.3. Профилирование. ⇢
- А.3.1. Простейший калькулятор. ⇢
- А.3.2. Сбор профильной информации. ⇢
- А.3.3. Отображение профильных данных. ⇢
- А.3.4. Как работает утилита gprof. ⇢
- А.3.5. Исходные тексты программы-калькулятора. ⇢
- Листинг А.3. (calculator.c) Основная часть программы-калькулятора.
- Листинг А.4. (number.c) Арифметика унарных чисел.
- Листинг А.5. (stack.c) Стек унарных чисел.
- Листинг А.6. (definitions.h) Файл заголовков для файлов number.c и stack.c.
- Приложение Б. Низкоуровневый ввод-вывод. ⇢
- Б.1. Чтение и запись данных. ⇢
- Б.1.1. Открытие файла. ⇢
- Значения umask.
- Листинг Б.1. (createfile.c) Создание файла.
- Б.1.2. Закрытие файла. ⇢
- Б.1.3. Запись данных. ⇢
- Листинг Б.2. (timestamp.c) Запись в файл метки времени.
- Листинг Б.3. (write-all.c) Запись буфера.
- Б.1.4. Чтение данных. ⇢
- Чтение текстовых файлов DOS/Windows.
- Листинг Б.4. (hexdump.c) Отображение шестнадцатеричного дампа файла.
- Б.1.5. Перемещение по файлу. ⇢
- Листинг Б.5. (lseek-huge.c) Создание огромных файлов с помощью функции lseek().
- Б.2. Функция stat(). ⇢
- Листинг Б.6. (read-file.c) Загрузка файла в буфер.
- Б.3. Векторные чтение и запись. ⇢
- Листинг Б.7. (write-args.c) Запись списка аргументов в файл с помощью функции writev().
- Б.4. Взаимосвязь с библиотечными функциями ввода-вывода. ⇢
- Б.5. Другие низкоуровневые операции. ⇢
- Б.6. Чтение содержимого каталога. ⇢
- Листинг Б.8. (listdir.c) Вывод содержимого каталога.
- Приложение В. Таблица сигналов. ⇢
- Приложение Г. Internet-ресурсы. ⇢
- Г.1. Общая информация. ⇢
- Г.2. Информация о программном обеспечении GNU/Linux. ⇢
- Г.3. Другие ресурсы. ⇢
- Приложение Д. Лицензия на публикацию программ с открытыми кодами, версия 1.0. ⇢
- I. Требования к модифицированной и немодифицированной версиям. ⇢
- II. Авторские права. ⇢
- III. Область действия Лицензии. ⇢
- IV. Требования к модифицированным материалам. ⇢
- V. Рекомендации. ⇢
- VI. Предусмотренные ограничения. ⇢
- Дополнение, касающееся политики публикации. ⇢
- Приложение Е. Общая лицензия GNU[42]. ⇢
- Преамбула. ⇢
- Условия копирования, распространения и модификации программных продуктов. ⇢
- Гарантия отсутствует.
- Конец условий. ⇢
- Как применить эти требования к новым программным продуктам. ⇢
- Примечания. ⇢
Марк Митчелл, Джеффри Оулдем, Алекс Самьюэл.