Книга: Разработка приложений в среде Linux. Второе издание

Сноски из книги

· #1

Andrew Tanenbaum, Computer Networks, Prentice Hall, 1981, стр. 168.

· #2

По этой причине некоторые люди называют GPL "вирусом". — Примеч. авт.

· #3

Это справедливо для тех, кто привык к раскладке qwerty. Те, кто обучался на клавиатуре Дворака, используют множество макросов vi, которые делают его удобным в наборе.

· #4

Несмотря на то что такое поведение выглядит неудобным, это важное средство, а не ошибка. Неразворачиваемые переменные критически важны при написании обобщенных суффиксных правил, которые создают подразумеваемые зависимости.

· #5

Большинство версий make, включая версию GNU, распространяемую с Linux, определят бесконечный цикл и завершатся с выдачей соответствующего сообщения об ошибке.

· #6

Большинство, но не все, поставщики услуг доступа в Internet назначают динамические IP-адреса, а не статические.

· #7

Несмотря на имя, которое может ввести в заблуждение, этот системный вызов устанавливает имя узла, а не имя Internet-хоста машины.

· #8

Сетевые информационные службы (Network Information Services — NIS) предоставляют для машин в сети механизм совместного использования информации, такой как пользовательские имена и пароли. Ранее они назывались "желтыми страницами" (Yellow Pages — YP). Имя домена NIS — часть этого механизма, который реализуется за пределами ядра системы с тем исключением, что доменное имя хранится в структуре utsname.

· #9

К сожалению, ни одно из средств, описанных в этой главе, не может отследить ошибки в памяти, связанные с глобальными переменными; для этого нужна помощь компилятора. В первом издании этой книги рассматривался инструмент под названием Checker, который представлял собой модифицированную версию компилятора gcc, однако он больше не поддерживается. К официальному компилятору gcc добавлена новая технология под названием mudflap, которая описана в текущем руководстве по gcc.

· #10

Для большей переносимости многие из средств mpr анализа журнала используют gdb для связывания адреса с соответствующим местом в исходном коде. Чтобы это работало, программа должна содержать отладочную информацию.

· #11

Большинство традиционных систем Unix передают ошибку шины (SIGBUS) процессу, который пытается использовать невыровненные данные. Ядро Linux обрабатывает доступ к невыровненным данным так, чтобы процесс мог нормально продолжать работу, хотя за это приходится платить существенным снижением производительности.

· #12

Во всяком случае это справедливо для систем Linux/Intel и Linux/SPARC. Размер страницы зависит от базовой аппаратной архитектуры и в некоторых системах может составлять 16 Кбайт и больше.

· #13

Разница между -fPIC и -fpic заключается в способе генерации независимого от расположения кода. В некоторых архитектурах с помощью -fpic можно собрать только относительно небольшие совместно используемые библиотеки, тогда как в других эти флаги дают один и тот же эффект. Если только нет веских причин на обратное, лучше использовать -fPIC вместо -fpic, тогда все будет работать должным образом во всех архитектурах.

· #14

В случае удаления /etc/ld.so.cache система может замедлиться. Для восстановления /etc/ld.so.cache запустите ldconfig.

· #15

Для многопоточных приложений библиотека хранит код ошибки там, где функция errno(), которой известно, какой поток является текущим, может получить ее. Разные потоки могут содержать разные текущие коды возврата ошибок.

· #16

uid и gid обычно представляют собой положительные целые, но отрицательные целые тоже имеют определенное назначение. Применение -1 для идентификатора проблематично, однако многие системные вызовы, работающие с uid и gid, используют -1 в качестве признака, что модифицировать значение не нужно (см. пример этого в setregid() далее в главе).

· #17

Процессы Linux также имеют четвертый uid и gid, используемые для файлового доступа. Они обсуждаются в следующем разделе этой главы.

· #18

Большинство систем передают окружение в виде параметра main(), но такой метод не включен в стандарт POSIX. Переменная environ — это метод, утвержденный POSIX.

· #19

Детальную информацию о том, как родительские и дочерние открытые файлы соотносятся друг с другом, можно найти в главе 11.

· #20

Группы процессов рассматриваются далее в этой главе

· #21

В главе 15 описаны причины, по которым это может произойти.

· #22

Это тот же формат, который использует команда env для печати текущих значений переменных окружения, и аргумент envp имеет тот же тип, что и глобальная переменная environ.

· #23

Технически это указатель на завершающийся NULL массив указателей на массивы символов, каждый из которых завершается символом ''. Более подробно об это рассказано в [15].

· #24

