![]() |
Модераторы: xvr |
![]() ![]() ![]() |
|
cupper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
Может кто рассказать или навести на актуальный в данные момент материал в котором описывается как в современных ядрах происходит механизм экспорта функций ядра в модуль. Я не о том что нужно в модулей написать чтобы вызвать функцию ядра, я о самом механизме ядра/компилятора с помощью которого в скомпилином модулей оказываются толи ядреса функция в ядре толи они туда статиком в гоняются.
и что такое modpost ? Заранее спасибо. а что произойдет если например под телом функции pintk убрать строчку EXPORT_SYMBOL(printk) при компиляции в модуле уже не будет происходить связка с этой функций ? А если сделать отдельный хедер, в котором определить свою функцию printk , сделать там же EXPORT_SYMBOL(printk) и подключить в модуле при компиляции этот хедер тогда в модуле будет происходить вызов не ядерной printk а "моей из моего хедера". Ядро собирается без этого хедера. Или же получиться какая ошибка ? Экспортируемые функции разбросаны по всему ядру, экспорт их производится сразу под телом функции, а при написании модуля указываются только хередеры. Вопрос: все экспортируемые ядром функции собраны в неком одном хедеры или также размазаны по всем ? |
|||
|
||||
nickless |
|
|||
![]() Гентозавр ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2976 Регистрация: 29.8.2005 Где: Germany Репутация: 4 Всего: 181 |
Модератор: Тема перенесена из Общих вопросов по никсам
-------------------- ![]() Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies - Linus Torvalds |
|||
|
||||
MAKCim |
|
||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
вам для начала необходимо ознакомиться с форматом elf для _объектных_ файлов без этого ничего не поймете если говорить простым языком, то модуль ядра - это объединение объектных файлов (aka объектный файл), получаемых при компиляции исходного кода модуля каждый объектный файл содержит таблицу символов каждый символ в ней либо связан с конкретной секцией данного объектного файла, либо является специальным первый случай характеризуется тем, что поле индекса в дескрипторе символа в таблице содержит номер секции: 1,2,... во втором случае значение поля не индекс, а одно из специальных значений: SHN_COMMON, SHN_ABS, SHN_UNDEF (подробнее в спецификации elf) наш случай - SHN_UNDEF ядро при загрузке модуля читает таблицу символов и если индекс в дескрипторе равен SHN_UNDEF, то осуществляет поиск символа посредcтвом вызова функции ядра resolve_symbol код а вот уже resolve_symbol непосредственно связана с EXPORT_SYMBOL расммотрим определение EXPORT_SYMBOL
мы видим, что экспортирование - это ни что иное как создание переменной типа struct kernel_symbol в спец. секции __ksymtab при сборке образа ядра все объекты struct kernel_symbol для экспортируемых переменных линейно располагаются в этой секции ее адрес определяется в скрипте компоновщика и участвует в разрешении символом им же так вот, в resolve_symbol просто осуществляется поиск символа в данной секции если же EXPORT_SYMBOL используется в модуле ядра, то при загрузке модуля в его дескриптор заносится адрес этой секции (она - часть модуля) и опять таки, в resolve_symbol, если символ не найден в __ksymtab ядра, то по очереди просматриваются __ksymtab каждого загруженного модуля modpost много всего делает как пример, динамически формирует <module>.mod.c файл, в котором определяется и инициализируется дескриптор модуля (struct module) -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||
|
|||||
cupper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
Суть улавливаю. В принцепи все так и представлялось, только без подробностей реализации.
А теперь такой вопрос: а что если в ядре у экспортируемых функций убрать непосредственно их экспорт (EXPORT_SUMBOL(bla)), она тогда станет не экспортируемой, ее адрес не появится в списке. А что произойдет в модуле ? на месте вызова экспортируемой функции вероятно вылезет ошибка и неизвестной/недоступной функции. И если создать отдельный хедер, в котором реализовать функцию с тем же именем и параметрами (идентичную по определению, экспортируемой) и подключать его в модуле, тогда на месте вызова ранее экспортируемой функции будет вставляться моя функция ? Или же будет по прежнему адрес функции ядра но на этапе разрешения символов будет получен игнор ? PS. нет, я не было хакер, не было кодер ![]() |
|||
|
||||
MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
модуль не загрузится
да -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
cupper |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
Я еще немного по вытягиваю из вас инфу ![]() при написании модуля подключаются только хедера ядра, там есть определения функций, но нету их реулизаций, тогда каким путем при компиляции модуля устраняется ошибка о том что функция не реализованна ? Я понимаю то что по логики на месте вызова функции должен ставить какойто "символ" по которому потом при загрузке модуля происходит функции яд ядра (с соответствующим "символом"). Я так пологая что такое возможно если бы при компиляции модуля был бы некий файл с примерно следующей логикой имя_функции -> "символ" имя_функцииё -> "символ1" и при компиляции модуля например известно о всех возможных экспортируемых функция, это обеспечивало бы замену имени функции на некий "символ" (идентификатор) по которому ядро ищет функцию в ядре которая была связана с соответствующим "символом". Я конечно скорее всего ошибаюсь, но я тогда не понимаю как решается этот вопрос. И если он решается именно так, то даже если в ядре убрать EXPORT_SYMBOL (что на этапе загрузки в ядро помешало бы связыванию с функций ядра) это не позволит реализовать такую подмену на этапе компиляции. Но что то мне подсказывает что я несу редкостную ахинею ![]() ![]() |
||||
|
|||||
MAKCim |
|
||||||||||||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
вернемся к формату elf существует 4 типа файла: исполняемый (executable), динамически загружаемый (shared object), статический (static object), объектный (relocatable) модуль ядра - объектный файл, точнее объединение объектных файлов, полученных при компиляции скомпилируйте след. программу
и посмотрите через readelf с ключом --all
в таблице символов будет находится кроме всего прочего символ printf с индексом UND (тип SHN_UNDEF из пред. примера), а на месте вызова функции в main - релокация, ссылающаяся на этот символ по сути main.o - это и есть модуль ядра (отличия в данном случае не столь существены) ошибка же отсутствия определения возникает при создании статических, динамически загружаемых или исполняемых файлов
это называется релокация в объектном файле есть таблица релокаций, каждый элемент в ней - дескриптор основные поля: offset (P), symbol (S), addend (A), type (T) T определяет, как использовать P, S и A, чтобы получить значение релокации в примере выше T = R_X86_PC32, а значение высчитывается V = S - P + A S - адрес символа (printf), P - где будет расположено значение релокации (смещение в секции кода main.o), A = 4 т. е., если к примеру P = 0xA, а адрес printf 0x400100, то 32-х разрядное значение, записываемое по адресу .text + 0xA будет равно 0x400100 - 0xA + 4 = 0x4001FA вызов printf - direct call адрес перехода = операнд + IP след. за call инструкции т. е. релокация в данном случае и есть
имя функции уже есть символ типа SHN_UNDEF -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||||||||||||
|
|||||||||||||||
cupper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
спасибо за наиподробнейшее объяснение, но из выше сказанного я понимаю что даже если реализовать в отдельном файле свою функцию то подмены не получиться ?
|
|||
|
||||
MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
-------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
cupper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
т.е. он вначале посмотрит что если эта функция реализована в хедерах (что не просто ее определение есть, а именно что есть тело функции) то он возьмет его, а если нету тела то он подумает что это экспортируемая функция ?) Я в начале имел не осторожность сказать "реализовать функцию и подключить свой хедер". Увы это было не правильно, если сделать еще один .h файл с определение аналогичной экспорируемой функции, не отключаю хедер ядра с таким же определение функции, то должен возникнуть конфликт имен. Далее я подумал о том что если оставить стандартный хедер с определением функции, сделать .c файл в который подключить этот хедер и написать тело этой функции то в этом случаем, модуль захавает реализацию этой функции из .c файла и небудет пытаться заменить ее символ экспортируемой функции... Это сообщение отредактировал(а) cupper - 23.3.2010, 15:36 |
|||
|
||||
MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
никто ничего смотреть не будет если функция, объявленная в хидере, определена в одном из *.c файлов модуля, то при сборке модуля компоновщик в одном из *.o файлов найдет определение соответствующего символа и в конечном *.ko файле он не будет иметь индекс SHN_UNDEF и ядро при загрузке просто вычислит его адрес с учетом смещения и адреса секции нет точнее да, но только для static inline функций, которые не подставляются компилятором -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
cupper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
бальшое спасибо за терпение и разъяснения ![]() |
|||
|
||||
MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
cupper,
не за что ![]() -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
cupper |
|
||||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
У меня появился еще вопрос, разрешите задать ?)
Все выше описанное очень походит для решения данной подзадачи, если бы не одно НО. Оно заключается в следующем. Рассмотрим функцию kazlloc реализованную в include/linux/slab.h
Как видно это простой врапер на функцию kmalloc которая, незнаю как правильно сказать, модели памяти зависимая, тобишь имееет свою реализацию для slab slob slub Вопрос 1: Метка inline тут делает эту функцию "вкомпилируемой" в обжект модуля? Поэтому данную функцию даже не требуется делать экспортируемой. Продолжаем, функция kmalloc это также можно сказать врапер, но уже побольше, реализованная в include/linux/slab_def.h include/linux/slob_def.h include/linux/slub_def.h Рассмотрим реализацию для slab
Уже мясо. На сколько мне известно метка __always_inline это чтото типо inline "беспесды". Тобишь если просто inline может быть в каком то случае отменен компилятором то функция с такой меткой 100% вкомпилиться в модуль. Из это й же функции уже начинаются вызываться экспортируемый функции, например __kmalloc
Уже без меток inline и с EXPORT_SYMBOL. Т.е. вплоть до таких вызова непосредственно экспортируемых, функции фраперы типа kzalloc будут вкомпиливаться в модуль. Зачем это было сделано и что мешало сделать kzalloc тоже укспортируемой, я думаю мало кому известно. Но вот именно такое построение интерфейсов портит все до чего я докапывался в верхних постах. Т.е. нельзя реализовать два тела функции kzalloc, одно по идее находящееся в slab.c являющееся экспортирумой функция и использумой ядром при сборке. А другое реализованное в файле my_slab.c как inline которое не использовалось бы при сборке ядра но использовалось бы при сборке модуля для того чтобы вкомпилится в него и таким образом сделать подмену. Нельзя именно потому что тело функции уже находится в хедере (нельзя подключить хедер к .с файлу и повторно реализовать тело функции). Был придуман выход из этой ситуации. Он заключается в следующем. В файле slab.h в котором реализованная функция kzalloc, сделать вот так
Вопрос 2: Можно ли один и тот же конфиг, сделать при компиляции файлов ядра выключенным а при сборке модулей включенным ? Если да то как ?) (я плохо владею макфайлами, а попытавшись что то понять в ядровом, я потерялся в нем). По хорошему нужно дать возможность при конфигурировании конфига включать и выключать эту функциональность. Это можно сделать следующим образом: 1. В основном конфиге не будет вообще MY_HACK_CONFIG, будет некая другая например CONFIG_FUCK_HUCK 2. На этапе собрки модулей в макфайле будет проверятся, включенали опция CONFIG_FUCK_HUCK, если да то компилировать модули с включеной MY_HACK_CONFIG. Таким образом при включенной или выключенной CONFIG_FUCK_HUCK ядро всегда будет собираться только со своей функцией, а модули будут собиратся с подмененой функций только при включеной CONFIG_FUCK_HUCK. Можно ли это сделать и как я тоже не знаю ![]() |
||||||||
|
|||||||||
MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
может, натолкнет на мысль, есть стандартный макрос MODULE, который определен при компиляции исходного кода модуля
т. е. ядерную функцию оберни в #ifndef MODULE...#endif а свою реализацию в #if defined MODULE && defined CONFIG_FUCK_FUCK...#endif -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С/С++: Программирование под Unix/Linux" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |