Здравствуйте, уважаемые читатели! С наступающими вас праздниками.
В последней апрельской публикации мы хотели бы рассказать вам о замечательной книге Майкла Керриска «Linux Programming Interface», которая в очередной раз вернулась в наше поле зрения благодаря превосходным продажам другой литературы по Linux:
Конечно, сложная книга о системном программировании объемом 1500+ страниц — литература, прямо скажем, на любителя. Но, поскольку отзывы о ней до сих пор восторженные, а нам потратиться на Linux завсегда не жалко предлагаем почитать ее обзор, опубликованный в далеком 2011 году.
Книга Майкла Керриска «The Linux Programming Interface» (TLPI) в первую очередь ориентирована на системных программистов, работающих с Linux, но целевая аудитория ими далеко не ограничивается. Хотя это и объемистый том (говорят, «таким можно быка пришибить»), читается книга на удивительно легко — и если вы ее просто пролистываете, и если штудируете каждый абзац. Здесь вы найдете энциклопедическую информацию об интерфейсе системных вызовов ядра Linux, но весь материал изложен в очень доступном стиле. В общем, это отличный справочник, который займет достойное место в библиотеке любого специалиста по Linux, работающего как с ядром, так и с пользовательским пространством, а также заинтересует некоторых из тех, кто не занимается Linux профессионально.
Керриск занимается поддержкой man-справки по Linux с 2004 года, поэтому отлично представляет себе Linux API. Как он упоминает в предисловии, возможно, вы уже знакомы с некоторыми его работами, а именно с разделами 2, 3, 4 и 5 этой справки. Но книга – не просто сборник статей из справки, хотя тематически во многом им близка. Ее материал организован иначе и изложен значительно более живым, популярным стилем.
Объем книги – около 1500 страниц, поэтому написать по ней обзор было не так просто. Однако, приступив к чтению, я вскоре ею увлекся. Керриск внятно описывает системные вызовы Linux и другие элементы API. Я решил прочитать лишь наиболее заинтересовавшие меня главы, а остальное пропустить, но в итоге прочитал гораздо больше, чем собирался.
Книга состоит из 64 глав, в каждой из которых примерно 20 страниц. Поэтому материал легко усваивается небольшими фрагментами, можно читать книгу и параллельно заниматься другими задачами. Основное внимание Керриск уделяет Linux, однако не забывает и о других разновидностях UNIX, отмечает, чем другие UNIX-подобные системы отличаются от Linux. Автор внимательно рассматривает различные стандарты, описывающие поведение Linux – в частности, POSIX и Single UNIX Specification (SUS) — указывая, где в Linux соблюдаются и где не соблюдаются эти стандарты.
Книга начинается с исторического экскурса: от таких классиков как Томпсон и Ричи до недавнего прошлого, с рассмотрением различных ветвей древа UNIX. Затем автор рассказывает, что такое операционная система, какую роль в ней играет ядро, а также излагает некоторые общие концепции, составляющие суть Unix (и Linux). Хотя для большинства корифеев Linux здесь нет никаких секретов, эта информация пригодится тем, кто раньше работал с другими операционными системами. Идеи «все — файл» и «файл — это просто поток байт» описаны настолько доступно, что любой системный программист, познакомившись с книгой, сможет быстро вступить на «путь Unix».
После такого введения Керриск переходит к главам, в каждой из которых описываются те или иные аспекты интерфейса системных вызовов. Этот материал занимает большую часть книги, причем каждая глава, в сущности, самодостаточна. Последующие главы основываются на предыдущих, при этом их текст изобилует ссылками на другие разделы. В предисловии Керриск упоминает, что постарался свести к минимуму количество опережающих ссылок, но это явно не слишком ему удалось, так как опережающих ссылок получилось не меньше, чем обычных.
В каждой главе приводятся понятные образцы кода, которые удобно читать. Важно, что эти примеры очень помогают напрактиковаться в теме, а некоторые из листингов легко можно доделать до хороших утилит. Весь исходный код доступен на сайте man7.org/tlpi и является свободным, выпущен по лицензии Affero GPLv3. Кроме того, в каждой главе есть упражнения для читателя, решения некоторых из них даны в приложении.
Итак, о чем же книга? Легко сказать «обо всем сразу», но это будет своеобразная отговорка, причем неточная. В книге вы найдете множество глав о файлах, файловом вводе/выводе, расширенных атрибутах, списках контроля доступа (ACL). Есть глава о каталогах и ссылках, а в другой главе рассматривается вызов inotify, позволяющий получать уведомления о событиях, происходящих в файлах.
Здесь вы найдете множество глав о процессах, потоках, сигналах, целые главы, в которых рассматриваются группы процессов, сеансы, приоритет процессов и планирование. Особенно интересной мне показалась глава о создании защищенных привилегированных программ. Есть две главы о разделяемых библиотеках, причем в первой из этих глав акцент делается на базовых идеях, лежащих в основе этих библиотек, а также о создании разделяемых библиотек в принципе; в свою очередь, вторая из этих глав посвящена системному вызову dlopen()
и ему подобным.
Пожалуй, в книге слишком много глав о межпроцессной коммуникации (IPC), по одной главе посвящено каждому IPC-механизму в составе System V (разделяемая память, очереди сообщений и семафоры). Также есть по главе о каждом из трех POSIX-вариантов этих типов IPC. Как по POSIX, так и по System V IPC есть своя вводная глава кроме тех глав, в которых излагаются подробности о каждом типе. Между двумя разделами о механизмах System V и POSIX IPC втиснуты две главы об отображении на память и об операциях с виртуальной памятью, которые, возможно, лучше было бы поставить в другой части книги. Еще есть глава, в которой делается введение в IPC и глава о более традиционных каналах Unix и очередях FIFO. Всего насчитывается двенадцать глав, связанных с IPC, после чего автор начинает рассматривать API сокетов.
После IPC идет глава о блокировке файлов, а затем шесть глав о сокетах. В этих главах рассматриваются сокеты Unix и сокеты Интернета, а также рассказывается о серверном дизайне и освещаются сложные темы, связанные с сокетами. Книга заканчивается главами о терминалах и псевдотерминалах, между которыми как-то затесалась глава «Альтернативные модели ввода/вывода». Это интересная глава, в которой рассматриваются вызовы select()
, poll()
, epoll()
, сигнально-управляемый ввод/вывод и некоторые другие темы. Но расположена она все-таки немного странно.
Само собой, содержание книги этим не ограничивается. После ее прочтения особенно впечатляет, насколько велик API Linux/Unix. В книге также рассматриваются некоторые недостатки и морально устаревшие детали, сохранившиеся в API. Керриск ничуть не стесняется делать в нужных местах подобные замечания: «Вообще, очередями сообщений System V обычно лучше не пользоваться».
Есть две темы, о которых я очень хотел почитать, но которые плохо раскрыты в книге. Во-первых, это контейнеры и пространства имен, которые лишь вскользь упоминаются при обсуждении флагов системного вызова clone()
. Более странным показалось, что в книге почти не упоминается системный вызов ptrace()
. В тех немногих местах, где он все-таки фигурирует, читателей отсылают к man-справке ptrace(2).
Разумеется, кроме интерфейса системных вызовов можно было бы рассмотреть и другие элементы Linux API – навскидку вспоминаются sysf, splice()
и perf – но Керриску явно приходилось выбирать, что включить в книгу, а от чего отказаться. В принципе, автор справился хорошо. Некоторые технические книги по Linux достаточно быстро устаревают, но в случае с этой работой проблема устаревания стоит не так остро как, например, с книгой об устройстве ядра.
У меня есть еще некоторые претензии к книге, но все они несущественные. В первую очередь, хотелось бы сказать, что многочисленные «отступления» в книге — это именно лирические отступления. Они содержат дополнительную информацию, которая некритична для понимания темы. По-моему, многие из них лучше было бы вплести в основной текст.
Книга пригодится, прежде всего, системным программистам и разработчикам приложений, но ими целевая аудитория не ограничивается. Разработчики ядра смогут уточнить, не противоречат ли их новые фичи (или фиксы) структуре API. Программисты, занятые преимущественно разработкой для Unix-подобных систем, при помощи этой книги смогут сделать свой код более портируемым. Думаю, читатель будет регулярно с пользой возвращаться к этой книге. Полагаю, все, кто по-настоящему интересуется программированием для Linux, со мной согласятся.
Автор: Издательский дом «Питер»