Появление vfork() было мотивировано старыми системами, которым необходимо было копировать всю память, используемую исходным процессом, как часть fork().Современные операционные системы используют копирование при записи, которое копирует области памяти только по необходимости, как это описано во многих источниках, посвященных операционным системам, в частности [40] и [2]. Это свойство делает fork() почти таким же быстрым, как vfork(), и намного более простым в использовании.

· #25

Это — существенное упрощение. В действительности kill() посылает сигнал, а сигналы сами по себе достаточно сложная тема. См. полное описание того, что такое сигналы и как их применять, в главе 12.

· #26

Это нужно для того, чтобы управляющая заданиями оболочка могла перезапускать процессы, у которых изменился эффективный идентификатор пользователя. Более подробно об управлении заданиями рассказывается в главе 15.

· #27

Одна из популярных ранее форм компьютерной памяти выглядела как набор маленьких железных колечек, расположенных на матрице, к каждому из которых подводились два проводка, служащих для установки и считывания магнитной полярности кольца. Эти кольца назывались ядрами (cores), а все вместе — ядерной памятью. Поэтому дамп ядра — это копия состояния системной памяти в определенный момент времени.

· #28

В процессе работы system() блокирует SIGCHILD, что заставляет передавать этот сигнал программе непосредственно перед тем, как system() вернет управление (но после того, как system() вызовет wait() для порожденного процесса), поэтому программы, которые используют обработчики сигналов, должны это учитывать и обрабатывать такие ложные сигналы осторожно. Функция system() также игнорирует SIGINT и SIGQUIT, а это означает, что быстрые циклические повторные вызовы system() может оказаться невозможно прервать ничем, кроме SIGSTOP и SIGKILL.

· #29

Хотя функция popen() это делает просто, с ней связаны некоторые побочные эффекты, которые не сразу становятся очевидны. Она создает дочерний процесс, который может быть прерван перед тем, как будет вызвана pclose(), что заставит функцию wait() вернуть состояние процесса. Когда этот процесс завершится, он также сгенерирует SIGCHLD, что может привести в замешательство упрощенно написанный обработчик сигналов.

· #30

Этот тип обработки часто приводит к взаимоблокировкам, при которых процесс А ожидает, пока процесс В выполнит какую-то работу, в то время как процесс В ожидает процесса А, в результате чего ничего не происходит.

· #31

Если вам понадобится делать это, запустите дочерний процесс с помощью fork() и exec(), а потом воспользуйтесь poll() для чтения и записи в дочерний процесс. Для этого предназначена программа под названием expect.

· #32

Информацию о чтении и записи в поток stdio можно найти в [15].

· #33

В главе 15 все это проясняется, поэтому, возможно, будет полезно сначала прочитать ее.

· #34

Но, может быть, не сразу. Может существовать группа процессов, содержащая процессы, чьи родители относятся к другой группе в том же сеансе. Поскольку отношения "родительский-дочерний" между процессами образуют дерево, иногда может оказаться, что существует группа процессов, которая содержит только те процессы, чьим родителем является оболочка, и когда такая группа процессов завершается, другая становится висячей.

· #35

Обсуждение станет более понятным после того, как вы прочитаете главы, посвященные сигналам (глава 12) и управлению заданиями (глава 15).

· #36

В среде Linux файловая система /proc включает информацию о каждом файле, открытом в системе в данный момент. Хотя это значит, что неименованные каналы могут быть найдены в файловой системе, все же они не имеют постоянных имен, потому что исчезают при завершении процесса, использующего их.

· #37

Не все блочные устройства представляют реальное оборудование. Более правильное описание блочных устройств — это нечто, на чем может располагаться файловая система; блочное устройство обратной связи (loopback block device) отображает на обычный файл логическое блочное устройство, что позволяет файлам содержать в себе целые файловые системы.

· #38

Точнее говоря, они кэшируются и доступ к ним упорядочен.

· #39

Это отличается от ряда систем, которые способны монтировать файловые системы как на символьных устройствах, так и на блочных.

· #40

В Linux всегда используется термин inode для обоих типов информационных узлов, в то время, как другие варианты Unix резервируют термин inode только для дисковых узлов, а узлы в памяти называют vnode. Хотя такая терминология менее запутана, мы будем использовать термин inode для обоих типов узлов, чтобы сохранять соответствие стандартам Linux.

· #41

Это режим, обычно используемый для каталога /tmp.

· #42

readv(), writev() и mmap() обсуждаются в главе 13; sendmsg() и recvmsg() упоминаются в главе 17.

· #43

