Linux - модули на ядрото
В съвременните ядра, когато хардуерът е свързан, модулите се свързват автоматично и това събитие се обработва от демона udev, който създава съответния файл на устройството в директорията "/dev". Всичко това се прави, ако съответният модул е правилно инсталиран в дървото на модула. При файловите системи ситуацията е същата: когато се опитате да монтирате файлова система, ядрото автоматично зарежда необходимия модул и извършва монтирането. Ако нуждата от модул не е толкова очевидна, ядрото не го зарежда само. Например, за да поддържате функцията за криптиране на устройство за цикъл, трябва ръчно да заредите модула „cryptoloop“, а за директно криптиране трябва да заредите модула за алгоритъм за криптиране, например „blowfish“.
Търсене на необходим модул
Модулите се съхраняват в директорията "/lib/modules/" като файлове с разширение "ko". За да получите списък с всички модули от дървото, можете да изпълните командата за търсене на всички файлове с разширение "ko" в директорията с модулите на текущото ядро:
намери /lib/modules/`uname -r` -name '*.ko'
Полученият списък ще даде известна представа за наличните модули, тяхното предназначение и имена. Например пътят "kernel/drivers/net/wireless/rt2x00/rt73usb.ko" ясно показва, че този модул е драйвер за безжично устройство, базиран на чипа rt73. По-подробна информация за даден модул може да бъде получена чрез командата modinfo:
Зареждане и разтоварване на модули
Можете да заредите модул в ядрото, като използвате две команди: "insmod" и "modprobe", които се различават една от друга по способността да изчисляват и удовлетворяват зависимости. Командата "insmod" зарежда конкретен файл с разширение "ko" и ако модулът зависи от други модули, които все още не са заредени в ядрото, командата ще издадегрешка и няма да зареди модула. Командата "modprobe" работи само с дървото на модула и е възможно да се зарежда от там само по име на модул, а не по име на файл. Това предполага обхвата на тези команди: с помощта на "insmod" модулен файл се зарежда от произволно място във файловата система (например потребителят е компилирал модулите и е решил да провери неговата производителност, преди да го прехвърли в дървото на ядрото), а "modprobe" се използва за зареждане на готови модули, включени в модулното дърво на текущата версия на ядрото. Например, за да заредите модула на ядрото "rt73usb" от дървото на ядрото, включително всички зависимости и деактивиране на хардуерното криптиране, изпълнете командата:
# modprobe rt73usb nohwcrypt=0
Зареждането на този модул с командата "insmod" ще се случи по следния начин:
# insmod /lib/modules/2.6.38-gentoo-r1/kernel/drivers/net/wireless/rt2x00/rt73usb.ko nohwcrypt=0
Но трябва да запомните, че когато използвате "insmod", всички зависимости ще трябва да се заредят ръчно. Следователно тази команда постепенно се заменя с командата "modprobe".
След като заредите модул, можете да проверите присъствието му в списъка с модули, заредени в ядрото, като използвате командата "lsmod":
# lsmod grep rt73usb
rt73usb | 17305 | 0 | |
crc_itu_t | 999 | 1 | rt73usb |
rt2x00usb | 5749 | 1 | rt73usb |
rt2x00lib | 19484 | 2 | rt73usb, rt2x00usb |
От изхода на командата става ясно, че модулът е зареден и използва други модули в работата си. За да го разтоварите, можете да използвате командата "rmmod" или същата команда "modprobe" с ключ "-r". И двете команди трябва да предадат само името на модула като параметър. Акомодулът не се използва, той ще бъде разтоварен, а ако е използван, ще се генерира грешка и всички модули, които зависят от него, ще трябва да бъдат разтоварени:
# rmmod rt2x00usb ГРЕШКА: Модулът rt2x00usb се използва от rt73usb # rmmod rt73usb # rmmod rt2x00usb
Когато даден модул бъде разтоварен, всички предоставени от него функции ще бъдат премахнати от таблицата на ядрото.
Различните дистрибуции предоставят различни механизми за автоматично зареждане на модули. Няма да навлизам в подробности тук, те са различни за всяка дистрибуция, но един метод за зареждане винаги е ефективен и удобен: използването на стартови скриптове. В същите RedHat системи можете да пишете команди за зареждане на модул директно в "/etc/rc.d/rc.local" с всички опции. Конфигурационните файлове на модула се намират в директорията "/etc/modprobe.d/" и имат разширение "conf". Тези файлове основно изброяват алтернативни имена на модули, техните параметри, използвани при зареждането им, както и черни списъци, които са забранени за зареждане. Например, за да може горният модул да бъде незабавно зареден с опцията „nohwcrypt=1“, трябва да създадете файл, в който да запишете реда:
опции rt73usb nohwcrypt=1
Черният списък на модулите се съхранява основно във файла "/etc/modules.d/blacklist.conf" във формат "черен списък". Тази функция се използва за предотвратяване на зареждането на бъги или конфликтни модули.
Сглобяване на модула и добавянето му към дървото
Понякога необходимият драйвер не е в ядрото, така че трябва да го компилирате ръчно. Такъв е и случаят, ако допълнителен софтуер трябва да добави свой собствен модул към ядрото, катоvmware,virtualbox или пакета за поддръжка на картиNvidia. Самият процес на компилиране не се различава от процеса на асемблиране на програмата, но все пак има определени изисквания. Първо, имате нужда от компилатор. Обикновеноинсталирането на "gcc" инсталира всичко необходимо за изграждане на модула. Ако нещо липсва, програмата за изграждане ще ви каже за това и ще трябва да инсталирате липсващите пакети. Второ, имаме нужда от заглавните файлове на ядрото. Въпросът е, че модулите на ядрото винаги се изграждат заедно с ядрото, използвайки неговите заглавни файлове, защото всяко отклонение и несъответствие между версиите на модула и зареденото ядро води до невъзможност за зареждане на този модул в ядрото. Ако системата е базирана на ядрото на дистрибуцията, тогава трябва да инсталирате пакети със заглавни файлове на ядрото. В повечето дистрибуции това са пакетите "kernel-headers" и/или "kernel-devel". Това ще бъде достатъчно за сглобяване на модулите. Ако ядрото е създадено ръчно, тогава тези пакети не са необходими: достатъчно е да направите символна връзка "/usr/src/linux", сочеща към конфигурираното дърво на изходния код на текущото ядро. След компилирането на модула, изходът ще бъде един или повече файлове с разширение "ko". Можете да опитате да ги заредите с командата "insmod" и да тествате работата им. Ако модулите са заредени и работят (или сте твърде мързеливи, за да заредите ръчно зависимости), трябва да ги копирате в дървото на модулите на текущото ядро, след което е необходимо да актуализирате зависимостите на модула с командата “depmod”. Той ще обхожда дървото на модула рекурсивно и ще записва всички зависимости във файла "modules.dep", който след това ще бъде анализиран от командата "modprobe". Модулите вече са готови за зареждане с командата modprobe и могат да бъдат заредени по име с всички зависимости. Заслужава да се отбележи, че този модул няма да работи при актуализиране на ядрото. Ще са необходими нови заглавни файлове и модулът ще трябва да бъде изграден отново.
„Слушайте“ какво казва ядрото
Ако има и най-малък проблем с модула, трябва да погледнете съобщенията на ядрото. Пускат се по команда."dmesg" и, в зависимост от настройките на syslog, към файла "/var/log/messages". Съобщенията на ядрото могат да бъдат информативни или за отстраняване на грешки, което ще помогне за идентифициране на проблем по време на работа на модула или могат да докладват за грешка по време на работа с модула, например недостатъчни символи и зависимости, неправилно предадени параметри. Например модулът "rt73usb", обсъден по-горе, изисква параметър bool, което означава, че параметърът може да приема или "0", или "1". Ако се опитате да изпратите "2", системата ще даде грешка:
# modprobe rt73usb nohwcrypt=2 ФАТАЛНО: Грешка при вмъкване на rt73usb (/lib/modules/2.6.38-gentoo-r1/kernel/drivers/net/wireless/rt2x00/rt73usb.ko): Невалиден аргумент
Грешката „Невалиден аргумент“ може да говори за всичко, самото ядро не може да запише грешката в конзолата, а само да я запише в системния журнал с помощта на функцията „printk“. Като прегледате регистрационните файлове, вече можете да разберете каква е грешката:
# dmesg tail -n1 rt73usb: '2' невалиден за параметър 'nohwcrypt'
В този пример само последният ред е отпечатан с грешка, за да не се претрупва статията. Модулът може да напише няколко реда, така че е по-добре да изведете пълния дневник или поне последните десет реда. Грешката вече е лесна за намиране: стойността "2" не е приемлива за параметъра "nohwcrypt". След коригиране, модулът ще се зареди правилно в ядрото.
От всичко казано по-горе може да се направи едно заключение: ядрото на Linux играе по свои собствени правила и прави сериозни неща. Това обаче е просто програма, всъщност не е толкова различна от другите обикновени програми. Разбирането, че ядрото не е толкова страшно, колкото изглежда, може да бъде първата стъпка към разбирането на вътрешната работа на системата и в резултат на това да помогне за бързото и ефикасно решаване на проблемите, с които всеки Linux администратор се сблъсква в ежедневието.работа.