ББК 32.973.2-018.2 УДК 004.451 Л13 Лав Р Л13 Linux Системное программирование 2-е изд — СПб.: Питер, 2014 — 448 с.: ил. — (Серия «Бестселлеры O’Reilly») ISBN 978-5-496-00747-4 Роберт Лав стоит у истоков создания операционной системы Linux Он внес существенный вклад в создание ядра Linux и настольной среды GNOME Эта книга представляет собой руководство по системному программированию для Linux, справочник по системным вызовам Linux, а также подробный рассказ о том, как писать более быстрый и умный код Роберт Лав четко разграничивает стандартные функции POSIX и специальные службы, которые предлагаются лишь в Linux Во втором издании вы изучите эту операционную систему как с теоретической, так и с прикладной точки зрения 12+ (В соответствии с Федеральным законом от 29 декабря 2010 г № 436-ФЗ.) ББК 32.973.2-018.2 УДК 004.451 Права на издание получены по соглашению с O’Reilly Все права защищены Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав Информация, содержащаяся в данной книге, получена из источников, рассматриваемых издательством как надежные Тем не менее, имея в виду возможные человеческие или технические ошибки, издательство не может гарантировать абсолютную точность и полноту приводимых сведений и не несет ответственности за возможные ошибки, связанные с использованием книги ISBN 978-1449339531 англ ISBN 978-5-496-00747-4 Authorized Russian translation of the English edition of Linux System Programming: Talking Directly to the Kernel and C Library 2nd edition (ISBN 9781449339531) © 2013 Robert Love This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same â ôằ, 2014 â , ôằ, 2014 Краткое содержание Предисловие 17 Вступление 19 Благодарности 25 От издательства 26 Глава 1 Введение и основополагающие концепции 27 Глава 2 Файловый ввод-вывод 54 Глава 3 Буферизованный ввод-вывод 99 Глава 4 Расширенный файловый ввод-вывод 125 Глава 5 Управление процессами 171 Глава 6 Расширенное управление процессами 210 Глава 7 Поточность 245 Глава 8 Управление файлами и каталогами 275 Глава 9 Управление памятью 324 Глава 10 Сигналы 365 Глава 11 Время 394 Приложение A Расширения GCC для языка C 427 Приложение Б Библиография 441 Оглавление Предисловие 17 Вступление 19 Целевая аудитория и необходимые Краткое содержание Версии, рассмотренные в книге Условные обозначения Работа с примерами кода предпосылки 19 20 21 22 24 Благодарности 25 От издательства 26 Глава 1 Введение и основополагающие концепции 27 Системное программирование Зачем изучать системное программирование Краеугольные камни системного программирования Системные вызовы Библиотека C Компилятор C API и ABI API ABI Стандарты История POSIX и SUS Стандарты языка C Linux и стандарты Стандарты и эта книга Концепции программирования в Linux Файлы и файловая система Процессы Пользователи и группы Права доступа 27 28 29 29 30 31 31 32 32 33 34 34 35 36 37 37 45 47 48 Оглавление Сигналы Межпроцессное взаимодействие Заголовки Обработка ошибок Добро пожаловать в системное программирование 49 50 50 50 53 Глава 2 Файловый ввод-вывод 54 Открытие файлов Системный вызов open() Владельцы новых файлов Права доступа новых файлов Функция creat() Возвращаемые значения и коды ошибок Считывание с помощью read() Возвращаемые значения Считывание всех байтов Неблокирующее считывание Другие значения ошибок Ограничения размера для read() Запись с помощью write() Случаи частичной записи Режим дозаписи Неблокирующая запись Другие коды ошибок Ограничения размера при использовании write() Поведение write() Синхронизированный ввод-вывод fsync() и fdatasync() sync() Флаг O_SYNC Флаги O_DSYNC и O_RSYNC Непосредственный ввод-вывод Закрытие файлов Значения ошибок Позиционирование с помощью Iseek() Поиск с выходом за пределы файла Ограничения Позиционное чтение и запись Усечение файлов 55 55 58 58 60 61 61 62 63 64 64 65 65 66 67 67 68 68 68 70 70 72 73 74 74 75 76 76 78 79 79 80 Мультиплексный ввод-вывод select() Системный вызов poll() Сравнение poll() и select() Внутренняя организация ядра Виртуальная файловая система Страничный кэш Страничная отложенная запись Резюме Оглавление 81 83 88 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 Оглавление Возвращаемые значения 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 434 Приложение A Расширения GCC для языка C Помещение глобальных переменных в регистр GCC позволяет программисту размещать глобальные переменные в специальном машинном регистре, где переменные затем будут находиться на протяжении всей длительности работы программы В GCC такие переменные называются глобальными регистровыми переменными В соответствии с синтаксисом программист обязан указать машинный регистр В следующем примере используется регистр ebx: register int *foo asm ("ebx"); Программист должен выбрать переменную, которая не затирается функциями: то есть выбранная переменная должна быть пригодна для использования локаль ными функциями, сохраняться и восстанавливаться при вызове функции и не выделяться для каких бы то ни было специальных целей на уровне ABI-интерфей сов данной архитектуры или операционной системы Если выбран неподходящий регистр, то компилятор сгенерирует предупреждение Если регистр подходит, на пример ebx, использованный в данном примере, полностью удовлетворяет требо ваниям архитектуры x86, то компилятор, в свою очередь, прекратит применять этот регистр Такая оптимизация позволяет радикально повысить производительность, если переменная часто используется Хороший пример — работа с виртуальными ма шинами Если поместить в регистр переменную, которая, скажем, содержит указа тель фрейма виртуального стека, то можно значительно выиграть в производитель ности С другой стороны, если архитектура с самого начала испытывает дефицит (а в архитектуре x86 ситуация именно такова), то подобная оптимизация нецеле сообразна Глобальные регистровые переменные нельзя использовать в обработчиках сиг налов или сразу в нескольких потоках исполнения Кроме того, они не могут со держать исходных значений, поскольку отсутствует механизм, с помощью которо го исполняемые файлы могли бы передавать в регистры содержимое, задаваемое по умолчанию Объявления глобальных регистровых переменных должны пред шествовать любым определениям функций Аннотирование ветвей GCC позволяет программисту аннотировать ожидаемое значение выражения — на пример, сообщать компилятору: должно быть условное выражение истинным или ложным GCC, в свою очередь, может выполнять переупорядочение блоков и дру гие виды оптимизации, позволяющие повысить производительность условных ветвлений Получение типа выражения 435 Синтаксис GCC для записи ветвления некрасив до безобразия Чтобы повы сить удобочитаемость аннотирования ветвей, мы используем препроцессорные макросы: #define likely(x) builtin_expect (!!(x), 1) #define unlikely(x) builtin_expect (!!(x), 0) Программист может аннотировать выражение как вероятно истинное или ве роятно ложное, обернув его в функцию likely() или unlikely() соответственно В следующем примере ветвь аннотируется как вероятно ложная: int ret; ret = close (fd); if (unlikely (ret)) perror ("close"); А в этом примере ветвь, наоборот, обозначается как вероятно истинная: const char *home; home = getenv ("HOME"); if (likely (home)) printf ("Ваш домашний каталог — %s\n", home); else fprintf (stderr, "Переменная среды HOME не установлена!\n"); Как и в случае со встраиваемыми функциями, программисты зачастую злоупо требляют аннотированием ветвей Как только вы начинаете это практиковать, возникает соблазн пометить все выражения Но будьте осторожны — такие анно тации выражений допустимы лишь в случаях, когда вы априори уверены и прак тически не сомневаетесь, что данное выражение будет истинным или ложным практически всегда (например, в 99 % случаев) Скажем, функцию unlikely() удоб но использовать с редко встречающимися ошибками Не забывайте, что неверный прогноз хуже, чем отсутствие какого-либо прогноза Получение типа выражения GCC предоставляет ключевое слово typeof() для получения типа заданного выра жения Семантически это ключевое слово действует точно так же, как и sizeof() Например, следующее выражение возвращает любой тип, на который указывает x: typeof (*x) Мы можем воспользоваться выражением для объявления массива y, состояще го из этих типов: typeof (*x) y[42]; 436 Приложение A Расширения GCC для языка C Популярный вариант использования typeof() — написание «безопасных» ма кросов, способных оперировать любыми арифметическими выражениями и интер претировать их параметры только один раз: #define max(a,b) ({ \ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a > _b ? _a : _b; \ }) Получение границы выравнивания типа GCC предоставляет ключевое слово alignof, позволяющее определить вырав нивание заданного объекта Это значение зависит от конкретной архитектуры и ABI Если в актуальной архитектуре не обеспечивается требуемое выравни вание, то ключевое слово возвращает выравнивание, рекомендуемое в данном ABI В противном случае ключевое слово возвращает минимальное требуемое выравнивание Синтаксис идентичен синтаксису sizeof(): alignof (int) В зависимости от архитектуры данная функция, вероятно, вернет 4, так как 32-битные целые числа обычно выравниваются по 4-байтным границам ПРИМЕЧАНИЕ В C11 и C++11 появилась функция alignof(), которая действует идентично alignof(), но при этом стандартизирована При написании программ на C11 или C++11 следует отдавать предпочтение alignof() Это ключевое слово работает и с адресами переменных (lvalue) В данном слу чае возвращается минимальное выравнивание базового типа, а не актуальное вы равнивание конкретного адреса переменной Если минимальное выравнивание было изменено с помощью атрибута aligned (описано выше, в разд. «Увеличение границы выравнивания переменной» этого приложения), то это изменение отра жается ключевым словом alignof Например, рассмотрим следующую структуру: struct ship { int year_built; char cannons; int mast_height; }; а также этот фрагмент кода: struct ship my_ship; printf ("%d\n", alignof (my_ship.cannons)); Получение возвращаемого адреса функции 437 Ключевое слово alignof для этого фрагмента кода вернет 1, хотя из-за забивки структуры возможна ситуация, в которой на cannons потратится 4 байт Смещение члена внутри структуры GCC предоставляет встроенное ключевое слово для определения смещения члена структуры внутри структуры Макрос offsetof(), определенный в , входит в состав стандарта ISO C Большинство определений просто ужасны, они содержат непристойную арифметику над указателями и не рекомендуются несовершенно летним читателям Расширение из GCC проще, а также потенциально быстрее: #define offsetof(type, member) builtin_offsetof (type, member) Вызов возвращает смещение члена member внутри типа, то есть количество бай тов от нуля (с начала этой структуры) до данного члена Расмотрим, например, следующую структуру: struct rowboat { char *boat_name; unsigned int nr_oars; short length; }; Точные значения смещений зависят от размера переменных, требований, предъ являемых к выравниванию в данной архитектуре, а также от принципа заполнения На 32-битной машине мы вполне можем встретить вызов offsetof() в структуре rowboat с полями boat_name, nr_oars и length, чьи возвращаемые значения будут равны 0, и соответственно В системе Linux макрос offsetof() должен определяться с применением ключе вого слова из GCC Повторно определять его не требуется Получение возвращаемого адреса функции GCC предоставляет ключевое слово для получения возвращаемого адреса актуаль ной функции либо одного из «вызывателей» этой функции: void * builtin_return_address (unsigned int level) Параметр level указывает в цепочке вызовов ту функцию, адрес которой должен быть возвращен Значение требует возвращаемый адрес актуальной функции, значение 1 — адрес той функции, которая вызвала актуальную, значение 2 — функ цию, вызвавшую ту, которой соответствует значение 1, и т. д Если актуальная функция является встроенной, то возвращается адрес вызы вающей функции Если это неприемлемо, то пользуйтесь ключевым словом noinline Так вы принудите компилятор не встраивать функции Существует несколько способов применения ключевого слова builtin_ return_address В частности, оно используется в отладочных и справочных целях 438 Приложение A Расширения GCC для языка C Другой пример практического использования — раскручивание цепочки вызо вов, требуемое для реализации интроспекции, утилиты для аварийного дампа, отладчика и т. д Обратите внимание: некоторые архитектуры позволяют возвращать только адрес вызывающей функции В таких архитектурах ненулевое значение параметра может привести к выводу случайного возвращаемого значения Следовательно, любые ненулевые значения параметров не допускают портирования и должны использоваться только в отладочных целях Диапазоны оператора case GCC позволяет указывать в метках оператора case диапазон значений для отдель но взятого блока Синтаксис таков: case low high: Например: switch (val) { case 10: /* */ break; case 11 20: /* */ break; default: /* */ } Эта функциональность очень полезна при работе с диапазоном значений ASCII: case 'A' 'Z': Обратите внимание, что до и после многоточия должны быть пробелы В про тивном случае компилятор может «запутаться», особенно в целочисленных диапа зонах Всегда делайте так: case 8: а так никогда не делайте: case 8: Арифметика указателей типа void и указателей на функции В GCC операции сложения и вычитания допускаются над указателями типа void и над указателями на функции Как правило, стандарт ISO C не позволяет выполнять 439 Более переносимо и красиво арифметические операции над такими указателями, поскольку размер значения типа void — это фактически нонсенс, он зависит от того, на какую именно сущность направлен указатель Для обеспечения подобной арифметики GCC принимает размер такого адресуемого объекта за один байт Следующий фрагмент кода уве личивает значение a на единицу: a++; /* a — это void-указатель */ Параметр -Wpointer-arith заставляет GCC генерировать предупреждение, когда используются такие расширения Более переносимо и красиво Согласитесь, синтаксис attribute очень некрасивый Некоторые расширения, рас смотренные в этом приложении, требуют использования препроцессорных макро сов — только так работа с ними становится терпимой Но любые расширения лишь выиграют, если немного улучшить их внешний вид Немного препроцессорных уловок — и все получается как по волшебству Более того, выполняя такую работу, мы также обеспечиваем портируемость GCC-расши рений, определяя их таким образом, что они будут понятны любому компилятору (а не только GCC) Для этого включите следующий фрагмент кода в заголовок и добавьте этот заголовок в ваши файлы исходников: #if GNUC_ _ >= # undef inline # define inline inline # define noinline # define pure # define const # define noreturn # define malloc # define must_check # define deprecated # define used # define unused # define packed # define align(x) # define align_max # define likely(x) # define unlikely(x) #else # define noinline # define pure # define const # define noreturn # define malloc # define must_check attribute_ _ ((always_inline)) attribute ((noinline)) attribute ((pure)) attribute ((const)) attribute ((noreturn)) attribute ((malloc)) attribute ((warn_unused_result)) attribute ((deprecated)) attribute ((used)) attribute ((unused)) attribute ((packed)) attribute ((aligned (x))) attribute ((aligned)) builtin_expect (!!(x), 1) builtin_expect (!!(x), 0) /* /* /* /* /* /* не не не не не не noinline */ pure */ const */ noreturn */ malloc */ warn_unused_result */ 440 # define # define # define # define # define # define # define # define #endif Приложение A Расширения GCC для языка C deprecated /* used /* unused /* packed /* align(x) /* align_max /* likely(x) (x) unlikely(x) (x) не не не не не не deprecated */ used */ unused */ packed */ aligned */ align_max */ Например, в следующем фрагменте мы помечаем эту функцию как чистую, пользуясь одним из вышеперечисленных сокращений: pure int foo (void) { /* */ } Если применяется GCC, то эта функция помечается атрибутом pure Если мы работаем не с GCC, а с другим компилятором, то препроцессор однозначно требу ет метку pure Обратите внимание: в каждом определении вы можете указывать несколько атрибутов и соответственно одновременно применять несколько из вышеперечисленных комбинаций Проще, красивее, портабельнее! Приложение Б Библиография В этом приложении перечислена рекомендуемая литература, имеющая отношение к системному программированию Все приведенные источники разбиты на четы ре подкатегории Ни одна из этих работ не является обязательной к прочтению Это просто моя подборка книг, которые кажутся мне наиболее ценными материа лами по той или иной теме Если вы желаете ознакомиться с дополнительной информацией, расширяющей материал моей книги, то именно эти книги я бы вам посоветовал Некоторые работы из данной подборки посвящены темам, в которых вы уже должны хорошо ориентироваться, — например, языку C Другие тексты значитель но дополняют книгу, подробно рассказывая, в частности, о gdb, Git и о проектиро вании операционных систем Разумеется, данный список неполный — наверняка вы найдете и другие, не менее ценные ресурсы Книги по языку программирования C В книгах из этого раздела рассматривается язык C — лингва франка1 системного программирования Если вы не умеете писать код на C столь же непринужденно, как говорить на родном языке, то одна или несколько следующих книг (а также большая практическая работа) помогут вам улучшить знания этого языка Особо рекомендую изучить первую книгу, иногда сокращенно именуемую K & R Ее краткость красноречиво показывает, насколько прост язык C Керниган Б., Ритчи Д Язык программирования Си (The C programming language). — 2-е изд. — М.: Вильямс, 2007 Лингва франка — смесь арабского, турецкого и различных романских языков, сложи вшаяся в Средние века на берегах Средиземного моря; использовалась в основном в ку печеской среде для межнационального делового общения. — Примеч пер 442 Приложение Б Библиография Эта книга написана одним из авторов языка C и его соратником Представляет собой наиболее фундаментальную работу по языку C Prinz Peter, Crawford Tony C in a Nutshell. — O'Reilly Media, 2005 Отличная книга, рассказывающая как о языке C, так и о стандартной библио теке C Prinz Peter, Kirch-Prinz Ulla C Pocket Reference. — O'Reilly Media, 2002 Краткий справочник по языку C, обновленный с учетом ANSI C99 Van der Linden Peter Expert C Programming. — Prentice Hall, 1994 Прекрасная книга о сравнительно малоизвестных аспектах языка C, написанная в остроумном стиле и сдобренная авторским юмором Summit Steve C Programming FAQs: Frequently Asked Questions. — 2nd edition. — Addison-Wesley, 1995 Эта книга — настоящий шедевр Она содержит более 400 часто задаваемых вопросов (с ответами) по языку программирования C Ответы на многие из вопросов покажутся банальными знатокам языка C, но некоторые глубокие вопросы и ответы впечатлят даже самых эрудированных C-программистов У этой книги есть и интернет-версия, которая обновляется гораздо оперативнее, чем бумажная Книги по программированию в Linux Следующие тексты посвящены программированию в Linux В них рассматривают ся некоторые темы, не затронутые в этой книге, а также многие интересные ин струменты для программирования Стивенс У., Феннер Б., Рудофф Э UNIX: Разработка сетевых приложений. — 3-е изд. — СПб.: Питер, 2004 Исчерпывающая работа, посвященная API сокетов К сожалению, книга расска зывает не только о Linux, однако радует, что она была обновлена с учетом стан дарта IPv6 Стивенс У UNIX: взаимодействие процессов. — СПб.: Питер, 2001 Отличная книга, посвященная межпроцессной коммуникации (IPC) Nichols Bradford PThreads Programming. — O'Reilly Media, 1996 Обзор интерфейса прикладного программирования потоков в POSIX Mecklenburg Robert Managing Projects with GNU Make. — O'Reilly Media, 2004 В этой книге отлично рассмотрен GNU Make — классический инструмент для выстраивания программных проектов в Linux Collins-Sussman Ben Version Control with Subversion. — O'Reilly Media, 2004 Исчерпывающая работа о Subversion — системе контроля версий, пришедшей на смену CVS В UNIX эта система применяется как для контроля версий, Книги об организации операционных систем 443 так и для управления исходным кодом Книга написана тремя авторами Subversion Loeliger Jon Version Control with Git. — O'Reilly Media, 2012 Великолепное введение в работу с Git — иногда немного запутанной, но неиз менно мощной распределенной системой контроля версий Robbins Arnold GDB Pocket Reference. — O'Reilly Media, 2005 Удобный карманный справочник по gdb — отладчику для Linux Siever Ellen Linux in a Nutshell. — O'Reilly Media, 2009 Потрясающий справочник по всем функциям Linux, в частности по многим из тех инструментов, из которых состоит среда разработки Linux Книги, посвященные ядру Linux Две книги, упомянутые в этом разделе, рассказывают о ядре Linux Существует три основные причины, по которым следует подробнее познакомиться с этой темой Во-первых, ядро предоставляет интерфейс для взаимодействия между системными вызовами и программами из пользовательского пространства, поэтому оно имеет ключевое значение для системного программирования Во-вторых, книга проливает свет на различные особенности поведения и странности, возникающие при взаи модействии ядра с приложением Наконец, ядро Linux — образец отличного кода, и эти книги просто интересны Лав Р Разработка ядра Linux. — 2-е изд. — М.: Вильямс, 2006 Это моя работа, относящаяся к данной категории Она отлично подойдет си стемным программистам, желающим разобраться в конструкции и реализации ядра Linux Эта книга не является справочником по API В ней подробно обсу ждаются алгоритмы, применяемые в ядре Linux, рассматриваются принципы принятия решений в ядре Corbet Jonathan Linux Device Drivers. — O'Reilly Media, 2005 Отличное руководство по программированию драйверов устройств для ядра Linux с великолепным справочником по API Хотя центральной темой этой книги являются драйверы устройств, материал будет интересен программистам различных специализаций, в частности системным программистам, желающим лучше понять принципы функционирования ядра Linux Прекрасное дополнение к моей книге по ядру Linux Книги об организации операционных систем Две упомянутые здесь книги касаются не только Linux — они описывают общие принципы организации операционных систем Как я не раз указывал в этой книге, 444 Приложение Б Библиография глубокое понимание операционной системы, в которой вы программируете, зна чительно повышает качество создаваемого кода Silberschatz Abraham Operating System Concepts. — Prentice Hall, 2012 Отличное введение в тему операционных систем, их историю и базовые алго ритмы В книге содержится хороший набор ситуативных исследований Schimmel Curt UNIX Systems for Modern Architectures. — Addison-Wesley, 1994 Эта книга рассказывает не столько об UNIX, сколько о современнных процес сорных и кэш-архитектурах, является отличным введением в тему взаимодей ствия операционных систем и аппаратного обеспечения Хотя книга немного устарела, я настоятельно ее рекомендую Р Лав Linux Системное программирование 2-е издание Перевел с английского О Сивченко Заведующий редакцией Д Виницкий Ведущий редактор Н Гринчик Литературный редактор В Конаш Художник Л Адуевская Корректоры Т Курьянович, Е Павлович Верстка А Барцевич ООО «Питер Пресс», 192102, Санкт-Петербург, ул Андреевская (д Волкова), 3, литер А, пом 7Н Налоговая льгота — общероссийский классификатор продукции ОК 005-93, том 2; 95 3005 — литература учебная Подписано в печать 27.03.14 Формат 70×100/16 Усл п л 36,120 Тираж 1500 Заказ 0000 Отпечатано в полном соответствии с качеством предоставленных издательством материалов в ГППО «Псковская областная типография» 180004, Псков, ул Ротная, 34 ЗАКАЗАТЬ КНИГИ ИЗДАТЕЛЬСКОГО ДОМА «ПИТЕР» МОЖНО ЛЮБЫМ УДОБНЫМ ДЛЯ ВАС СПОСОБОМ: на нашем сайте: www.piter.com по электронной почте: postbook@piter.com по телефону: (812) 703 73 74 по почте: 197198, Санкт Петербург, а/я 127, ООО «Питер Мейл» по ICQ: 413763617 ВЫ МОЖЕТЕ ВЫБРАТЬ ЛЮБОЙ УДОБНЫЙ ДЛЯ ВАС СПОСОБ ОПЛАТЫ: Наложенным платежом с оплатой при получении в ближайшем почтовом отделении С помощью банковской карты Во время заказа Вы будете перенаправлены на защищенный сервер нашего оператора, где сможете ввести свои данные для оплаты Электронными деньгами Мы принимаем к оплате все виды электронных денег: от традиционных Яндекс.Деньги и Web-money до USD E-Gold, MoneyMail, INOCard, RBK Money (RuPay), USD Bets, Mobile Wallet и др В любом банке, распечатав квитанцию, которая формируется автоматически после совершения Вами заказа Все посылки отправляются через «Почту России» Отработанная система позволяет нам организовывать доставку Ваших покупок максимально быстро Дату отправления Вашей покупки и предполагаемую дату доставки Вам сообщат по e-mail ПРИ ОФОРМЛЕНИИ ЗАКАЗА УКАЖИТЕ: фамилию, имя, отчество, телефон, факс, e mail; почтовый индекс, регион, район, населенный пункт, улицу, дом, корпус, квартиру; название книги, автора, количество заказываемых экземпляров ... 978-5-496-00747-4 Authorized Russian translation of the English edition of Linux System Programming: Talking Directly to the Kernel and C Library 2nd edition (ISBN 9781449339531) © 2013 Robert Love This translation... вклад в создание ядра Linux и настольной среды GNOME Эта книга представляет собой руководство по системному программированию для Linux, справочник по системным вызовам Linux, а также подробный... подробно и фокусируются именно на Linux Еще меньше подобных книг учитывают новейшие релизы Linux и продвинутые интерфейсы, ориентированные исключительно на Linux Эта книга не только лишена всех