Хотя такое разделение почти ясно, сокеты TCP поддерживают "внеполосные" данные, что несколько усложняет ситуацию. Такие данные выходят за пределы тем, рассматриваемых в этой книге. Их полное описание можно найти в [33].

· #44

Почти независимую; см. описание исключений из этого правила в дискуссии о dup() в конце этой главы.

· #45

Поскольку в большинстве систем SEEK_SET определена как 0, часто можно увидеть использование lseek(fd, offset, 0) вместо lseek(fd, offset, SEEK_SET). Это делает код непереносимым (или плохо читабельным), чем SEEK_SET, но подобное часто встречается в старом коде.

· #46

Все же не всегда. Если процессы разделяют файловые дескрипторы (имеются в виду дескрипторы, полученные от одного вызова open()),эти процессы разделяют одни и те же файловые структуры и одно и тоже текущее положение. Наиболее часто такое случается после вызова fork(),как обсуждается в конце этой главы. Другая ситуация, когда такое может случиться — это если файловый дескриптор передается другому процессу через доменный сокет Unix, описанный в главе 17.

· #47

Она так называется потому, что это протоколируемая версия Second Extended File System (второй расширенной файловой системы), которая была наследницей Linux Extended File System, которая, в свою очередь, была спроектирована как более сложная файловая система, чем файловая система Minix — единственная, которую изначально поддерживалась в Linux.

· #48

В действительности это хорошо работает и на файловой системе ext2. Эти две файловые системы очень похожи (можно даже смонтировать систему ext3 на ext2), и представленные программы работают на обеих. Фактически, если в исходных тексте заменить 3 на 2, программы будут функционировать точно так же.

· #49

Хотя не гарантировано, что PATH_MAX будет достаточно велик, но для большинства практических целей она подходит. Если вы имеете дело с патологическими случаями, то должны вызывать readlink() последовательно, увеличивая буфер, до тех пор, пока readlink() не вернет значение меньше чем bufsiz.

· #50

В зависимости от операционной системы, файловые структуры также известны как позиции в таблице файлов или объекты открытых файлов.

· #51

Файловый дескриптор в каждом процессе ссылается на одну и ту же файловую структуру.

· #52

Эта терминология распространена в большей части литературы по стандартам, включая единую спецификацию Unix (Single Unix Specification).

· #53

Это механизм, используемый для утилиты nohup.

· #54

Необходимость в реентерабельных функциях не ограничивается обработчиками сигналов. Многопоточные приложения должны с большой осторожностью относиться к обеспечению реентерабельности и блокировкам.

· #55

Вообще-то, не совсем так. Модель обработки сигналов ANSI/ISO С специфицирована немного иначе, чем мы ее представили. Однако она допускает сброс обработчика в значение SIG_DFL перед доставкой сигнала, что делает функции signal() в ASNI/ISO С ненадежными.

· #56

Спецификация POSIX Real Time Signal позволяет некоторые сигналам ставить в очередь, и для сигналов, работающих с ограниченными объемами данных, существенно изменяет эту модель. Сигналы реального времени обсуждаются ближе к концу этой главы.

· #57

Это аналогично типу fd_set, который используется системным вызовом select(), описанным в главе 13.

· #58

Разница между быстрыми и медленными файлами та же, что и между быстрыми и медленными системными вызовами, и она обсуждается в главе 11.

· #59

Имеются и другие отличия между этими вызовами; они касаются многопоточных программ, которые в настоящей книге не рассматриваются.

· #60

В действительности она отправляет сигнал текущему потоку текущего процесса.

· #61

Эти флаги определены в Single Unix Specification. Многие из них имеют имена, отличающиеся от описанных в тексте.

· #62

Хотя ссылка на память, которая может быть заполнена, может работать в некоторых системах, это не является переносимым. Некоторые реализации malloc() возвращают память операционной системе, что при обращении к возвращенной памяти вызывает ошибку сегментации; другие — перезаписывают части заполненной памяти служебной информацией.

· #63

Применение sigprocmask() и pause() для получения требуемого поведения может вызвать состояние состязаний, если сигнал, появление которого ожидается, поступит между этими двумя системными вызовами.

· #64

Более подробно о дампах памяти рассказывается в главе 10.

· #65

Хотя пользователи могут посылать SIGCHLD любым процессам, которыми они владеют, программы не обладают возможностью должным образом реагировать на непредвиденные сигналы.

· #66

В табл. 12.2 перечислены функции, которые могут отсутствовать в некоторых, а может, даже во всех системах Linux. Мы включаем все функции, которые POSIX специфицирует в качестве безопасных для вызова из обработчиков сигналов.

· #67

