Модули
модули — это рецепт, предлагаемый операционной системой Linux для эффективного достижения многих теоретических преимуществ микроядра без снижения производительности.
Быть (модулем) или не быть?
Когда системным программистам нужно добавить в ядро Linux новую функциональную возможность, им приходится принимать принципиальное решение: создавать ли новый код так, что он будет откомпилирован как модуль, или статически компоновать этот код с ядром.
Вообще, системные программисты стараются реализовать новый код в виде модуля. Поскольку модули могут быть скомпонованы по требованию (в чем мы убедимся далее), ядру не приходится "раздуваться" от сотен редко используемых программ. Почти все высокоуровневые компоненты ядра Linux— файловые системы, драйверы устройств, форматы исполняемых файлов, сетевые слои и т. д. — могут быть откомпилированы как модули. Дистрибутивы Linux активно используют модули для обеспечения удобной работы с широким диапазоном аппаратных устройств. Например, в дистрибутиве в соответствующем каталоге находятся десятки модулей драйверов звуковых карт, хотя только один из этих модулей будет фактически загружен на конкретном компьютере.
Тем не менее часть кода Linux обязательно должна быть скомпонована статически, а это означает, что либо соответствующий компонент включен в ядро, либо он вообще не откомпилирован. Как правило, это происходит, когда компонент требует модификации каких-нибудь структур данных или некоторой функции, статически скомпонованной с ядром.
Предположим, например, что компонент должен добавить новые поля в дескриптор процесса. Подключение модуля не сможет изменить существующие структуры, такие как task struct, поскольку, даже если модуль будет пользоваться модифицированной версией структуры, весь статически скомпонованный код будет по-прежнему видеть старую версию. В результате, скорее всего, произойдет порча данных. Частичным решением проблемы будет "статическое" добавление новых полей в дескриптор процесса, чтобы они были доступны компоненту ядра, независимо от того, как он был скомпонован. Однако если этот компонент не используется, то дополнительные поля, размноженные в каждом дескрипторе процесса, будут непроизводительной тратой памяти. Если новый компонент ядра значительно увеличивает размер дескриптора процесса, то, с точки зрения производительности системы, разумнее будет добавить требуемые поля в структуру данных, только если компонент скомпонован с ядром статически.
В качестве второго примера рассмотрим компонент ядра, который замещает собой статически скомпонованный код. Совершенно ясно, что такой компонент не может быть откомпилирован в виде модуля, потому что ядро не в состоянии изменить машинный код, уже находящийся в оперативной памяти, когда оно подключает модуль. Например, невозможно подключить модуль, который меняет способ выделения страничных кадров, поскольку функции buddy-системы всегда статически скомпонованы с ядром1.
При работе с модулями перед ядром стоят две основные задачи. Первая — сделать так, чтобы остальным компонентам были доступны глобальные символы модуля, например, точка входа в его главную функцию. Кроме того, модуль должен знать адреса символов в ядре и других модулях. Таким образом, при подключении модуля должны быть и навсегда разрешены ссылки. Вторая задача заключается в слежении за использованием модулей, чтобы ни один модуль не был выгружен, когда с ним работает другой модуль или другая часть ядра. Для этой цели служит обычный счетчик ссылок.
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | Следующая страница