Термин реальное время употребляется здесь неправильно, поскольку это расширение не делает попыток обеспечить гарантии времени задержки при доставке сигнала. Однако средства, которые оно добавляет, удобны для построения реализаций систем реального времени.

· #68

До появления стандарта POSIX приложение могло обращаться к struct sigcontext за информацией того же рода, что теперь представляет siginfo_t, и термин "контекст" остался от этой старой реализации.

· #69

Этот третий параметр на самом деле указывает на структуру struct ucontext, которая позволяет процессам выполнять полное переключение контекстов в пользовательском пространстве. Данные вопросы выходят за пределы тем, рассматриваемых в настоящей книге, но это хорошо документировано в Single Unix Specification.

· #70

Существует гораздо больше значений si_code, нежели мы обсуждаем здесь, и эти значения имеют отношение к асинхронному вводу-выводу, очередям сообщений и таймерам реального времени, что выходит за границы тем, обсуждаемых в книге.

· #71

Он также принимает специальное значение SIGTRAP, которое используется отладчиками, и SIGPOLL, применяемое механизмом ненадежного асинхронного ввода-вывода. Ни один из них не описан в настоящей книге, поэтому подробности об этих сигналах не включены в табл. 12.3.

· #72

Вспомните, что SIGCHLD посылается не только при завершении дочернего процесса, но и при его приостановке или возобновлении работы.

· #73

Дополнительные примеры обработки сигналов вы можете найти в программах для аренды файлов (глава 13), управления терминалом (глава 16) и работы с интервальными таймерами (глава 18).

· #74

Это похоже на тип sigset_t, используемый для шаблонов сигналов.

· #75

Когда сетевой сокет прослушивается (listen()) и готов к приему (accept()), считается, что он готов к считыванию для целей select(); информацию о сокетах можно найти в главе 17.

· #76

Если сравнить это с параметром numfds для poll(), то можно понять, почему возникают затруднения.

· #77

Кроме некоторых экспериментальных ядер серии 2.1.

· #78

Когда Линус Торвальдс впервые реализовал select(), неспособность ядра BSD обновлять timeout была отмечена как ошибка на man-странице для select(). Вместо написания ошибочного кода Линус решил "исправить" эту ошибку. К сожалению, комитеты по стандартам одобрили поведение BSD.

· #79

Фактически ядро устанавливает обратный вызов для каждого файла, а затем, когда происходит событие, активизирует обратный вызов. Этот механизм устраняет проблемы масштабируемости при очень большом количестве файловых дескрипторов, поскольку опрос не используется в каждой точке.

· #80

EPOLLET — это еще одно значение, которое может иметь events, переключающее epoll с запуска уровнем на запуск фронтом сигнала. Эта тема выходит за рамки настоящей книги, и epoll, запускаемую фронтом, следует применять только в особых случаях.

· #81

Структура, показанная в тексте, предоставляет правильные размеры элементов на большинстве платформ, но они неправильны для машин, в которых int имеет 64 бита.

· #82

Эту программу необходимо запускать от имени root для наборов, содержащих более 1000 дескрипторов.

· #83

Настоящее тестирование не гарантирует статистическую точность. Был проведен лишь один тестовый прогон, поэтому результаты поначалу будут неустойчивыми, что, однако, исчезнет после большого количества повторов.

· #84

Сохранение копии памяти может показаться не столь важным, но благодаря эффективному механизму кэширования Linux, эти задержки копий являются самой медленной частью записи в файлы данных, в которых нет набора O_SYNC.

· #85

Хотя большинство устройств символьного ввода-вывода не могут быть отображены, /dev/zero отображается именно для этого типа приложений.

· #86

Ошибка сегментации возникнет при попытке доступа к нераспределенной странице.

· #87

В будущем это может измениться, поскольку в ядре реализуются мелкомодульные системные полномочия.

· #88

Файл /etc/passwd обновляется только процессами, создающими новую копию файла с модификациями и затем заменяющими оригинал с помощью системного вызова rename(). Поскольку такая последовательность является атомарной, процессы могут считывать из etc/passwd в любое время.

· #89

Файловая система Andrew Filesystem (AFS), доступная в Linux, но не включенная в стандартное ядро, поддерживает O_EXCL во всей сети.

· #90

Эта ситуация более сложна для потоков. Многие ядра и библиотеки Linux рассматривают потоки как разные процессы, что увеличивает потенциал возникновения конфликтов файловых блокировок между потоками (а это не совместимо со стандартной моделью потоков POSIX). Linux предлагает более традиционную модель потоков, при которой файловые блокировки разделяются между всеми потоками одного процесса, но в многопоточных программах лучше применять потоковые механизмы блокировки POSIX, а не полагаться на поведение файловых блокировок.

· #91

Эта манипуляция блокировками происходит атомарно — не имеет значения, какая часть области разблокирована.

· #92

Эффект, производимый вызовами fork() и exec() на файловые блокировки, является наиболее существенным отличием между файловой блокировкой POSIX (а, следовательно, и блокировкой lockf()) и файловой блокировкой flock() в BSD.

· #93

Одним из самых частых пользователей аренды файлов является файловый сервер Samba, позволяющий клиентам кэшировать свои записи для увеличения производительности.

· #94

Если тот факт, что аренда записи уведомляет процесс об открытии файла для чтения, может показаться несколько странным, посмотрите на него с точки зрения процесса, получающего аренду. Ему необходимо знать, делает ли другой процесс читать файл, только в случае, когда основной процесс сам что-либо записывает в этот файл.

· #95

Ядра предшествующих версий при успешной операции возвращает ноль либо единицу, тогда как более новые ядра всегда возвращают в данном случае ноль. В другом случае проверка на положительное или отрицательное значение работает нормально.

· #96

Если один сигнал используется для аренды множества файлов, убедитесь, что сигнал является сигналом реального времени, так что множество событий аренды ставятся в очередь. Если используется обычный сигнал, он может потеряться либо события аренды могут возникать через очень короткие промежутки времени.

· #97

До тех пор пока O_NONBLOCK не будет определен как флаг open(); в этом случае возвращается EWOULDBLOCK.

· #98

Они так именуются, поскольку чтение разбрасывает данные по всей памяти, а запись собирает данные из разных областей памяти. Они также известны как векторное чтение и запись. Этим объясняется наличие "v" в конце readv() и writev().

· #99

Эта эмулированная версия в большинстве случаев ведет себя корректно, но действует не так, как фактический системный вызов, если сигналы принимаются во время его выполнения.

· #100

Это верно; PATH_MAX не является фактическим пределом. POSIX считает его неопределенным, что обычно является эквивалентом "не используйте его".

· #101

Имя этого пути эквивалентно более простому /usr/bin/less.

· #102

Функции ftw() необходимо выполнять stat() для каждого файла для выяснения, является ли он каталогом, и передача этой информации обратному вызову во многих случаях избавляет последний от необходимости повторного выполнения stat() для файлов.

· #103

Это то же, что и метод, используемый для владения файлами (глава 13).

· #104

Обработчик сигналов все еще следует регистрировать с помощью флага SA_SIGINFO, чтобы файловый дескриптор надлежащим образом получил доступ к сигналу.

· #105

Остановленные процессы, однако, не могут генерировать сигналы, поэтому они также не могут перезапускаться.

· #106

Обычно клавиатурной комбинацией приостановки является <Ctrl+Z>. Программа stty позволяет пользователям менять эту комбинацию. Подробнее это рассматривается в главе 16.

· #107

То есть устройства, используемые как для ввода, так и для вывода.

· #108

Реализации Unix старого типа предоставляли эту функцию с помощью TIOCSPGRP ioctl(), до сих пор поддерживаемого Linux. Для сравнения, tcsetpgrp() можно реализовать как ioctl(ttyfd, TIOCSPGRP, &pgrp).

· #109

Более подробно о сигналах и их взаимодействии с управлением заданиями рассказывается в главе 12.

· #110

На man-странице setserial описан способ обхода этого ограничения, специфический для Linux.

· #111

Обратите внимание: "бит в секунду" ("бит/с"), а не "бод". Бит в секунду определяет интенсивность передачи информации. Бод является техническим термином, описывающим смены фаз в течение секунды. Бод не соответствует termios, но слово бод, к сожалению, попало в названия некоторых флагов termios, не рассматриваемых в этой книге.

· #112

Например, приложения настройки сетевых протоколов, передающие информацию с помощью устройств tty.

· #113

B134 в действительности равняется 134,5 бит/с, скорость, используемая устаревшим терминалом IBM.

· #114

Linux также использует c_cflag для хранения скорости, но не стоит на это полагаться. Вместо этого применяйте cfsetospeed() и cfstispeed().

· #115

Ядра 2.6.x, рассматриваемые в настоящей книге, поддерживают как версию 4, так и версию 6 (на последнюю обычно ссылаются как на IPv6 из набора TCP/IP).

· #116

Кстати, именно так работают сети на основе коммутации пакетов. Альтернативная конструкция, сети с коммутацией каналов, более похожа на телефонные соединения. Однако они не часто используются при организации компьютерных сетей.

· #117

Вот почему криптография приобрела такую значимость с тех пор как появилась всемирная сеть Internet.

· #118

Многие высокоуровневые протоколы, такие как BOOTP и NFS, построены на основе UDP.

· #119

Допустимы еще несколько значений данного параметра, однако они редко применяются в коде приложений.

· #120

Системный вызов connect() может также быть неблокируемым, что позволит пользователям гораздо быстрее открывать несколько TCP соединений (он позволяет продолжать работу программы, в то время как выполняется процесс синхронизации TCP). Подробности по этой теме можно найти в [33].

· #121

Различные формы select() помечают сокет как открытый для чтения, тогда как accept() не может блокировать его, даже если сокет не помечен как неблокируемый. Для обеспечения максимальной переносимости функцию select() необходимо применять только для принятия соглашений с неблокируемыми сокетами, хотя в системе Linux это фактически не нужно. Причины этого подробно рассматриваются в [33].

· #122

Варианты BSD не поддерживают такую модель поведения, в таких системах ошибки проходят без отчетов.

· #123

И для bind(), и для connect() процесс должен иметь права на выполнение для каталогов, через которые проходит поиск путевого имени (почти как при открытии стандартных файлов).

· #124

Исходя из условий реального мира, большинство серверных программ должны быть параллельными. Однако многие из них фактически созданы как итерационные сервера. Например, Web-серверы, в основном, обрабатывают только одно соединение за раз через данный процесс. Для того чтобы разрешить соединение нескольким клиентам, сервер организован в виде множества отдельных процессов. Это делает создание Web-сервера более простым. Если ошибка прерывает работу одного из таких процессов, она затрагивает только одно клиентское соединение.

· #125

Это иногда называется передачей прав доступа.

· #126

Несмотря на то что это может показаться очевидным, некоторые протоколы позволяют отправителю использовать любой порядок байтов и в зависимости от получателя преобразовывать информацию в соответствующем порядке. Это приводит к увеличению производительности, если взаимодействуют подобные механизмы, за счет повышения сложности алгоритма.

· #127

Все процессоры Intel и совместимые с Intel хранят данные с прямым порядком байтов, поэтому здесь получение права преобразования очень важно для корректной работы программ.

· #128

Информация о IANA доступна по адресу http://www.iana.org.

· #129

Либо, все чаще и чаще, чтобы скрыть их от широкополосных поставщиков Internet-услуг, которые не хотят разрешить своим рядовым клиентам запускать серверы на домашних машинах.

· #130

Однако она может оказаться троянским конем, запущенным привилегированным пользователем.

· #131

Значения для неустановленных IPv4-адресов содержатся в константе INADDR_ANY, которая является 32-битным числом.

· #132

Эти примеры взяты из документа RFC 1884, в котором определена структура адресации IPv6.

· #133

Это так называемый неустановленный адрес для IPv6.

· #134

Если у вас большой опыт в программировании сокетов (или вы сравниваете данную книгу с ее первым изданием), то вы обязательно заметите, что функции, применявшиеся для преобразования имен, значительно изменились. Эти изменения позволяют создавать программы абсолютно независимо от того протокола, который они используют. Теперь гораздо легче разрабатывать программы, работающие как на IPv4-, так и на IPv6-машинах. Они также должны распространяться на остальные протоколы, хотя функция getaddrinfo() в данный момент работает только для IPv4 и IPv6.

· #135

Адрес обратной связи — это специальный адрес, который позволяет программам взаимодействовать через TCP/IP с приложениями только на одной и той же машине.

· #136

Для TCP-портов данная комбинация не может использоваться в течение двух минут.

· #137

Это называется трехсторонним квитированием TCP, которое на самом деле проходит несколько сложнее, чем описано выше.

· #138

Этот процесс называется сетевой загрузкой.

· #139

UDP-сокеты, которые имеют постоянные пункты назначения, присвоенные через функцию connect(), иногда называются присоединенными UDP-сокетами.

· #140

Есть также возможность превратить подключенный сокет в неподключенный с помощью функции connect(), однако эта процедура не стандартизирована. Если вам все же необходимо ее применить, обратитесь к [33].

· #141

Данные функции могут применяться для передачи данных через любой сокет, и иногда возникают причины для использования их в TCP-соединениях.

· #142

Возможно также применение системных вызовов sendmsg() и recvmsg(), однако необходимость в этом встречается редко.

· #143

Полное описание tftp можно найти в [33] и [34].

· #144

Спецификация tftp-протокола требует, чтобы серверы посылали данные клиенту на номер порта, отличающийся от порта, на котором сервер ожидает новые соединения. При этом нетрудно создать параллельный сервер, поскольку каждый сокет сервера предназначен только для одного клиента.

· #145

Применение этой структуры делает невозможным расширение данных функций на IPv6 без изменения их интерфейса.

· #146

Функции, использующие статическую память для сохранения результатов, усложняют построение многопоточных приложений, поскольку в код приложения требуется добавлять блокировки для защиты этих статических буферов.

· #147

Наверное, не существует IPv6-программ, использующих struct hostaddr, однако они могут это делать. Функции, которые мы обсуждаем здесь, по умолчанию возвращают только информацию IPv4. Мы не будем рассматривать применение этих функций с IPv6.

· #148

UTC — Universal Coordinated Time (универсальное синхронизированное время), на которое иногда ошибочно ссылаются как на UCT, приблизительно эквивалентное среднему времени по Гринвичу (GMT) и зулу. Описание всех часовых поясов выходит за рамки материала, рассматриваемого в настоящей книге.

· #149

Мы не рекомендуем применять библиотеку svgalib для графического программирования. Во многих книгах описывается программирование для X Window System, и система X предоставляет более разумный, безопасный и мобильный метод программирования графики. С другой стороны, если вы действительно собираетесь программировать для сервера X Window, то не сможете обойтись без кодирования VC. Таким образом, в любом случае данная глава окажется полезной.

· #150

Прочтите man-страницы для утилит loadkeys, dumpkeys, keytables, setfont и mapscrn.

· #151

Данный интерфейс имеет недостаток. Для него необходимо устанавливать некоторые постоянные доли секунды и осуществлять преобразование. Макрос HZ больше не является константой даже на отдельной платформе. Однако, по крайней мере, для архитектуры Intel i86 Линус Торвальдс установил, что все определенные интерфейсы в отношении HZ должны представлять синтетический интерфейс в 100 Гц. Возможно, что в будущем периодические системные часы исчезнут, в таком случае тики станут полностью искусственным понятием.

· #152

В большинстве остальных систем с виртуальными консолями или терминалами динамическое распределение для них не производится.

· #153

Отдельные системы (но не Linux) инициируют автоматическое переключение, если вызывается консоль, которая не исполняется в текущий момент.

· #154

Библиотека curses определена в X/Open. Реализация, которая входит в состав Linux, представляет собой совместимую в данный момент с X/Open XSI Curses версию базового уровня.

· #155

Эта тема логически относится к главе 20, поскольку она имеет отношение к виртуальным консолям. Однако практический смысл вынуждает поместить этот раздел в данную главу — поскольку, как упоминалось во введении, настоящую книгу можно читать и выборочно.

· #156

Популярным способом проверки в ранних ядрах Linux было создание последовательности абсолютно случайных байтов и запуск их на выполнение как программы. Кроме того, что таким методом невозможно сделать что-либо полезное, он довольно часто вызывает полную блокировку ядра. Поскольку попытки выполнения совершенно случайных последовательностей кодов не входят в "должностные инструкции" ядра, пользовательские программы не должны вызывать остановку корректной работы ядра. Таким образом, этот прием помогает находить большое число дефектов, которые необходимо устранить.

· #157

Атака на программное обеспечение приложений сейчас является основным способом распространения вирусов.

· #158

Системные квоты предотвращают возможность успешности такой атаки.

· #159

Словарная атака — это довольно прямолинейный метод обнаружения паролей, когда автоматическая программа прогоняет огромный список обычных паролей (таких как слова в словаре) до тех пор, пока один из них не подойдет.

· #160

ВООТР — это предшественник DHCP, позволяющий компьютерам автоматически узнавать свои IP-адреса при запуске сетевых интерфейсов.

· #161

Функция alloca() не является стандартным средством языка С, однако компилятор gcc предоставляет alloca() в большинстве поддерживаемых операционных систем. В более старых версиях gcc (до версии 3.3) alloca() не всегда должным образом взаимодействовала с массивами динамических размеров (другое расширение GNU), поэтому примите во внимание, что использовать нужно только одну из версий.

· #162

В некоторых устаревших версиях библиотеки С вместо этого возвращается -1 (если строка не помещается). Старая версия библиотеки С уже не поддерживается и не используется в защищенных программах, однако на man-странице по функции snprintf() демонстрируется код, обрабатывающий оба варианта.

· #163

К сожалению, функция clearenv() не очень хорошо стандартизирована. Она входит в последние версии POSIX, однако она была выброшена из стандарта Single Unix Standard и не доступна во всех системах типа Unix. Если вам необходимо поддерживать операционную систему, не включающую эту переменную, установите environ=NULL;.

· #164

Существует еще несколько библиотечных функций, имеющих дело с временными файлами, такие как tmpnam(), tempnam(), mktemp() и tmpfile(). К сожалению, их применение приносит небольшую пользу, поскольку они могут привести к возникновению состязаний в программах, которые невнимательно реализованы.

· #165

Система Linux позволяет программам открывать очень большое количество файлов. Процессы, работающие как root, могут одновременно открывать сотни файлов, однако большинство дистрибутивов устанавливают предел ресурсов на количество файлов, который может открывать пользовательский процесс. Этот предел также ограничивает максимальный файловый дескриптор, который можно использовать, с помощью метода dup2(), тем самым, предоставляя удобный верхний предел для закрывающего файлового дескриптора.

· #166

Еще одним способом закрытия всех файлов, открытых программой, является прохождение через каталог файловой системы процесса /proc, в котором перечислены все открытые файлы, и закрытие каждого из них. Каталог /proc/PID/fd (где PID —это pid текущего процесса) содержит символическую ссылку для каждого файлового дескриптора, открытого процессом. Имя каждой символической ссылки представляет собой файловый дескриптор, которому она соответствует. Считывая содержимое каталога, программа легко может закрыть все файловые дескрипторы, которые больше не нужны.

· #167

Один из авторов этой книги разработал набор инструментальных средств newt для управления окнами на высоком уровне на основе S-Lang; этот набор входит в состав большинства распространяемых дистрибутивов Linux.

· #168

Как это описано в базе данных terminfo.

· #169

Ошибка возникает, если получение сигнала происходит в тот момент, когда S-Lang ожидает нажатие клавиши.

· #170

Помните, что обновление физического терминала производится только с помощью функции SLsmg_refresh().

· #171

Со временем эта цифра может возрасти, однако маловероятно, что это когда-нибудь будет необходимо.

· #172

В частности, в некоторых системах это может привести к мерцанию текста.

· #173

Библиотека Berkley db была существенно расширена, и сейчас включает реализацию B-деревьев и весь спектр работы с транзакциями.

· #174

В настоящее время Berkley db разрабатывается некоммерческой организацией, которая продает альтернативные лицензии для своей библиотеки, поэтому на них вполне можно ориентироваться при разработке определенного рода приложений.

· #175

Инвертированные индексы представляют собой структуры данных, предназначенные для полнотекстового поиска.

· #176

В отличие от некоторых библиотек баз данных, использующих множество файлов с расширениями .pag и .dir, библиотека Depot использует один файл.

· #177

Хорошее описание хеш-таблиц можно найти в [11].

· #178

Это значение можно изменить только путем оптимизации базы данных с помощью функции dpoptimize(), описание которой можно найти на Web-сайте qdbm.

· #179

Несмотря на то что qdbm обеспечивает доступ к файловому дескриптору, использовать его следует осторожно. Дело в том, что все операции по чтению и записи в файл должны производиться через библиотеку qdbm; операции, не связанные с изменением данных в файле, например, блокировка или установка флага для закрытия после выполнения, допускаются.

· #180

Вернее, они возвращаются в том порядке, в котором производятся ссылки на элементы из хеш-области. Хотя это и есть порядок, он является совершенно бесполезным.

· #181

Библиотека glibc также предлагает библиотеку argp, с помощью которой можно осуществлять альтернативный вариант проверки синтаксиса параметров.

· #182

Те, кто знаком с функцией getopt(), заметят, что argInfo является единственным обязательным членом структуры struct poptOption, который отличается от члена в таблице аргументов getoptlong(). Благодаря этому сходству существенно упрощается переход от getoptlong() к popt.

· #183

Полный исходный код для данного примера можно найти в главе 23.

· #184

Распространенной ошибкой является определение массива argv как char **, а не как const char **, что является правильным вариантом. Благодаря прототипу функции poptGetContext() компилятор генерирует предупреждающее сообщение, если массив argv будет определен неправильно.

· #185

Он также добавляет параметр -?, который соответствует --help.

· #186

Макрос POPT_AUTOHELP расширяется для включения вложенной таблицы параметров, определяющей новые параметры и обратный вызов, при котором реализуются эти параметры.

· #187

Часто в подобных случаях удобно использовать POPT_CONTEXT_KEEP_FIRST.

· #188

Первоначально библиотека popt была реализована для RPM, и многие параметры запросов RPM реализованы в виде простых макросов popt.

----

Оглавление книги


Генерация: 0.109. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз