Internet Windows Android
Kengaytirish

Linux yadrosini sozlash va kompilyatsiya qilish. Kategoriya arxivlari: Yakunlash va ishga tushirish funksiyalarini aniq belgilovchi drayverlarni dasturlash

Nega yadroni o'zingiz kompilyatsiya qilasiz?
Ehtimol, yadroni kompilyatsiya qilish haqida so'raladigan asosiy savol: "Nega buni qilishim kerak?"
Ko'pchilik o'zini aqlli va ilg'or "Linuxoid" sifatida ko'rsatish uchun buni vaqtni behuda sarflash deb biladi. Aslida yadroni kompilyatsiya qilish juda muhim. Aytaylik, siz yangi noutbuk sotib oldingiz va veb-kamerangiz ishlamayapti. Sizning harakatlaringiz? Siz qidiruv tizimiga qaraysiz va ushbu masala bo'yicha muammoning echimini qidirasiz. Ko'pincha veb-kamerangiz siznikidan yangiroq yadroda ishlayotganligi aniqlanishi mumkin. Qaysi versiyangiz borligini bilmasangiz, terminalga uname -r ni kiriting, natijada siz yadro versiyasini olasiz (masalan, linux-2.6.31-10). Yadro kompilyatsiyasi samaradorlikni oshirish uchun ham keng qo'llaniladi: haqiqat shundaki, tarqatishda yadrolar sukut bo'yicha "hamma uchun" tuzilgan, shuning uchun u sizga kerak bo'lmasligi mumkin bo'lgan juda ko'p sonli drayverlarni o'z ichiga oladi. Shunday qilib, ishlatilgan uskunani yaxshi bilsangiz, konfiguratsiya bosqichida keraksiz drayverlarni o'chirib qo'yishingiz mumkin. Bundan tashqari, tizimning bit chuqurligini o'zgartirmasdan 4 Gigabaytdan ortiq operativ xotirani qo'llab-quvvatlashni yoqish mumkin. Shunday qilib, agar siz hali ham o'z yadrongizga ega bo'lishingiz kerak bo'lsa, keling, kompilyatsiya qilishni boshlaylik!

Yadro manbasini olish.
Birinchi narsa, yadro versiyasining to'g'ri manba kodini olishdir. Odatda eng so'nggi barqaror versiyani olishingiz kerak. Yadroning barcha rasmiy versiyalari kernel.org saytida mavjud. Agar sizda allaqachon X server o'rnatilgan bo'lsa (uy kompyuteri), u holda siz sevimli brauzeringizdagi saytga o'tishingiz va tar.gz arxivida (siqilgan gzip) kerakli versiyani yuklab olishingiz mumkin. Agar siz konsolda ishlayotgan bo'lsangiz (masalan, siz hali X serverini o'rnatmagansiz yoki serverni sozlayotgan bo'lsangiz), matn brauzeridan foydalanishingiz mumkin (masalan, elinks). Siz standart wget yuklab olish menejeridan ham foydalanishingiz mumkin:
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.33.1.tar.gz
Iltimos, shuni yodda tutingki, siz kerakli versiya raqamini bilishingiz kerak.

Manba arxivini ochish.
Arxivni manba kodi bilan olganingizdan so'ng, arxivni jildga ochishingiz kerak. Buni grafik fayl boshqaruvchilaridan (delfin, nautilus va boshqalar) yoki mc orqali amalga oshirish mumkin. Shu bilan bir qatorda, an'anaviy tar buyrug'idan foydalaning:
tar -zxvf path_to_archive
Endi sizda papka va manba kodingiz bor, buyruq yordamida unga o'ting cd kernel_source_code_directory(papkadagi kataloglarni ro'yxatga olish uchun ls buyrug'idan foydalaning).

Yadro konfiguratsiyasi.
Yadro manba katalogiga o'tganingizdan so'ng, "20 daqiqa" yadro konfiguratsiyasini bajarishingiz kerak. Uning maqsadi faqat kerakli drayverlar va funktsiyalarni qoldirishdir. Barcha buyruqlar allaqachon superuser nomidan bajarilishi kerak.

config - konfiguratorning konsol rejimini yarating.

menuconfig - konsol rejimini ro'yxat sifatida qiling.

xconfig - grafik rejimini yarating.

Kerakli o'zgarishlarni amalga oshirgandan so'ng, sozlamalarni saqlang va konfiguratordan chiqing.

Jamlama.
Yig'ilishning yakuniy bosqichi - kompilyatsiya vaqti keldi. Bu ikkita buyruq yordamida amalga oshiriladi:
qilish && o'rnatish
Birinchi buyruq barcha fayllarni mashina kodiga kompilyatsiya qiladi, ikkinchisi esa yangi yadroni tizimingizga o'rnatadi.
Biz 20 daqiqadan bir necha soatgacha kutamiz (kompyuterning kuchiga qarab). Yadro o'rnatilgan. Uni grub (2) ro'yxatida ko'rsatish uchun (superuserdan) yozing.
yangilash guruhi
Endi qayta ishga tushirgandan so'ng "Escape" tugmasini bosing va ro'yxatda yangi yadroni ko'rasiz. Agar yadro yoqilmasa, shunchaki eski yadro bilan yuklang va ehtiyotkorlik bilan sozlang.

KernelCheck - konsolga kirmasdan yadroni kompilyatsiya qilish.
yadroni to'liq grafik rejimda qurish imkonini beradi Debian va unga asoslangan tarqatishlar uchun... Ishga tushgandan so'ng, KernelCheck yadro va yamoqlarning so'nggi versiyalarini taklif qiladi va sizning roziligingizdan so'ng u manba kodini yuklab oladi, grafik konfiguratorni ishga tushiradi. Dastur yadroni .deb paketlariga kompilyatsiya qiladi va ularni o'rnatadi. Siz shunchaki qayta ishga tushirishingiz kerak.

Haqida: "Tarjima asosida" Linux Device Driver 2-nashr. Tarjimasi: Knyazev Aleksey [elektron pochta himoyalangan] Oxirgi o'zgartirish sanasi: 03.08.2004 Joylashtirish: http://lug.kmv.ru/index.php?page=knz_ldd2

Endi dasturlashni boshlaymiz! Ushbu bobda modullar va yadro dasturlash haqida umumiy ma'lumot berilgan.
Bu erda biz strukturasi har qanday haqiqiy modul drayveriga mos keladigan to'liq huquqli modulni quramiz va ishga tushiramiz.
Shu bilan birga, biz haqiqiy qurilmalarning o'ziga xos xususiyatlarini hisobga olmasdan, asosiy pozitsiyalarga e'tibor qaratamiz.

Bu erda eslatib o'tilgan funktsiyalar, o'zgaruvchilar, sarlavhalar va makrolar kabi yadroning barcha qismlari
bob oxirida batafsil bayon etilgan.

Salom Dunyo!

Alessndro Rubini va Jonatan Korbet tomonidan yozilgan asl materialni ko'rib chiqayotib, men "Salom dunyo" deb berilgan bir oz baxtsiz misol topdim! Shuning uchun men o'quvchiga, mening fikrimcha, birinchi modulning yaxshiroq versiyasini taqdim etmoqchiman. Umid qilamanki, uni 2.4.x yadrosi ostida kompilyatsiya qilish va o'rnatishda hech qanday muammo bo'lmaydi. Taklif etilayotgan modul va uni kompilyatsiya qilish usuli uni versiya boshqaruvini qo'llab-quvvatlaydigan va qo'llab-quvvatlamaydigan yadrolarda ishlatishga imkon beradi. Keyinchalik barcha tafsilotlar va terminologiya bilan tanishasiz, men endi vimni ochaman va ishlay boshlayman!

=================================================== // hello_knz.c fayl #include #o'z ichiga oladi <1>Salom, dunyo \ n "); qaytish 0;); void cleanup_module (void) (printk ("<1>Xayr zolim dunyo \ n ");) MODULE_LICENSE (“ GPL ”); =============================== == ===============

Bunday modulni kompilyatsiya qilish uchun quyidagi Makefile faylidan foydalanish mumkin. $ (CC)… bilan boshlanadigan qator oldiga yorliq belgisini qo'yishni unutmang.

=================================================== BAYROQLAR = -c -Wall -D__KERNEL__ -DMODULE PARAM = -I / lib / modullar / $ (qobiq unname -r) / qurish / o'z ichiga hello_knz.o: hello_knz.c $ (CC) $ (FLAGS) $ (PARAM) - o [elektron pochta himoyalangan] $^ =================================================

Bu yerda Rubini & Corbet tomonidan taklif qilingan asl Salom dunyo kodiga nisbatan ikkita xususiyatdan foydalaniladi. Birinchidan, modul yadro bilan bir xil versiyaga ega bo'ladi. Bunga kompilyatsiya skriptida PARAM o'zgaruvchisini o'rnatish orqali erishiladi. Ikkinchidan, endi modul GPL (MODULE_LICENSE () makrosidan foydalangan holda) litsenziyalanadi. Agar bu bajarilmasa, modulni yadroga o'rnatishda siz taxminan quyidagi ogohlantirishni ko'rishingiz mumkin:

# insmod hello_knz.o Ogohlantirish: hello_knz.o-ni yuklash yadroni buzadi: litsenziya yo'q Zararlangan modullar haqida ma'lumot olish uchun http://www.tux.org/lkml/#export-tainted sahifasiga qarang hello_knz moduli yuklangan, ogohlantirishlar bilan.

Keling, modulni kompilyatsiya qilish imkoniyatlarini tushuntiramiz (makroslar keyinroq tushuntiriladi):

-bilan- agar ushbu parametr mavjud bo'lsa, gcc kompilyatori bajariladigan binarni yaratishga urinmasdan, ob'ekt fayli yaratilgandan so'ng darhol faylni kompilyatsiya qilish jarayonini to'xtatadi.

- Devor- gcc ishlayotgan paytda ogohlantirish chiqishining maksimal darajasi.

-D- makro belgilarning ta'riflari. Kompilyatsiya qilingan fayldagi #define direktivasi bilan bir xil. Manba faylida #define yoki kompilyator uchun -D opsiyasi yordamida ushbu modulda ishlatiladigan makroslarni qanday aniqlashingizning farqi yo'q.

-I- fayllarni qo'shish uchun qo'shimcha qidiruv yo'llari. “Uname -r” almashtirishdan foydalanishga e’tibor bering, bu sizga hozirda foydalanilayotgan yadro versiyasining aniq nomini beradi.

Keyingi bo'limda modulning yana bir misoli keltirilgan. Shuningdek, u yadrodan qanday o'rnatish va tushirishni batafsil tushuntiradi.

Asl Salom dunyo!

Endi Rubini & Corbet tomonidan taklif qilingan oddiy "Salom, dunyo" modulining asl kodi. Ushbu kod 2.0 dan 2.4 gacha yadrolar ostida kompilyatsiya qilinishi mumkin. Ushbu misol, kitobdagi boshqalar kabi, O'Reilly FTP saytida mavjud (1-bobga qarang).

// hello.c fayl #define MODULE #include int init_module (void) (printk ("<1>Salom, dunyo \ n "); qaytish 0;) void cleanup_module (void) (printk ("<1>Xayr zolim dunyo \ n ");)

Funktsiya printk () Linux yadrosida aniqlangan va standart kutubxona funktsiyasi sifatida ishlaydi printf () C tilida. Yadro foydalanuvchi darajasidagi kutubxonalarda emas, balki to'g'ridan-to'g'ri yadroda joylashgan o'zining, afzalroq kichik, chiqish funktsiyasiga muhtoj. Modul funktsiyani chaqirishi mumkin printk () chunki modulni buyruq bilan yuklagandan so'ng insmod modul yadro bilan aloqa qiladi va nashr etilgan (eksport qilingan) yadro funktsiyalari va o'zgaruvchilariga kirish huquqiga ega.

String parametri "<1>”printk () funksiyasiga o‘tish xabarning ustuvorligi hisoblanadi. Ingliz tilining asl manbalarida loglevel atamasi ishlatiladi, ya'ni xabarlarni qayd qilish darajasini bildiradi. Bu erda biz asl "loglevel" o'rniga ustuvorlik atamasidan foydalanamiz. Ushbu misolda biz past raqamga mos keladigan xabar uchun yuqori ustuvorlikdan foydalanamiz. Xabarning yuqori ustuvorligi ataylab o'rnatiladi, chunki standart ustuvorlikdagi xabar modul o'rnatilgan konsolda ko'rsatilmasligi mumkin. Standart ustuvorlikka ega yadro xabarlarini chiqarish yo'nalishi ishlaydigan yadro versiyasiga, demon versiyasiga bog'liq. klogd, va sizning konfiguratsiyangiz. Batafsilroq, funktsiya bilan ishlash printk () biz 4-bob, "Nosozliklarni tuzatish usullari"da tushuntiramiz.

Buyruq yordamida modulni sinab ko'rishingiz mumkin insmod yadro va buyruqlarga modul o'rnatish uchun rmmod yadrodan modulni olib tashlash uchun. Quyida buni qanday qilish mumkinligini ko'rsatamiz. Bunday holda, modul yadroga o'rnatilganda init_module () kirish nuqtasi va yadrodan olib tashlanganda cleanup_module () bajariladi. Esda tutingki, faqat super foydalanuvchi modullarni yuklashi va tushirishi mumkin.

Yuqoridagi misol moduli faqat "modul versiyasini qo'llab-quvvatlash" bayrog'i o'chirilgan holda qurilgan yadro bilan ishlatilishi mumkin. Afsuski, ko'pchilik distributivlar versiyalangan yadrolardan foydalanadi (11-bobning "Modullarda versiyalarni boshqarish" bo'limida muhokama qilingan "kmod va kengaytirilgan modulizatsiya"). Paketning eski versiyalari bo'lsa-da modullar bunday modullarni versiya boshqaruvi bilan tuzilgan yadrolarga yuklashga ruxsat bering, endi bu mumkin emas. Eslatib o'tamiz, modulils to'plami insmod va rmmod dasturlarini o'z ichiga olgan dasturlar to'plamini o'z ichiga oladi.

Vazifa: Distribyutoringizdan modulils paketining versiya raqami va tarkibini aniqlang.

Bunday modulni versiya boshqaruvini qo'llab-quvvatlaydigan yadroga kiritishga harakat qilganingizda, quyidagiga o'xshash xato xabarini ko'rishingiz mumkin:

# insmod hello.o hello.o: yadro moduli versiyasi mos kelmasligi hello.o yadro versiyasi 2.4.20 uchun tuzilgan, bu yadro 2.4.20-9asp versiyasidir.

Katalogda turli modullar Ftp.oreilly.com dan misollar uchun siz hello.c asl misol dasturini topasiz, u bir oz ko'proq satrlardan iborat bo'lib, yadrolarga versiya boshqaruvi bo'lgan yoki bo'lmagan holda o'rnatilishi mumkin. Biroq, versiyani boshqarish yordamisiz o'z yadrongizni yaratishingizni qat'iy tavsiya qilamiz. Shu bilan birga, www.kernel.org saytida asl yadro manbalarini olish tavsiya etiladi

Agar siz yadro yaratishda yangi bo'lsangiz, Alessandro Rubini (asl kitob mualliflaridan biri) http://www.linux.it/kerneldocs/kconf saytida chop etgan maqolani o'qib ko'ring, bu jarayonni o'zlashtirishingizga yordam beradi.

Yuqoridagi asl misol modulini kompilyatsiya qilish va sinab ko'rish uchun matn konsolida quyidagi buyruqlarni bajaring.

Root # gcc -c hello.c root # insmod ./hello.o Salom, dunyo ildizi # rmmod salom Xayr zolim dunyo ildizi #

Tizimingiz xabarlar satrlarini yuborish uchun foydalanadigan mexanizmga qarab, funktsiya tomonidan yuborilgan xabarlarning chiqish yo'nalishi. printk () farq qilishi mumkin. Modulni kompilyatsiya qilish va sinab ko'rishning keltirilgan misolida printk () funksiyasidan uzatilgan xabarlar bir xil konsolda ko'rsatildi, u erdan modullarni o'rnatish va ishga tushirish buyruqlari berildi. Ushbu misol matn konsolidan olingan. Agar siz buyruqlarni bajarsangiz insmod va rmmod dastur doirasidan xterm keyin siz terminalda hech narsa ko'rmaysiz. Buning o'rniga, xabar tizim jurnallaridan birida tugashi mumkin, masalan / var / log / xabarlar. Faylning aniq nomi tarqatilishiga bog'liq. Jurnal fayllarini o'zgartirish vaqtiga qarang. Printk () funksiyasidan xabarlarni uzatish uchun foydalaniladigan mexanizm 4-bob, “Texnik” “Xabarlar qanday qayd qilinadi” bo‘limida tasvirlangan.
disk raskadrovka ".

Tizim jurnali fayli / val / log / xabarlaridagi modul xabarlarini ko'rish uchun tizimning dumli yordam dasturidan foydalanish qulay bo'lib, u sukut bo'yicha unga o'tkazilgan faylning oxirgi 10 qatorini ko'rsatadi. Ushbu yordamchi dasturning qiziqarli varianti -f opsiyasi bo'lib, u yordam dasturini faylning oxirgi satrlarini kuzatish rejimida ishga tushiradi, ya'ni. faylda yangi satrlar paydo bo'lganda, ular avtomatik ravishda ko'rsatiladi. Bu holda buyruq bajarilishini to'xtatish uchun Ctrl + C tugmalarini bosing. Shunday qilib, tizim jurnali faylining oxirgi o'n qatorini ko'rish uchun buyruq qatoriga quyidagilarni kiriting:

Ildiz # dum / var / log / xabarlar

Ko'rib turganingizdek, modul yozish ko'rinadigan darajada qiyin emas. Eng qiyin narsa bu sizning qurilmangiz qanday ishlashini va modulning ishlashini qanday oshirishni tushunishdir. Ushbu bob davomida biz oddiy modullarni yozish haqida ko'proq bilib olamiz, qurilmaning xususiyatlarini keyingi boblarga qoldiramiz.

Yadro modullari va ilovalar o'rtasidagi farqlar

Ilovada bitta kirish nuqtasi mavjud bo'lib, u ishga tushirilgan dastur kompyuterning operativ xotirasiga joylashtirilgandan so'ng darhol ishlay boshlaydi. Bu kirish nuqtasi C da asosiy () funksiya sifatida tasvirlangan. Asosiy () funksiyaning tugatilishi dasturning tugatilishini anglatadi. Modul yadrodan modulni o'rnatish va olib tashlashda, shuningdek foydalanuvchidan kiruvchi so'rovlarni qayta ishlashda bajariladigan bir nechta kirish nuqtalariga ega. Masalan, modul yadroga yuklanganda init_module () kirish nuqtasi bajariladi. Cleanup_module () funksiyasi modul tushirilganda bajariladi. Kelajakda modulga turli so'rovlar berilganda bajariladigan modulga kirishning boshqa nuqtalari bilan tanishamiz.

Modullarni yuklash va tushirish qobiliyati modulizatsiya mexanizmining ikkita ustunidir. Ular turli kalitlarda baholanishi mumkin. Ishlab chiquvchi uchun bu, birinchi navbatda, ishlab chiqish vaqtini qisqartirishni anglatadi, chunki uzoq qayta yuklash jarayonisiz drayverning funksiyalarini sinab ko'rishingiz mumkin.

Dasturchi sifatida siz bilasizki, dastur ilovada e'lon qilinmagan funksiyani chaqira oladi. Statik yoki dinamik bog'lanish bosqichlarida tegishli kutubxonalardan bunday funktsiyalarning manzillari aniqlanadi. Funktsiya printf () kutubxonada belgilangan ushbu chaqiriladigan funksiyalardan biri libc... Boshqa tomondan, modul faqat yadro bilan bog'langan va faqat yadro tomonidan eksport qilinadigan funktsiyalarni chaqirishi mumkin. Yadro bajariladigan kodi tashqi kutubxonalardan foydalana olmaydi. Masalan, funktsiya printk () bu misolda ishlatilgan salom.c, taniqli funktsiyaning analogidir printf () foydalanuvchi darajasidagi ilovalarda mavjud. Funktsiya printk () yadroda joylashgan va imkon qadar kichik bo'lishi kerak. Shuning uchun, printf () dan farqli o'laroq, u ma'lumotlar turlarini juda cheklangan darajada qo'llab-quvvatlaydi va, masalan, suzuvchi nuqta raqamlarini umuman qo'llab-quvvatlamaydi.

2.0 va 2.2 yadrolarini amalga oshirish tur spetsifikatorlarini qo'llab-quvvatlamadi L va Z... Ular faqat 2.4 yadrosida kiritilgan.

2-1-rasmda modulga kirish nuqtalari bo'lgan funksiyalarni chaqirish mexanizmining amalga oshirilishi ko'rsatilgan. Shuningdek, ushbu rasmda o'rnatilgan yoki o'rnatilayotgan modulning yadro bilan o'zaro ta'siri mexanizmi ko'rsatilgan.

Guruch. 2-1. Modulni yadroga ulash

Unix/Linux operatsion tizimlarining o'ziga xos xususiyatlaridan biri shundaki, yadro modullari bilan bog'lanishi mumkin bo'lgan kutubxonalar mavjud emas. Ma'lumki, modullar yuklanganda yadroga ulanadi, shuning uchun modulingizdan tashqaridagi barcha funktsiyalar yadro sarlavhasi fayllarida e'lon qilinishi va yadroda mavjud bo'lishi kerak. Modullar manbalari hech qachon foydalanuvchi fazosi kutubxonalaridagi oddiy sarlavhali fayllarni o'z ichiga olmaydi. Yadro modullarida siz faqat yadroning bir qismi bo'lgan funksiyalardan foydalanishingiz mumkin.

Butun yadro interfeysi kataloglarda joylashgan sarlavha fayllarida tasvirlangan o'z ichiga / Linux va o'z ichiga / asm yadro manbalari ichida (odatda /usr/src/linux-x.y.z(x.y.z sizning yadro versiyangiz)). Eski tarqatishlar (asoslangan libc 5 yoki undan kam versiyalar) ramziy havolalardan foydalanilgan / usr / o'z ichiga / linux va / usr / o'z ichiga / asm yadro manbalaridagi tegishli kataloglarga. Ushbu ramziy havolalar kerak bo'lganda maxsus ilovalarda yadro interfeyslaridan foydalanish imkoniyatini beradi.

Garchi foydalanuvchi-makon kutubxonasi interfeysi endi yadro interfeysidan alohida bo'lsa ham, ba'zida foydalanuvchi jarayonlari yadro interfeyslaridan foydalanishi kerak bo'ladi. Biroq, yadro sarlavhalaridagi ko'pgina havolalar yadroning o'ziga xosdir va foydalanuvchi ilovalari uchun mavjud bo'lmasligi kerak. Shuning uchun bu reklamalar himoyalangan. #ifdef __KERNEL__ bloklar. Shuning uchun drayveringiz, boshqa yadro kodlari kabi, e'lon qilingan makro belgisi bilan kompilyatsiya qilinishi kerak __KERNEL__.

Alohida yadro sarlavhalarining roli kerak bo'lganda kitob davomida muhokama qilinadi.

Har qanday yirik dasturiy ta'minot loyihasida (masalan, yadro) ishlaydigan ishlab chiquvchilar ko'rib chiqishlari va undan qochishlari kerak "nom maydonining ifloslanishi"... Bu muammo nomlari yetarlicha ifodali bo‘lmagan (ajraladigan) funksiyalar va global o‘zgaruvchilar soni ko‘p bo‘lganda yuzaga keladi. Keyinchalik bunday ilovalar bilan shug'ullanishi kerak bo'lgan dasturchi "zahiralangan" nomlarni eslab qolish va yangi elementlar uchun noyob nomlarni topish uchun ko'proq vaqt sarflashga majbur bo'ladi. Nomlar to'qnashuvi (noaniqliklar) modulni yuklashdagi xatolardan tortib, boshqa konfiguratsiyada o'rnatilgan yadrodan foydalanuvchi foydalanuvchilarda yuzaga kelishi mumkin bo'lgan beqaror yoki tushunarsiz dastur xatti-harakatlarigacha bo'lgan keng ko'lamli muammolarni keltirib chiqarishi mumkin.

Ishlab chiquvchilar yadro kodini yozishda bunday xatolarga yo'l qo'yishlari mumkin emas, chunki hatto eng kichik modul ham butun yadro bilan bog'lanadi. Nomlar to'qnashuvining oldini olishning eng yaxshi yechimi, birinchi navbatda, dastur ob'ektlarini shunday deb e'lon qilishdir statik va ikkinchidan, global ob'ektlarni nomlash uchun yagona tizimli prefiksdan foydalanish. Bundan tashqari, modul ishlab chiqaruvchisi sifatida siz kodingizdagi ob'ektlar doirasini, keyinchalik "Yadro ulash jadvali" bo'limida tasvirlanganidek boshqarishingiz mumkin.

Buyruqning ko'p (lekin hammasi emas) versiyalari insmod deb e'lon qilinmagan barcha modul ob'ektlarini eksport qilish statik, sukut bo'yicha, ya'ni. modulda aniq ko'rsatmalar belgilanmagan bo'lsa. Shuning uchun, siz eksport qilmoqchi bo'lmagan modul ob'ektlarini e'lon qilish juda mantiqiy statik.

Modul ichidagi mahalliy ob'ektlar uchun noyob prefiksdan foydalanish yaxshi amaliyot bo'lishi mumkin, chunki bu nosozliklarni tuzatishni osonlashtiradi. Drayvingizni sinab ko'rayotganda, yadroga qo'shimcha ob'ektlarni eksport qilishingiz kerak bo'lishi mumkin. Nomlarni belgilash uchun noyob prefiksdan foydalanish orqali siz yadro nomlar maydoniga to'qnashuvlar kiritish xavfiga ega bo'lmaysiz. Yadro prefikslari an'anaviy ravishda kichik harflardan foydalanadi va biz bu konventsiyaga amal qilamiz.

Yadro va foydalanuvchi jarayonlari o'rtasidagi yana bir muhim farq bu xatolarni qayta ishlash mexanizmi. Yadro foydalanuvchi jarayonining bajarilishini nazorat qiladi, shuning uchun foydalanuvchi jarayonidagi xato tizim uchun zararsiz xabarni keltirib chiqaradi: segmentatsiya xatosi. Bunday holda, nosozliklarni tuzatuvchi har doim foydalanuvchi ilovasining manba kodidagi xatoni kuzatish uchun ishlatilishi mumkin. Yadroda yuzaga keladigan xatolar halokatli - agar butun tizim uchun bo'lmasa, hech bo'lmaganda joriy jarayon uchun. 4-bobning “Tizim xatolarini tuzatish” bo‘limida “Nosozliklarni tuzatish usullari” bo‘limida yadro xatolarini kuzatish yo‘llarini ko‘rib chiqamiz.

Foydalanuvchi maydoni va yadro maydoni

Modul deb atalmishda bajariladi yadro maydoni ilovalar ishga tushganda. Ushbu kontseptsiya operatsion tizimlar nazariyasining asosidir.

Operatsion tizimning asosiy maqsadlaridan biri foydalanuvchi va foydalanuvchi dasturlarini kompyuter resurslari bilan ta'minlashdan iborat bo'lib, ularning aksariyati tashqi qurilmalar bilan ifodalanadi. Operatsion tizim nafaqat resurslarga kirishni ta'minlashi, balki ularning taqsimlanishi va ishlatilishini nazorat qilishi, to'qnashuvlar va ruxsatsiz kirishning oldini olishi kerak. Bunga qo'shimcha ravishda, operatsion tizim dasturlar uchun mustaqil operatsiyalarni yaratishi va resurslarga ruxsatsiz kirishdan himoya qilishi mumkin. Ushbu ahamiyatsiz vazifani hal qilish faqat protsessor tizim dasturlarini foydalanuvchi ilovalaridan himoya qilgan taqdirdagina mumkin.

Deyarli har bir zamonaviy protsessor bajariladigan kod uchun turli darajadagi imtiyozlarni amalga oshirish orqali bu ajratishni ta'minlay oladi (kamida ikkita daraja talab qilinadi). Misol uchun, I32 protsessorlari 0 dan 3 gacha bo'lgan to'rtta imtiyoz darajasiga ega. Bundan tashqari, 0 darajasi eng yuqori imtiyozlarga ega. Bunday protsessorlar uchun faqat imtiyozli darajalarda bajarilishi mumkin bo'lgan imtiyozli ko'rsatmalar sinfi mavjud. Unix tizimlari protsessor imtiyozlarining ikki darajasidan foydalanadi. Agar protsessor ikkitadan ortiq imtiyoz darajasiga ega bo'lsa, eng past va eng yuqori daraja ishlatiladi. Unix yadrosi foydalanuvchining apparat va jarayonlari ustidan nazoratni ta'minlab, eng yuqori imtiyozlar darajasida ishlaydi.

Biz gaplashganda yadro maydoni va foydalanuvchi jarayoni maydoni Men nafaqat bajariladigan kodning turli darajadagi imtiyozlarini, balki turli xil manzil maydonlarini ham nazarda tutyapman.

Unix ikki marta bajarilishni foydalanuvchi jarayonlar maydonidan yadro maydoniga o'tkazadi. Birinchidan, foydalanuvchi ilovasi yadroga qo'ng'iroq qilganda (tizim qo'ng'irog'i), ikkinchidan, texnik xizmat ko'rsatishda uzilishlar. Tizim chaqiruvida bajarilgan yadro kodi jarayon kontekstida ishlaydi, ya'ni. dan qo'ng'iroq qilish jarayoni manfaatlarida ishlaydigan jarayonning manzil maydoni ma'lumotlariga kirish huquqiga ega. Boshqa tomondan, apparat uzilishiga xizmat ko'rsatishda bajariladigan kod jarayonga nisbatan asinxrondir va hech qanday maxsus jarayonga tegishli emas.

Modullarning maqsadi yadro funksionalligini kengaytirishdir. Modul kodi yadro maydonida bajariladi. Odatda, modul avval qayd etilgan ikkala vazifani ham bajaradi: modulning baʼzi funksiyalari tizim chaqiruvlarining bir qismi sifatida bajariladi, baʼzilari esa uzilishlarni boshqarish uchun javobgardir.

Yadroda parallellashtirish

Qurilma drayverlarini dasturlashda, amaliy dasturlashdan farqli o'laroq, bajariladigan kodni parallellashtirish masalasi ayniqsa keskin. Odatda, dastur boshidan oxirigacha o'z muhitini o'zgartirish haqida tashvishlanmasdan ketma-ket ishlaydi. Yadro kodi bir vaqtning o'zida bir necha marta kirish mumkin degan taxmin bilan ishlashi kerak.

Yadro kodini parallellashtirish uchun ko'p sabablar mavjud. Odatda Linuxda ishlaydigan ko'plab jarayonlar mavjud va ularning ba'zilari bir vaqtning o'zida modul kodingizga kirishga harakat qilishi mumkin. Ko'pgina qurilmalar protsessorda apparat uzilishlarini keltirib chiqarishi mumkin. Interrupt ishlov beruvchilari asinxron chaqiriladi va haydovchi boshqa so'rovni bajarish bilan band bo'lganda chaqirilishi mumkin. Ba'zi dasturiy ta'minot abstraktsiyalari (masalan, "Vaqt oqimi" 6-bobida tushuntirilgan yadro taymerlari) ham asinxron ishlaydi. Bundan tashqari, Linux simmetrik ko'p protsessorli (SMP) tizimda ishlashi mumkin, bunda sizning drayver kodingiz bir vaqtning o'zida bir nechta protsessorlarda parallel ravishda ishlashi mumkin.

Shu sabablarga ko'ra, Linux yadrosi kodi, shu jumladan drayver kodlari qayta kirishi kerak, ya'ni. bir vaqtning o'zida bir nechta ma'lumotlar konteksti bilan ishlay olishi kerak. Ma'lumotlar tuzilmalari parallel ravishda ishlaydigan bir nechta iplar bilan ishlab chiqilishi kerak. O'z navbatida, yadro kodi bir nechta parallel ma'lumotlar oqimini ularga zarar bermasdan boshqarishi kerak. Parallel ravishda bajarilishi mumkin bo'lgan va boshqa ketma-ket bajarilish tizimning istalmagan xatti-harakatlariga olib kelishi mumkin bo'lgan vaziyatlardan qochadigan kod yozish ko'p vaqt talab qiladi va ehtimol qiyin. Ushbu kitobdagi har bir haydovchi misoli bir vaqtda hisobga olingan holda yozilgan. Agar kerak bo'lsa, biz bunday kodni yozish texnikasining xususiyatlarini tushuntiramiz.

Dasturchilarning eng keng tarqalgan xatosi shundaki, ular parallellik muammo emas deb o'ylashadi, chunki ba'zi kod segmentlari uxlay olmaydi. Haqiqatan ham, Linux yadrosi sahifali emas, muhim yadro kodi bajarilayotganda protsessor tomonidan qabul qilina olmaydigan uzilish ishlovchilariga nisbatan muhim istisno. Yaqinda yuklanmaslik ko'p hollarda kiruvchi parallelizmning oldini olish uchun etarli bo'ldi. SMP tizimlarida esa parallel hisoblash tufayli kodni tushirish talab qilinmaydi.

Agar sizning kodingiz uni tashlab ketmaydi deb hisoblasa, u SMP tizimlarida to'g'ri ishlamaydi. Agar sizda bunday tizim bo'lmasa ham, kimdir sizning kodingizdan foydalanishi mumkin. Bundan tashqari, yadro kelajakda peyjingdan foydalanishi ham mumkin, shuning uchun hatto bir protsessorli tizimlar ham hamma joyda parallelizm bilan shug'ullanishi kerak. Bunday yadrolarni amalga oshirish uchun allaqachon variantlar mavjud. Shunday qilib, ehtiyotkor dasturchi yadro kodini SMP tizimida ishlaydi degan taxmin bilan yozadi.

Taxminan tarjimon: Kechirasiz, lekin oxirgi ikki paragraf menga tushunarli emas. Ehtimol, bu noto'g'ri tarjimaning natijasidir. Shuning uchun men asl matnni beraman.

Haydovchi dasturchilar tomonidan yo'l qo'yilgan keng tarqalgan xato - bu kodning ma'lum bir segmenti mavjud bo'lganda, parallellik muammo emas deb taxmin qilishdir.
uyquga ketmaydi (yoki "blok"). To'g'ri, Linux yadrosi preemptiv emas; muhim istisno bilan
xizmat ko'rsatishda uzilishlar bo'lsa, u protsessorni o'z xohishi bilan bermaydigan yadro kodidan uzoqlashtirmaydi. O'tgan vaqtlarda bu nopreemptive
xatti-harakatlari ko'pincha istalmagan parallellikni oldini olish uchun etarli edi. Biroq, SMP tizimlarida, sabab bo'lishi uchun oldindan imtiyoz talab qilinmaydi
bir vaqtda amalga oshirish.

Agar sizning kodingiz oldindan belgilanmaydi deb hisoblasa, u SMP tizimlarida to'g'ri ishlamaydi. Agar sizda bunday tizim bo'lmasa ham,
Sizning kodingizni ishlatadigan boshqalar ham bo'lishi mumkin. Kelajakda yadro preemptiv ish rejimiga o'tishi ham mumkin,
bu vaqtda hatto bir protsessorli tizimlar ham hamma joyda parallellik bilan shug'ullanishi kerak bo'ladi (yadroning ba'zi variantlari allaqachon amalga oshirilgan.
u).

Joriy jarayon haqida ma'lumot

Yadro moduli kodi ilovalar kabi ketma-ket bajarilmasa ham, yadroga qo'ng'iroqlarning aksariyati qo'ng'iroq qilish jarayoniga nisbatan amalga oshiriladi. Yadro kodi strukturaga ishora qiluvchi global ko'rsatkichga murojaat qilib, uni chaqirgan jarayonni aniqlay oladi struct task_struct fayldagi 2.4 yadro uchun belgilangan kiritilgan ... Pointer joriy hozirda ishlayotgan foydalanuvchi jarayonini bildiradi. Kabi tizim chaqiruvlarini bajarishda ochiq () yoki yopish (), ularga sabab bo'lgan jarayon bo'lishi kerak. Yadro kodi, agar kerak bo'lsa, ko'rsatgich orqali qo'ng'iroq qilish jarayoni bo'yicha aniq ma'lumotlarni chaqirishi mumkin joriy... Ushbu ko'rsatgichdan foydalanish misollari uchun 5-bobdagi "Qurilma fayliga kirishni boshqarish" ga qarang, "Kengaytirilgan Chard drayveri operatsiyalari".

Bugungi kunga kelib, ko'rsatgich joriy yadroning oldingi versiyalarida bo'lgani kabi global o'zgaruvchi emas. Ishlab chiquvchilar joriy jarayonni tavsiflovchi tuzilmaga kirishni stek sahifasiga o'tkazish orqali optimallashtirishdi. Siz faylda joriyning amalga oshirish tafsilotlarini ko'rishingiz mumkin ... U erda ko'radigan kod sizga oddiy ko'rinmasligi mumkin. Shuni yodda tutingki, Linux SMP-ga yo'naltirilgan tizimdir va global o'zgaruvchi bir nechta protsessorlar bilan ishlaganingizda ishlamaydi. Amalga oshirish tafsilotlari boshqa yadro quyi tizimlari uchun yashirin bo'lib qoladi va qurilma drayveri ko'rsatgichga kirishi mumkin joriy faqat interfeys orqali .

Modul nuqtai nazaridan, joriy tashqi havolaga o'xshaydi printk ()... Modul foydalanishi mumkin joriy qayerda kerak bo'lsa. Masalan, quyidagi kod bo'lagi identifikatorni (jarayon identifikatori - PID) va modulni chaqirgan jarayonning buyruq nomini bosib chiqaradi va ularni strukturaning tegishli maydonlari orqali oladi. struct task_struct:

Printk ("Jarayon \"% s \ "(pid% i) \ n", joriy-> comm, joriy-> pid);

Joriy-> comm maydoni joriy jarayonni yaratgan buyruq fayl nomidir.

Modullarni kompilyatsiya qilish va yuklash

Ushbu bobning qolgan qismi atipik bo'lsa-da, to'liq modul yozishga bag'ishlangan. Bular. modul “Qurilma drayverlariga kirish” 1-bobidagi “Qurilma va modul sinflari” bo‘limida tavsiflangan sinflarning birortasiga tegishli emas. Ushbu bobda ko'rsatilgan misol drayveri bosh suyagi deb nomlanadi (Lokallarni yuklash uchun oddiy yadro yordam dasturi). O'zingizning mahalliy kodingizni yozish uchun shablon sifatida qayiq modulidan foydalanishingiz mumkin.

Biz "mahalliy kod" atamasidan eski Unix an'anasida (/ usr / local) shaxsiy kodingiz o'zgarishlarini ta'kidlash uchun foydalanamiz.

Biroq, biz init_module () va cleanup_module () funksiyalarini kontent bilan to'ldirishdan oldin, biz modul ob'ekt kodini yaratish uchun foydalanadigan Makefile skriptini yozamiz.

Preprotsessor har qanday sarlavha faylini qo'shishni qayta ishlashdan oldin __KERNEL__ so'l belgisi #define direktivasi bilan aniqlanishi kerak. Yuqorida aytib o'tilganidek, yadro interfeysi fayllarida yadroga xos kontekstni aniqlash mumkin, faqat __KERNEL__ belgisi oldindan ishlov berishda oldindan belgilangan bo'lsa ko'rinadi.

#define direktivasi bilan belgilangan yana bir muhim belgi MODUL belgisidir. Interfeysni yoqish uchun From aniqlanishi kerak (yadro bilan kompilyatsiya qilinadigan drayverlar bundan mustasno). Yadroga kiritilgan drayverlar ushbu kitobda tasvirlanmaydi, shuning uchun MODUL belgisi barcha misollarimizda mavjud bo'ladi.

Agar siz SMP tizimi uchun modul qurayotgan bo'lsangiz, yadro interfeyslarini yoqishdan oldin __SMP__ makrosini ham belgilashingiz kerak. 2.2 yadrosida bir protsessor va ko'p protsessorli tizim o'rtasidagi tanlov yadro konfiguratsiyasida alohida element sifatida kiritilgan. Shuning uchun, modulingizning birinchi qatorlari sifatida quyidagi qatorlarni qo'shish ko'p protsessorni qo'llab-quvvatlashga olib keladi.

#o'z ichiga oladi #ifdef CONFIG_SMP # __SMP__ #endifni aniqlang

Modul ishlab chiquvchilari kompilyator uchun -O optimallashtirish bayrog'ini ham belgilashlari kerak, chunki ko'p funktsiyalar yadro sarlavhalarida inline deb e'lon qilingan. Optimallashtirish yoqilmaguncha gcc kompilyatori funktsiyalarda qatorni kengaytirishni amalga oshirmaydi. -g va -O opsiyalari bilan ichki o'zgartirishlarni kengaytirishni yoqish sizga tuzatuvchidagi ichki funksiyalar yordamida keyinchalik kodni disk raskadrovka qilish imkonini beradi. Yadro inline funktsiyalaridan keng foydalanganligi sababli, ularning to'g'ri kengaytirilganligi juda muhimdir.

Shunga qaramay, -O2 darajasidan yuqori bo'lgan har qanday optimallashtirish xavfli ekanligini unutmang, chunki kompilyator inline sifatida tavsiflanmagan funktsiyalarni kengaytirishi mumkin. Bu muammolarga olib kelishi mumkin. ba'zi funktsiya kodi standart qo'ng'iroqlar to'plamini topishni kutadi. Inline kengayish deganda funktsiya kodini uni chaqirish nuqtasiga mos keladigan funktsiyani chaqirish buyrug'i o'rniga kiritish tushuniladi. Shunga ko'ra, bu holda, funktsiya chaqiruvi mavjud emasligi sababli, qo'ng'iroqlar to'plami ham mavjud emas.

Modul o'rnatilishi kerak bo'lgan yadroni yaratishda foydalanilgan modullarni kompilyatsiya qilish uchun bir xil kompilyatordan foydalanayotganingizni tekshirishingiz kerak bo'lishi mumkin. Tafsilotlar uchun fayldagi asl hujjatga qarang Hujjatlar / o'zgarishlar yadro manbalari katalogida joylashgan. Yadro va kompilyator ishlanmalari odatda ishlab chiqish guruhlari o'rtasida sinxronlashtiriladi. Ushbu elementlardan birini yangilash boshqasida xatoliklarni yuzaga keltiradigan holatlar bo'lishi mumkin. Ba'zi tarqatuvchi sotuvchilar kompilyatorning ular ishlatayotgan yadroga mos kelmaydigan ultra-yangi versiyalarini jo'natadi. Bunday holda, ular odatda alohida paketni taqdim etadilar (ko'pincha deyiladi kgcc) uchun maxsus ishlab chiqilgan kompilyator bilan
yadroni kompilyatsiya qilish.

Va nihoyat, zerikarli xatolarning oldini olish uchun kompilyatsiya opsiyasidan foydalanishni tavsiya qilamiz - Devor(barcha ogohlantirishlar - barcha ogohlantirishlar). Ushbu ogohlantirishlarning barchasini qondirish uchun odatiy dasturlash uslubingizni o'zgartirishingiz kerak bo'lishi mumkin. Yadro kodini yozishda Linus Torvalds tomonidan tavsiya etilgan kodlash uslubidan foydalanish afzalroqdir. Shunday qilib, hujjat Hujjatlar / kodlash uslubi, yadro manba katalogidan, yetarlicha qiziqarli va yadro darajasidagi dasturlash bilan qiziquvchilarga tavsiya etiladi.

Biz yaqinda ko'rgan modulning kompilyatsiya bayroqlari to'plamini o'zgaruvchiga joylashtirish tavsiya etiladi. CFLAGS sizning Makefile. Make yordam dasturi uchun bu maxsus o'zgaruvchi bo'lib, undan foydalanish quyidagi tavsifdan aniq bo'ladi.

O'zgaruvchidagi bayroqlardan tashqari CFLAGS, turli obyekt fayllarini birlashtirish uchun Makefile-ga maqsad kerak bo'lishi mumkin. Ushbu maqsad faqat modul kodi bir nechta manba fayllariga bo'linganda kerak bo'ladi, bu umuman olganda kam uchraydi. Obyekt fayllari buyruq bilan birlashtiriladi ld -r, bu bog'lovchidan foydalanishga qaramay, an'anaviy ma'noda bog'lovchi operatsiya emas ( ld). Buyruqning bajarilishi natijasi ld -r bog'lovchi kirish fayllari ob'ekt kodlarini birlashtirgan boshqa ob'ekt faylidir. Variant -r degan ma'noni anglatadi ko'chirish mumkin - ko'chirish", ya'ni. biz buyruqning chiqish faylini manzil maydoniga o'tkazamiz, chunki u hali mutlaq funksiya chaqiruv manzillariga ega emas.

Quyidagi misolda ikkita manba fayli bo'lgan modulni kompilyatsiya qilish uchun zarur bo'lgan minimal Makefile ko'rsatilgan. Agar sizning modulingiz bitta manba fayldan iborat bo'lsa, berilgan misoldan buyruqni o'z ichiga olgan maqsadni olib tashlashingiz kerak ld -r.

# Yadro manbalari katalogiga yoʻlni shu yerda oʻzgartirish mumkin, # yoki “make” ga qoʻngʻiroq qilganingizda uni parametr sifatida oʻtkazishingiz mumkin KERNELDIR = / usr / src / linux include $ (KERNELDIR) /. Config CFLAGS = -D__KERNEL__ -DMODULE - I $ (KERNELDIR) / o'z ichiga \ -O -Wall ifdef CONFIG_SMP CFLAGS + = -D__SMP__ -DSMP endif hammasi: skull.o skull.o: skull_init.o skull_clean.o $ (LD) -r $ ^ -o [elektron pochta himoyalangan] toza: rm -f * .o * ~ yadro

Agar make utilitasida yangi bo'lsangiz, * .c fayllarini * .o fayllariga kompilyatsiya qilish qoidalari yo'qligiga hayron bo'lishingiz mumkin. Bunday qoidalarning ta'rifi kerak emas, chunki make yordam dasturi, agar kerak bo'lsa, standart kompilyator yoki o'zgaruvchi tomonidan belgilangan kompilyator yordamida * .c fayllarini * .o fayllariga o'zgartiradi. $ (CC)... Bunday holda, o'zgaruvchining mazmuni $ (CFLAGS) kompilyatsiya bayroqlarini belgilash uchun ishlatiladi.

Modulni qurishdan keyingi qadam uni yadroga yuklashdir. Biz buning uchun modulning barcha noaniq belgilarini (funksiya chaqiruvi va h.k.) ishlaydigan yadroning belgilar jadvali bilan bog‘laydigan insmod yordam dasturidan foydalanamiz, deb aytgan edik. Biroq, bog'lovchidan (masalan, ld) farqli o'laroq, u modulning disk faylini o'zgartirmaydi, balki yadro bilan bog'langan modul ob'ektini RAMga yuklaydi. Insmod yordam dasturi bir nechta buyruq qatori opsiyalarini qabul qiladi. Tafsilotlarni orqali ko'rish mumkin odam insmod... Ushbu parametrlardan foydalanib, siz, masalan, modulni yadroga ulashdan oldin, modulingizdagi ma'lum bir butun son va qator o'zgaruvchilarni ma'lum qiymatlarga belgilashingiz mumkin. Shunday qilib, agar modul to'g'ri ishlab chiqilgan bo'lsa, uni yuklash vaqtida sozlash mumkin. Modulni sozlashning bunday usuli foydalanuvchiga kompilyatsiya vaqtida sozlashdan ko'ra ko'proq moslashuvchanlikni beradi. Yuklab olish bosqichi konfiguratsiyasi ushbu bobning keyingi qismidagi "Qo'lda va avtomatik sozlash" bo'limida tushuntiriladi.

Ba'zi o'quvchilarni insmod yordam dasturi qanday ishlashi haqida ma'lumot qiziqtiradi. Insmodni amalga oshirish kernel / module.c da belgilangan bir nechta tizim chaqiruvlariga asoslangan. sys_create_module () funksiyasi modulni yuklash uchun yadro manzil maydoniga kerakli hajmdagi xotirani ajratadi. Ushbu xotira vmalloc () funksiyasi yordamida ajratiladi ("Xotirani egallash" 7-bobidagi "vmalloc va do'stlar" bo'limiga qarang). get_kernel_sysms () tizimi chaqiruvi ulanish paytida ob'ektlarning haqiqiy manzillarini aniqlash uchun foydalaniladigan yadro belgilari jadvalini qaytaradi. sys_init_module () funktsiyasi modul ob'ekt kodini yadro manzil maydoniga ko'chiradi va modulni ishga tushirish funktsiyasini chaqiradi.

Agar siz yadro kodining manbalariga qarasangiz, u erda sys_ prefiksi bilan boshlanadigan tizim chaqiruv nomlarini topasiz. Ushbu prefiks faqat tizim qo'ng'iroqlari uchun ishlatiladi. Boshqa hech qanday funktsiyalar uni ishlatmasligi kerak. Yadro manbalarini grep bilan qayta ishlashda buni yodda tuting.

Versiyaga bog'liqliklar

Agar siz bu erda aytilganlardan boshqa hech narsani bilmasangiz, unda siz yaratgan modullar yadroning ular bog'langan har bir versiyasi uchun qayta kompilyatsiya qilinishi kerak bo'ladi. Har bir modul chaqirilgan belgini belgilashi kerak __modul_yadro_versiyasi kimning qiymati
insmod yordam dasturi bilan joriy yadro versiyasi bilan solishtirganda. Ushbu belgi bo'limda joylashgan .modinfo ELF (bajariladigan va ulanish formati) fayllari. Bu 11-bobda "kmod va ilg'or modulizatsiya" da batafsilroq tushuntirilgan. Iltimos, ushbu versiyani boshqarish usuli faqat 2.2 va 2.4 yadrolari uchun amal qilishini unutmang. 2.0 yadrosida bu biroz boshqacha tarzda amalga oshiriladi.

Sarlavha fayli kiritilgan joyda kompilyator ushbu belgini belgilaydi ... Shuning uchun, yuqoridagi hello.c misolida biz bu belgini tasvirlamadik. Bu shuningdek, agar sizning modulingiz ko'p manba fayllardan iborat bo'lsa, siz faylni o'z ichiga olishingiz kerakligini anglatadi kodingizga faqat bir marta kiring. Istisno - bu ta'rifdan foydalanish holati __NO_VERSION__, biz keyinroq uchrashamiz.

Quyida 2.4.25 yadro kodidan olingan module.h faylidan tasvirlangan belgining ta'rifi keltirilgan.

Static const char __module_kernel_versio / PRE__attribute __ ((bo'lim (". Modinfo"))) = "kernel_version =" UTS_RELEASE;

Agar versiya mos kelmasligi sababli modul yuklanmasa, siz kalitni insmod yordam dasturining parametrlar qatoriga o'tkazib, ushbu modulni yuklashga urinib ko'rishingiz mumkin. -f(kuch). Modulni yuklashning bu usuli xavfsiz emas va har doim ham muvaffaqiyatli emas. Mumkin bo'lgan muvaffaqiyatsizliklar sabablarini tushuntirish qiyin. Modul yuklanmasligi mumkin, chunki ulanish paytida belgilar echilishi mumkin emas. Bunday holda, siz tegishli xato xabarini olasiz. Muvaffaqiyatsizlik sabablari yadro ishidagi yoki tuzilishidagi o'zgarishlarda ham bo'lishi mumkin. Bunday holda, modulni yuklash jiddiy ish vaqti xatolariga, shuningdek, tizim vahimasiga olib kelishi mumkin. Ikkinchisi versiyani boshqarish tizimidan foydalanish uchun yaxshi rag'bat bo'lishi kerak. Versiyaning mos kelmasligini yadrodagi versiya boshqaruvi yordamida yanada oqilona boshqarish mumkin. Bu haqda 11-bobda "kmod va ilg'or modulizatsiya" ning "Modullardagi versiyalarni boshqarish" bo'limida batafsil gaplashamiz.

Agar siz modulni ma'lum bir yadro versiyasi uchun kompilyatsiya qilmoqchi bo'lsangiz, ushbu yadro versiyasidan sarlavha fayllarini kiritishingiz kerak. Yuqoridagi Makefile misolida o'zgaruvchi ushbu fayllar joylashgan katalogni aniqlash uchun ishlatilgan KERNELDIR... Ushbu maxsus kompilyatsiya yadro manbalari mavjud bo'lganda kam uchraydi. Bundan tashqari, katalog daraxtida yadroning turli versiyalari bo'lishi odatiy hol emas. Ushbu kitobdagi barcha modul misollari o'zgaruvchidan foydalanadi KERNELDIR yig'ilgan modulni bog'lashi kerak bo'lgan yadro versiyasining manba katalogining joylashishini ko'rsatish uchun. Siz ushbu katalogni belgilash uchun tizim o'zgaruvchisidan foydalanishingiz yoki uning joylashuvini buyruq qatori parametrlari orqali o'tkazishingiz mumkin.

Modul yuklanganda, insmod yordam dasturi modulning ob'ekt fayllari uchun o'z qidiruv yo'llaridan foydalanadi va versiyaga bog'liq kataloglarni ko'rib chiqadi: / lib / modullar... Yordamchi dasturning eski versiyalari joriy katalogni qidirish yo'llariga qo'shgan bo'lsa-da, endi bu xatti-harakatlar xavfsizlik nuqtai nazaridan qabul qilinishi mumkin emas (tizim o'zgaruvchisidan foydalanish bilan bir xil muammolar) YO'L). Shunday qilib, agar siz joriy katalogdan modulni yuklamoqchi bo'lsangiz, uni uslubda belgilashingiz mumkin ./module.o... Modul pozitsiyasining ushbu ko'rsatkichi insmod yordam dasturining har qanday versiyasi uchun ishlaydi.

Ba'zan siz 2.0.x va 2.4.x versiyalari orasida farq qiluvchi yadro interfeyslariga duch kelishingiz mumkin. Bunday holda, siz yadroning joriy versiyasini aniqlaydigan so'ldan foydalanishga murojaat qilishingiz kerak bo'ladi. Ushbu makros sarlavha faylida joylashgan ... Biz ulardan foydalanishda interfeyslardagi farqlar holatlarini ko'rsatamiz. Buni to'g'ridan-to'g'ri yo'lda yoki bo'lim oxirida, versiyaga bog'liqlik bo'yicha maxsus bo'limda qilish mumkin. Tafsilotlarni alohida bo'limga ko'chirish, ba'zi hollarda, ushbu kitob uchun profil yaratadigan 2.4.x yadro versiyasiga muvofiq tavsifni murakkablashtirmaslik imkonini beradi.

Sarlavha faylida linux / version.h yadro versiyasining ta'rifi bilan bog'liq quyidagi makroslar aniqlanadi.

UTS_RELEASE Joriy yadro versiyasini tavsiflovchi qatorga kengaytiriladigan makros
manba daraxti. Misol uchun, makro buni kengaytirishi mumkin
qator: "2.3.48" . LINUX_VERSION_CODE Ushbu so'l yadro versiyasining ikkilik ko'rinishiga kengaytiriladi, tomonidan
raqamning har bir qismi uchun bir bayt. Masalan, ikkilik
2.3.48 versiyasi uchun taqdimot 131888 (o'nlik
hex 0x020330 uchun tasvir). Ehtimol, ikkilik
ko'rinish sizga satrdan ko'ra qulayroq ko'rinadi. Nima ekanligiga e'tibor bering
ko'rinish har birida 256 dan ortiq bo'lmagan variantni tavsiflash imkonini beradi
xonaning qismlari. KERNEL_VERSION (asosiy, kichik, nashr) Ushbu makros kernel_version_code yaratish imkonini beradi
yadro versiyasini tashkil etuvchi alohida elementlardan. Masalan,
keyingi makro KERNEL_VERSION (2, 3, 48)
131888 gacha kengaytiradi. Bu so'l qachon juda foydali
yadroning joriy versiyasini talab qilingani bilan solishtirish. Biz qayta-qayta bo'lamiz
kitob davomida ushbu makrosdan foydalaning.

Keling, faylning mazmunini beraylik linux / version.h yadro 2.4.25 uchun (sarlavha faylining matni to'liq berilgan).

#UTS_RELEASE "2.4.25" ni aniqlang #LINUX_VERSION_KODini aniqlang 132121 #yadro_VERSIONini aniqlang (a, b, c) (((a))<< 16) + ((b) << 8) + (c))

version.h sarlavha fayli module.h fayliga kiritilgan, shuning uchun odatda modul kodingizga version.h ni kiritish shart emas. Shu bilan bir qatorda, makrosni e'lon qilish orqali version.h sarlavha faylining module.h tarkibiga kiritilishini oldini olishingiz mumkin. __NO_VERSION__... foydalanasiz __NO_VERSION__, masalan, yoqishingiz kerak bo'lgan holatda bir nechta manba fayllarga, keyinchalik ular bitta modulga bog'lanadi. E'lon __NO_VERSION__ sarlavha fayl module.h, shu jumladan oldin oldini oladi
avtomatik chiziq tavsifi __modul_yadro_versiyasi yoki uning manba fayllaridagi ekvivalenti. Bu sizga bog'lovchi shikoyatlarini hal qilish uchun kerak bo'lishi mumkin ld -r havolalar jadvallaridagi belgilarning bir nechta tavsifini yoqtirmaydiganlar. Odatda, agar modul kodi bir nechta manba fayllariga, shu jumladan sarlavha fayliga bo'lingan bo'lsa keyin e'lon __NO_VERSION__ bu fayllarning bittasidan tashqari barchasida bajariladi. Kitobning oxirida moduldan foydalanish misoli mavjud __NO_VERSION__.

Yadro versiyasi bilan bog'liq bo'lgan bog'liqliklarning aksariyati makroslar yordamida preprotsessor ko'rsatmalariga asoslangan mantiq yordamida ishlov berilishi mumkin. KERNEL_VERSION va LINUX_VERSION_CODE... Biroq, versiyaga bog'liqlikni tekshirish turli xil ko'rsatmalar tufayli modul kodining o'qilishini sezilarli darajada murakkablashtirishi mumkin. #ifdef... Shuning uchun, ehtimol, eng yaxshi yechim, qaramlik tekshiruvini alohida sarlavha fayliga qo'yishdir. Shuning uchun bizning misolimiz sarlavha faylini o'z ichiga oladi sysdep.h versiyaga bog'liqlikni tekshirish bilan bog'liq barcha makroslarni o'z ichiga olish uchun ishlatiladi.

Biz taqdim qilmoqchi bo'lgan birinchi versiyaga bog'liqlik maqsadli deklaratsiyada " o'rnatish"Bizning drayverni kompilyatsiya qilish skriptimiz. Siz kutganingizdek, foydalanilgan yadro versiyasiga qarab o'zgarib turadigan o'rnatish katalogi version.h faylini ko'rish asosida tanlanadi. Mana fayldan kod parchasi. Qoidalar.make barcha yadro Makefiles tomonidan qo'llaniladi.

VERSIONFILE = $ (INCLUDEDIR) /linux/version.h VREION = $ (shell awk -F \ "" / REL / (chop etish $$ 2) "$ (VERSIONFILE)) INSTALLDIR = / lib / modullar / $ (VERSION) / boshqa

E'tibor bering, biz barcha drayverlarni o'rnatish uchun misc katalogidan foydalanamiz (yuqoridagi Makefile misolidagi INSTALLDIR deklaratsiyasi). Yadro 2.4 dan boshlab, ushbu katalog maxsus drayverlarni joylashtirish uchun tavsiya etilgan katalogdir. Bundan tashqari, modulils to'plamining eski va yangi versiyalari qidiruv yo'llarida turli xil kataloglarni o'z ichiga oladi.

Yuqorida keltirilgan INSTALLDIR taʼrifidan foydalanib, Makefileʼdagi oʻrnatish maqsadi quyidagicha koʻrinishi mumkin:

O'rnatish: install -d $ (INSTALLDIR) install -c $ (OBJS) $ (INSTALLDIR)

Platformaga bog'liqlik

Har bir hisoblash platformasi eng yuqori samaradorlikka erishish uchun yadro ishlab chiquvchilari tomonidan hisobga olinishi kerak bo'lgan o'ziga xos xususiyatlarga ega.

Yadro ishlab chiquvchilari tanlash va qaror qabul qilishda / PCLASS = "g'arbiy" va dastur ishlab chiquvchilarga qaraganda ko'proq erkinlikka ega. Aynan shu erkinlik sizga kodingizni optimallashtirishga imkon beradi va har bir aniq platformadan maksimal darajada siqib chiqadi.

Modul kodi yadroni kompilyatsiya qilishda foydalanilgan bir xil kompilyator variantlari yordamida kompilyatsiya qilinishi kerak. Bu bir xil protsessor registridan foydalanish namunalaridan foydalanishga ham, bir xil darajadagi optimallashtirishni amalga oshirishga ham tegishli. Fayl Qoidalar.make, yadro manba daraxtining ildizida joylashgan bo'lib, barcha Makefiles kompilyatsiyasiga kiritilishi kerak bo'lgan platformaga xos ta'riflarni o'z ichiga oladi. Barcha platformaga xos kompilyatsiya skriptlari Makefile deb nomlanadi. platforma va joriy yadro konfiguratsiyasiga muvofiq make yordam dasturi uchun o'zgaruvchilar qiymatlarini o'z ichiga oladi.

Makefile-ning yana bir qiziqarli xususiyati bu o'zaro platformalar yoki shunchaki o'zaro kompilyatsiya uchun qo'llab-quvvatlashdir. Ushbu atama boshqa platforma uchun kodni kompilyatsiya qilish kerak bo'lganda ishlatiladi. Masalan, i86 platformasidan foydalanib, siz M68000 platformasi uchun kod yaratmoqchisiz. Agar siz o'zaro kompilyatsiyadan foydalanmoqchi bo'lsangiz, unda siz kompilyatsiya vositalarini almashtirishingiz kerak ( gcc, ld va boshqalar) boshqa tegishli vositalar to'plami bilan
(masalan, m68k-linux-gcc, m68k-linux-ld). Amaldagi prefiks $ (CROSS_COMPILE) Makefile o'zgaruvchisi, make yordam dasturining buyruq qatori parametri yoki tizim muhiti o'zgaruvchisi tomonidan belgilanishi mumkin.

SPARC arxitekturasi maxsus holat bo'lib, u Makefile faylida to'g'ri ko'rib chiqilishi kerak. SPARC64 (SPARC V9) platformasida ishlaydigan foydalanuvchi dasturlari ikkilikdir, odatda SPARC32 (SPARC V8) platformasi uchun moʻljallangan. Shuning uchun, SPARC64 platformasidagi standart kompilyator (gcc) SPARC32 uchun ob'ekt kodini yaratadi. Boshqa tomondan, SPARC V9 da ishlash uchun mo'ljallangan yadro SPARC V9 uchun ob'ekt kodini o'z ichiga olishi kerak, shuning uchun ham o'zaro faoliyat kompilyator talab qilinadi. SPARC64-ga mo'ljallangan barcha GNU/Linux distributorlari yadro kompilyatsiya skriptining Makefile faylida tanlanishi kerak bo'lgan tegishli o'zaro kompilyatorni o'z ichiga oladi.

Garchi versiya va platformaga bog'liqliklarning to'liq ro'yxati bu erda tasvirlanganidan biroz murakkabroq bo'lsa-da, u o'zaro kompilyatsiya uchun hali ham etarli. Qo'shimcha ma'lumot olish uchun siz Makefile kompilyatsiya skriptlari va yadro manba fayllarini ko'rishingiz mumkin.

Yadro 2.6 xususiyatlari

Vaqt bir joyda turmaydi. Va endi biz 2.6 yadrosining yangi avlodi paydo bo'lishiga guvoh bo'lamiz. Afsuski, ushbu kitobning asli yangi yadroni qamrab olmaydi, shuning uchun tarjimon tarjimaga yangi bilim qo'shish erkinligini oladi.

Siz TimeSys 'TimeStorm kabi IDE'lardan foydalanishingiz mumkin, ular kerakli yadro versiyasiga qarab modulingizni to'g'ri skeletlari topadi va kompilyatsiya qiladi. Agar siz bularning barchasini o'zingiz yozmoqchi bo'lsangiz, unda sizga yangi yadro tomonidan kiritilgan asosiy farqlar haqida qo'shimcha ma'lumotlar kerak bo'ladi.

2.6 yadrosining xususiyatlaridan biri modul_init () va module_exit () makroslarini ishga tushirish va tugatish funksiyalarining nomlarini aniq qayd etish uchun foydalanish zaruratidir.

2.4 yadrosida kiritilgan MODULE_LISENCE () makrosi, agar siz modulni yuklashda tegishli ogohlantirishlarni ko'rishni istamasangiz, hali ham kerak bo'ladi. Makrosga oʻtkazish uchun quyidagi litsenziya qatorlarini tanlashingiz mumkin: “GPL”, “GPL v2”, “GPL va qoʻshimcha huquqlar”, “Dual BSD / GPL” (BSD yoki GPL litsenziyalari orasidan tanlang), “Dual MPL / GPL”( Mozilla yoki GPL litsenziyalari o'rtasida tanlov) va
"Xususiy".

Yangi yadro uchun modullarni kompilyatsiya qilishning yangi sxemasi muhimroq bo'lib, u nafaqat modulning kodini, balki uning kompilyatsiya skriptining Makefile faylini ham o'zgartirishni nazarda tutadi.

Shunday qilib, modul kodida ham, Makefile faylida ham MODUL so'l belgisining ta'rifi endi talab qilinmaydi. Agar kerak bo'lsa, yangi kompilyatsiya sxemasining o'zi ushbu so'l belgini belgilaydi. Bundan tashqari, __KERNEL__ makrolarini yoki KBUILD_BASENAME va KBUILD_MODNAME kabi yangilarini aniq belgilashingiz shart emas.

Bundan tashqari, kompilyatsiya vaqtini optimallashtirish darajasini ko'rsatmasligingiz kerak (-O2 yoki boshqalar), chunki modulingiz barcha bayroqlar to'plami bilan, jumladan, yadroingizdagi barcha boshqa modullar tuzilgan optimallashtirish bayroqlari bilan kompilyatsiya qilinadi - make yordam dasturi avtomatik ravishda barcha kerakli bayroqlar to'plamidan foydalanadi.

Shu sabablarga ko'ra, 2.6 yadrosi uchun modulni kompilyatsiya qilish uchun Makefile ancha oson. Shunday qilib, hello.c moduli uchun Makefile quyidagicha ko'rinadi:

Obj-m: = salom.o

Biroq, modulni kompilyatsiya qilish uchun sizga vaqtinchalik fayllar va kataloglar yaratiladigan yadro manba daraxtiga yozish huquqi kerak bo'ladi. Shuning uchun, modul manba kodini o'z ichiga olgan joriy katalogdan berilgan modulni 2.6 yadrosiga kompilyatsiya qilish buyrug'i quyidagicha ko'rinishi kerak:

# make -C /usr/src/linux-2.6.1 SUBDIRS = `pwd` modullari

Shunday qilib, biz modulning manbasiga egamiz salom-2.6.c, 2.6 yadroda kompilyatsiya qilish uchun:

//hello-2.6.c #include #o'z ichiga oladi #o'z ichiga oladi MODULE_LICENSE ("GPL"); static int __init my_init (void) (printk ("Salom dunyo \ n"); qaytish 0;); statik void __exit my_cleanup (void) (printk ("Good bye \ n"); modul_init (mening_init); modul_exit (mening_tozalashim);

Shunga ko'ra, bizda Makefile mavjud:

Obj-m: = salom-2.6.o

Makefile-ni quyidagi parametrlar bilan qayta ishlash uchun make yordam dasturini chaqiramiz:

# make -C / usr / src / linux-2.6.3 SUBDIRS = `pwd` modullari

Oddiy kompilyatsiya jarayoni quyidagi standart chiqish bilan davom etadi:

Yarating: `/usr/src/linux-2.6.3" katalogini kiriting *** Ogohlantirish: Buyruqlar satrida SUBDIRSni bekor qilish *** nomuvofiqliklarga olib kelishi mumkin: `arch / i386 / kernel / asm-offsets.s" yangilashni talab qiladi. . CHK o'z ichiga oladi / asm-i386 / asm_offsets.h CC [M] /home/knz/j.kernel/3/hello-2.6.o Modullarni qurish, 2-bosqich. /usr/src/linux-2.6.3/scripts/Makefile .modpost: 17: *** Uh-oh, sizda eskirgan modul yozuvlari bor. Siz SUBDIRS, /usr/src/linux-2.6.3/scripts/Makefile.modpost:18 bilan aralashib qoldingiz: agar biror narsa noto'g'ri bo'lsa, shikoyat qilmang. MODPOST CC /home/knz/j.kernel/3/hello-2.6.mod.o LD [M] /home/knz/j.kernel/3/hello-2.6.ko make: Chiqish katalogi `/ usr / src / linux-2.6.3 "

Kompilyatsiyaning yakuniy natijasi yadroga o'rnatilishi mumkin bo'lgan hello-2.6.ko modul fayli bo'ladi.

E'tibor bering, 2.6 yadrosida modul fayllari 2.4 yadrosidagi kabi .o emas, balki .ko qo'shimchasi bilan jihozlangan.

Yadro belgilari jadvali

Insmod yordam dasturi modulni yadroga ulashda yadroning umumiy belgilar jadvalidan qanday foydalanishi haqida allaqachon gapirgan edik. Ushbu jadvalda modulli drayver variantlarini amalga oshirish uchun zarur bo'lgan global yadro ob'ektlari - funktsiyalar va o'zgaruvchilar manzillari mavjud. Yadroning umumiy belgilar jadvali, agar yadroingiz / proc fayl tizimini qo'llab-quvvatlasa, / proc / ksyms faylidan matn shaklida o'qilishi mumkin.

2.6 yadrosida / proc / ksyms fayli / proc / modullarga o'zgartirildi.

Modul yuklanganda, modul tomonidan eksport qilinadigan belgilar yadro belgilari jadvalining bir qismiga aylanadi va siz uni / proc / ksyms dan ko'rishingiz mumkin.

Yangi modullar modulingiz tomonidan eksport qilingan belgilardan foydalanishi mumkin. Masalan, msdos moduli yog 'modul tomonidan eksport qilinadigan belgilarga tayanadi va o'qish rejimida ishlatiladigan har bir USB qurilmasi usbcore va kirish modullarining belgilaridan foydalanadi. Modullarni ketma-ket yuklash orqali amalga oshirilgan bu munosabat modullar stegi deb ataladi.

Modullar to'plami murakkab modul loyihalarini yaratishda foydalidir. Ushbu abstraktsiya qurilma drayverini kodini apparatga bog'liq va apparatga bog'liq bo'lmagan qismlarga ajratish uchun foydalidir. Misol uchun, video-for-linux drayverlari to'plami qo'llaniladigan uskunaning o'ziga xos xususiyatlarini hisobga oladigan past darajadagi drayver uchun belgilarni eksport qiluvchi asosiy moduldan iborat. Konfiguratsiyangizga ko'ra, siz asosiy video modulni va uskunangizga xos modulni yuklaysiz. Xuddi shunday, parallel portlar va USB qurilmalari kabi keng ko'lamli plagin qurilmalari uchun yordam ko'rsatiladi. Parallel port tizimi to'plami rasmda ko'rsatilgan. 2-2. O'qlar modullar va yadro API o'rtasidagi o'zaro ta'sirlarni ko'rsatadi. O'zaro ta'sir funksiyalar darajasida ham, funktsiyalar tomonidan boshqariladigan ma'lumotlar tuzilmalari darajasida ham sodir bo'lishi mumkin.

2-2-rasm. Parallel port modullari to'plami

Stacking modullaridan foydalanganda modprobe yordam dasturidan foydalanish qulay. Modprobe yordam dasturining funksionalligi ko'p jihatdan insmod yordam dasturiga o'xshaydi, lekin modul yuklanganda uning asosiy bog'liqliklarini tekshiradi va agar kerak bo'lsa, kerakli modullar to'plami to'ldirilguncha kerakli modullarni yuklaydi. Shunday qilib, bitta modprobe buyrug'i insmod buyrug'iga bir nechta qo'ng'iroqlarga olib kelishi mumkin. Aytishimiz mumkinki, modprobe - bu insmod ustidan aqlli o'rash. Joriy katalogdan maxsus modullarni yuklashdan tashqari hamma joyda insmod o'rniga modprobe dan foydalanishingiz mumkin. modprobe faqat modulning maxsus joylariga qaraydi va mumkin bo'lgan bog'liqliklarni qondira olmaydi.

Modullarni qismlarga bo'lish muammo bayonini soddalashtirish orqali ishlab chiqish vaqtini qisqartirishga yordam beradi. Bu qurilma drayverlariga kirish 1-bobida muhokama qilinadigan amalga oshirish mexanizmi va nazorat siyosati o'rtasidagi bo'linishga o'xshaydi.

Odatda modul o'z funksiyalarini belgilarni umuman eksport qilmasdan amalga oshiradi. Agar boshqa modullar undan foydalanishi mumkin bo'lsa, belgilarni eksport qilishingiz kerak bo'ladi. Statik bo'lmagan belgilarni eksport qilishning oldini olish uchun maxsus direktivani kiritishingiz kerak bo'lishi mumkin. modullarning aksariyat ilovalari sukut bo'yicha barchasini eksport qiladi.

Linux yadro sarlavhalari sizning belgilaringizning ko'rinishini boshqarishning qulay usulini ta'minlaydi va shu bilan yadro belgilari jadvali nom maydonining ifloslanishini oldini oladi. Ushbu bobda tasvirlangan mexanizm 2.1.18 versiyasidan boshlab yadrolarda ishlaydi. 2.0 yadrosi butunlay boshqacha boshqaruv mexanizmiga ega edi
belgilarning ko'rinishi, bu bobning oxirida tasvirlanadi.

Agar modulingiz belgilarni umuman eksport qilmasligi kerak bo'lsa, modul manba fayliga quyidagi so'l qo'ng'iroqni aniq joylashtirishingiz mumkin:

EXPORT_NO_SYMBOLS;

Linux / module.h faylida aniqlangan ushbu so'l chaqiruv assembler direktivasiga kengaytirilgan va modulning istalgan joyida ko'rsatilishi mumkin. Biroq, turli yadrolar uchun ko'chma kodni yaratishda, ushbu so'l qo'ng'iroqni modulning ishga tushirish funktsiyasiga (init_module) joylashtirish kerak, chunki biz sysdep.h faylimizda ushbu so'l ta'rifining versiyasi eski uchun aniqlangan. yadro versiyalari faqat shu yerda ishlaydi.

Boshqa tomondan, agar siz modulingizdan belgilarning ma'lum bir qismini eksport qilishingiz kerak bo'lsa, unda siz so'l belgisidan foydalanishingiz kerak.
EXPORT_SYMTAB... Ushbu makros aniqlanishi kerak old sarlavha fayl module.h jumladan. Bu umumiy qabul qilingan amaliyotdir
bayroq orqali ushbu so'l belgining ta'rifi -D Makefile faylida.

Agar so'l belgi bo'lsa EXPORT_SYMTAB Belgilangan bo'lsa, individual belgilar bir nechta makroslar yordamida eksport qilinishi mumkin:

EXPORT_SYMBOL (ism); EXPORT_SYMBOL_NOVERS (nomi);

Ushbu ikkita makrosning har biri berilgan belgini moduldan tashqarida mavjud qiladi. Farqi shundaki, makro EXPORT_SYMBOL_NOVERS versiya ma'lumotlari bo'lmagan belgini eksport qiladi ("kmod va Kengaytirilgan modulizatsiya" 11-bobga qarang). Qo'shimcha ma'lumot uchun
sarlavha faylini tekshiring , garchi yuqorida aytilganlar amaliy foydalanish uchun etarli
makroslar.

Modullarni ishga tushirish va yakunlash

Yuqorida aytib o'tilganidek, init_module () funktsiyasi modulning funktsional komponentlarini yadroda qayd etadi. Bunday ro'yxatdan o'tgandan so'ng, moduldan foydalanadigan dastur uchun modulga kirish nuqtalari yadro tomonidan taqdim etilgan interfeys orqali mavjud bo'ladi.

Modullar ko'plab turli komponentlarni ro'yxatdan o'tkazishi mumkin, ular ro'yxatdan o'tganda modul funktsiyalarining nomlari hisoblanadi. Taklif etilgan funksiyani amalga oshiradigan funktsiyalarga ko'rsatgichlarni o'z ichiga olgan ma'lumotlar strukturasiga ko'rsatgich asosiy ro'yxatga olish funktsiyasiga uzatiladi.

"Qurilma drayverlariga kirish" 1-bobida qurilmalarning asosiy turlari tasnifi keltirilgan. Siz nafaqat u erda ko'rsatilgan qurilmalar turlarini, balki boshqa har qanday qurilmalarni, masalan, / proc fayl tizimining fayllari va boshqalar kabi dasturiy ta'minot abstraktsiyalarini ro'yxatdan o'tkazishingiz mumkin. API drayveri orqali yadroda ishlashi mumkin bo'lgan har qanday narsa bo'lishi mumkin. haydovchi sifatida ro'yxatdan o'tgan.

Agar siz yadro misolingiz uchun roʻyxatdan oʻtgan drayverlarning turlari haqida koʻproq maʼlumotga ega boʻlishni istasangiz, yadro manbalarida EXPORT_SYMBOL pastki qatorini qidirishni amalga oshirishingiz va turli drayverlar tomonidan taklif qilingan kirish nuqtalarini topishingiz mumkin. Qoida tariqasida, ro'yxatga olish funktsiyalari o'z nomidagi prefiksdan foydalanadi ro'yxatdan o'tish_,
shuning uchun ularni topishning yana bir mumkin bo'lgan usuli pastki qatorni qidirishdir ro'yxatdan o'tish_ grep yordam dasturidan foydalangan holda / proc / ksyms faylida. Yuqorida aytib o'tilganidek, 2.6.x yadrosida / proc / ksyms fayli / proc / modullari bilan almashtiriladi.

init_module da ishlov berishda xato

Agar modulni ishga tushirish paytida biron bir xatolik yuzaga kelsa, modulni yuklashni to'xtatishdan oldin amalga oshirilgan ishga tushirishni bekor qilishingiz kerak. Masalan, ma'lumotlar tuzilmalarini taqsimlashda tizimda xotira etarli emasligi sababli xatolik yuzaga kelishi mumkin. Afsuski, bu sodir bo'lishi mumkin va yaxshi kod bu vaziyatlarni hal qilishi kerak.

init_module () ishga tushirish funksiyasida xatolik yuz berishidan oldin roʻyxatga olingan yoki ajratilgan har qanday narsa oʻz-oʻzidan bekor qilinishi yoki chiqarilishi kerak, chunki Linux yadrosi ishga tushirish xatolarini kuzatmaydi va modul kodi tomonidan allaqachon bajarilgan qarz olish va resurslarni taqsimlashni bekor qilmaydi. Agar siz orqaga qaytmagan bo'lsangiz yoki ro'yxatdan o'tishni orqaga qaytara olmasangiz, yadro beqaror holatda qoladi va modul qayta yuklanganda.
siz allaqachon ro'yxatdan o'tgan narsalarni qayta ro'yxatdan o'tkaza olmaysiz va avval qilingan ro'yxatdan o'tishni bekor qila olmaysiz, chunki init_module () funktsiyasining yangi nusxasida ro'yxatdan o'tgan funksiyalar manzillari uchun to'g'ri qiymatga ega bo'lmaysiz. Tizimni avvalgi holatiga qaytarish turli xil murakkab fokuslarni talab qiladi va ko'pincha bu tizimni oddiy qayta ishga tushirish orqali amalga oshiriladi.

Modulni ishga tushirishda xatolik yuz bergan taqdirda tizimning oldingi holatini tiklashni amalga oshirish eng yaxshi goto operatori yordamida amalga oshiriladi. Odatda, bu operatorga juda salbiy munosabatda bo'lishadi va hatto nafrat bilan, lekin bu vaziyatda u juda foydali bo'lib chiqadi. Shuning uchun yadroda goto operatori ko'pincha modulni ishga tushirish xatolarini boshqarish uchun ishlatiladi.

Quyidagi oddiy kod misol sifatida soxta ro'yxatga olish va bekor qilish funksiyalaridan foydalangan holda xatolarni hal qilishning bu usulini ko'rsatadi.

Int init_module (void) (int err; / * ro'yxatdan o'tish ko'rsatkich va nom oladi * / err = register_this (ptr1, "skull"); if (err) bo'lsa fail_this; err = register_that (ptr2, "skull"); agar (err) o'tish muvaffaqiyatsiz_; err = ro'yxatga olish_o'sha (ptr3, "bosh suyagi"); agar (xato) bo'lsa, muvaffaqiyatsiz_busa; 0 qaytaring; / * muvaffaqiyat * / fail_those: unregister_that (ptr2, "skull"); fail_that: register_buni (ptr1, " bosh suyagi "); fail_this: return err; / * xatoni tarqatish * /)

Ushbu misol uchta modul komponentini ro'yxatdan o'tkazishga harakat qiladi. Goto bayonoti ro'yxatdan o'tishda xatolik yuzaga kelganda ishlatiladi va modul yuklashni to'xtatmasdan oldin ro'yxatdan o'tgan komponentlarni ro'yxatdan o'tkazmaydi.

Oson o'qiladigan kod uchun goto iborasidan foydalanishning yana bir misoli - modulning muvaffaqiyatli yakunlangan ro'yxatga olish operatsiyalarini "eslab qolish" va xatolik yuz berganda ushbu ma'lumot bilan cleanup_module () ni chaqirish. Cleanup_module () funktsiyasi bajarilgan ishga tushirish operatsiyalarini orqaga qaytarish uchun mo'ljallangan va modul tushirilganda avtomatik ravishda chaqiriladi. init_module () funktsiyasi tomonidan qaytarilgan qiymat bo'lishi kerak
modulni ishga tushirish xato kodini ifodalaydi. Linux yadrosida xato kodi sarlavha faylida qilingan ko'plab ta'riflardan olingan salbiy raqamdir. ... -ENODEV, -ENOMEM va boshqalar kabi zahiradagi xato kodlarining ramziy mnemonikasidan foydalanish uchun ushbu sarlavha faylini modulingizga qo'shing. Bunday mnemonikadan foydalanish yaxshi dasturlash uslubi hisoblanadi. Ammo shuni ta'kidlash kerakki, modulils yordam dasturlarining ba'zi versiyalari qaytarilgan xato kodlari bilan to'g'ri ishlamaydi va "Qurilma band" xabarini ko'rsatadi.
init_modules () tomonidan qaytarilgan butunlay boshqa xatolar to'plamiga javoban. Paketning so'nggi versiyalarida bu
zerikarli xato tuzatildi.

Yuqoridagi holat uchun cleanup_module () funktsiya kodi, masalan, quyidagicha bo'lishi mumkin:

Tozalash_modulini bekor qilish (yaroqsiz) (bularni ro'yxatdan o'chirish (ptr3, "bosh suyagi"); ro'yxatdan_o'chirish (ptr2, "bosh suyagi"); ro'yxatdan_ olib tashlash (ptr1, "bosh suyagi"); qaytish;)

Agar ishga tushirish va tugatish kodingiz bu yerda tasvirlanganidan murakkabroq bo'lsa, goto iborasidan foydalanish dastur kodini o'qish qiyin bo'lishi mumkin, chunki tugatish kodi init_module () funksiyasida o'tish uchun bir nechta teglar yordamida takrorlanishi kerak. . Shu sababli, modulni yuklashda xatolik yuzaga kelganda, muvaffaqiyatli ishga tushirish miqdori haqida ma'lumotni uzatuvchi init_module () funktsiyasidagi cleanup_module () funksiyasiga qo'ng'iroq qilish orqali yanada murakkab usul qo'llaniladi.

Quyida init_module () va cleanup_module () shu tarzda qanday yozilishiga misol keltirilgan. Ushbu misol muvaffaqiyatli ishga tushirish miqdori haqida ma'lumot berish uchun global miqyosda belgilangan ko'rsatkichlardan foydalanadi.

Biror narsani tuzing * element1; struct something elsese * element2; int stuff_ok; bekor qilish_tozalash_moduli (void) (agar (element1) bo'shatish_narsa (element1); agar (2-modda) chiqarish_narsa (2-modda); agar (materiallar) register_narsa (); return;) int init_module (void) (int err = -ENOMEM; element1 = ajratish_thing (argumentlar); element2 = allocate_thing2 (argumentlar2); agar (! element2 ||! element2) bajarilmasa; err = register_stuff (element1, element2); agar (! err) stuff_ok = 1; aks holda bajarilmaydi; 0 qaytaring; / * muvaffaqiyat * / muvaffaqiyatsiz: cleanup_module (); qaytish xatosi;)

Modulingizni ishga tushirish operatsiyalarining murakkabligiga qarab, modulni ishga tushirish xatolarini boshqarish uchun bu yerda tasvirlangan usullardan birini qo'llashingiz mumkin.

Moduldan foydalanish hisoblagichi

Tizimda modulni xavfsiz tushirish mumkinligini aniqlash uchun har bir modul uchun foydalanish hisoblagichi mavjud. Tizimga bu maʼlumot kerak, chunki modul kimdir yoki biror narsa bilan band boʻlsa, uni oʻchirib boʻlmaydi - agar ushbu fayl tizimi oʻrnatilgan boʻlsa, fayl tizimi drayverini oʻchira olmaysiz yoki biror jarayon ushbu qurilmadan foydalansa, belgili qurilma modulini oʻchira olmaysiz. Aks holda,
bu tizimning ishdan chiqishiga olib kelishi mumkin - segmentatsiya xatosi yoki yadro vahima.

Zamonaviy yadrolarda tizim sizni keyingi bobda ko'rib chiqadigan mexanizm yordamida moduldan foydalanish uchun avtomatik hisoblagich bilan ta'minlashi mumkin. Yadro versiyasidan qat'i nazar, siz ushbu hisoblagichni qo'lda boshqarishdan foydalanishingiz mumkin. Shunday qilib, yadroning eski versiyalarida ishlatilishi kerak bo'lgan kod quyidagi uchta makrosga asoslangan moduldan foydalanishni hisobga olish modelidan foydalanishi kerak:

MOD_INC_USE_COUNT Joriy modulning foydalanish hisoblagichini oshiradi MOD_DEC_USE_COUNT Joriy modulning foydalanish hisoblagichini kamaytiradi MOD_IN_USE Ushbu modul uchun foydalanish hisoblagichi nolga teng bo'lsa, true qiymatini qaytaradi

Ushbu makroslar ichida belgilangan , va ular to'g'ridan-to'g'ri kirish istalmagan maxsus ichki ma'lumotlar tuzilmasini manipulyatsiya qiladi. Haqiqat shundaki, ushbu ma'lumotlarni boshqarishning ichki tuzilishi va usuli versiyadan versiyaga o'zgarishi mumkin, bu makrolardan foydalanish uchun tashqi interfeys o'zgarishsiz qoladi.

E'tibor bering, tekshirishingiz shart emas MOD_IN_USE cleanup_module () funksiyasi kodida, chunki bu tekshirish kernel / module.c da aniqlangan sys_delete_module () tizim chaqiruvida cleanup_module () ni chaqirishdan oldin avtomatik ravishda amalga oshiriladi.

Moduldan foydalanish hisoblagichini to'g'ri boshqarish tizim barqarorligi uchun juda muhimdir. Esda tutingki, yadro istalgan vaqtda foydalanilmagan modulni avtomatik ravishda tushirishga qaror qilishi mumkin. Modullarni dasturlashda keng tarqalgan xato - bu hisoblagichni noto'g'ri boshqarish. Masalan, so'rovga javoban modul kodi ba'zi harakatlarni bajaradi va ishlov berish tugagach, moduldan foydalanish hisoblagichini oshiradi. Bular. Bunday dasturchi ushbu hisoblagich moduldan foydalanish bo'yicha statistik ma'lumotlarni to'plash uchun mo'ljallangan deb hisoblaydi, aslida esa, bu, aslida, joriy modul bandligi uchun hisoblagich, ya'ni. hozirda modul kodidan foydalanayotgan jarayonlar sonini kuzatib boradi. Shunday qilib, modulga so'rovni qayta ishlashda siz qo'ng'iroq qilishingiz kerak MOD_INC_USE_COUNT har qanday harakat qilishdan oldin, va MOD_DEC_USE_COUNT ularni tugatgandan keyin.

Ma'lum sabablarga ko'ra moduldan foydalanish hisoblagichi ustidan nazoratni yo'qotib qo'ysangiz, uni tushira olmaydigan holatlar bo'lishi mumkin. Bunday holat modulni ishlab chiqish bosqichida tez-tez uchrab turadi. Misol uchun, jarayon NULL ko'rsatkichni o'chirishga harakat qilganda to'xtatilishi mumkin va siz uning foydalanish hisoblagichini nolga qaytarmaguningizcha bunday modulni yuklay olmaysiz. Modulni nosozliklarni tuzatish bosqichida ushbu muammoni hal qilishning mumkin bo'lgan echimlaridan biri moduldan foydalanish hisoblagichini boshqarishdan butunlay voz kechishdir. MOD_INC_USE_COUNT va MOD_DEC_USE_COUNT bo'sh kodga. Yana bir yechim moduldan foydalanish hisoblagichini nolga majburlash uchun ioctl () chaqiruvini amalga oshirishdir. Biz buni 5-bobning “Charli drayverning kengaytirilgan ishlashi”ning “ioctl argumentidan foydalanish” bo‘limida ko‘rib chiqamiz. Albatta, foydalanishga tayyor drayverda hisoblagich bilan bunday soxta manipulyatsiyalar istisno qilinishi kerak, ammo disk raskadrovka bosqichida ular ishlab chiquvchining vaqtini tejaydi va juda maqbuldir.

Har bir modul uchun tizimdan foydalanish hisoblagichining joriy qiymatini / proc / modules faylidagi har bir yozuvning uchinchi maydonida topishingiz mumkin. Ushbu faylda joriy yuklangan modullar haqidagi ma'lumotlar mavjud - har bir modul uchun bitta qator. Qatorning birinchi maydoni modul nomini o'z ichiga oladi, ikkinchi maydon xotirada modul egallagan o'lcham, uchinchi maydon esa foydalanish hisoblagichining joriy qiymati. Ushbu ma'lumot formatlangan shaklda,
lsmod yordam dasturini chaqirish orqali olish mumkin. Quyida misol / proc / modul fayli:

Parport_pc 7604 1 (avtomatik tozalash) lp 4800 0 (ishlatilmagan) parport 8084 1 qulflangan 33256 1 (avtomatik tozalash) sunrpc 56612 1 (avtomatik tozalash) ds 6252 1 i82365 22304 core1cm102

Bu erda biz tizimga yuklangan bir nechta modullarni ko'ramiz. Bayroqlar maydonida (qatorning oxirgi maydoni) modulga bog'liqlik stegi kvadrat qavs ichida ko'rsatiladi. Boshqa narsalar qatorida, siz parallel port modullari 1-rasmda ko'rsatilganidek, modullar to'plami orqali aloqa qilishini sezishingiz mumkin. 2-2. (Avtomatik tozalash) bayroq kmod yoki yadro tomonidan boshqariladigan modullarni belgilaydi. Bu 11-bobda, “kmod va kengaytirilgan modullashtirish”da yoritiladi). (ishlatilmagan) bayroq modul hozirda ishlatilmayotganligini bildiradi. 2.0 yadrosida o'lcham maydoni ma'lumotni baytlarda emas, balki ko'pgina platformalar uchun hajmi 4 KB bo'lgan sahifalarda ko'rsatadi.

Modulni tushirish

Modulni tushirish uchun rmmod yordam dasturidan foydalaning. Modulni tushirish uni yuklashdan ko'ra oddiyroq vazifa bo'lib, uni yadro bilan dinamik bog'laydi. Modul o'chirilganda, Delete_module () tizim chaqiruvi bajariladi, agar uning foydalanish hisoblagichi nolga teng bo'lsa, yuklanmagan modulning cleanup_module () funksiyasini chaqiradi yoki xato bilan tugaydi.

Yuqorida aytib o'tilganidek, cleanup_module () funktsiyasida modul yuklanganda bajarilgan ishga tushirish operatsiyalari cleanup_module () funksiyasi tomonidan orqaga qaytariladi. Shuningdek, modulning eksport qilingan belgilari avtomatik ravishda o'chiriladi.

Yakunlash va ishga tushirish funktsiyalarini aniq belgilash

Yuqorida aytib o'tilganidek, modulni yuklashda yadro init_module () funktsiyasini chaqiradi va uni tushirishda cleanup_module () ni chaqiradi. Biroq, yadroning zamonaviy versiyalarida bu funktsiyalar ko'pincha turli nomlarga ega. 2.3.23 yadrosidan boshlab modulni yuklash va tushirish funksiyasi nomini aniq belgilash mumkin bo'ldi. Endi bu funksiyalarni aniq nomlash uchun dasturlash uslubi tavsiya etiladi.

Keling, bir misol keltiraylik. Agar siz mos ravishda init_module () va cleanup_module () o'rniga my_init () funksiyasini modulingizni ishga tushirish funksiyasi va my_cleanup () funksiyasini oxirgi funksiya sifatida e'lon qilmoqchi bo'lsangiz, quyidagi ikkitasini qo'shishingiz kerak bo'ladi. modul matni bilan makroslar (odatda ular oxirida kiritiladi
modul manba fayli):

Module_init (my_init); modul_exit (mening_tozalashim);

E'tibor bering, ushbu makroslardan foydalanish uchun siz modulingizga sarlavha faylini kiritishingiz kerak bo'ladi. .

Ushbu uslubdan foydalanishning qulayligi shundaki, yadrodagi har bir modulni ishga tushirish va yakunlash funksiyasi o'ziga xos nomga ega bo'lishi mumkin, bu esa disk raskadrovkada katta yordam beradi. Bundan tashqari, ushbu funktsiyalardan foydalanish drayver kodini modul sifatida qo'llayotganingizdan yoki uni to'g'ridan-to'g'ri yadroga joylashtirmoqchi bo'lishingizdan qat'i nazar, disk raskadrovkani soddalashtiradi. Albatta, modul_init va module_exit makroslaridan foydalanish shart emas, agar ishga tushirish va tugatish funksiyalaringiz zahiradagi nomlarga ega boʻlsa, yaʼni. mos ravishda init_module () va cleanup_module ().

Agar siz 2.2 yoki undan keyingi versiya yadrolari uchun manbalar bilan tanish bo'lsangiz, ishga tushirish va tugatish funksiyasi uchun tavsifning biroz boshqacha shaklini ko'rishingiz mumkin. Masalan:

Static int __init my_init (void) (....) static void __exit my_cleanup (void) (....)

Atributlardan foydalanish __init ishga tushirish tugallangach, ishga tushirish funksiyasi xotiradan olib tashlanishiga olib keladi. Biroq, bu faqat o'rnatilgan yadro drayverlari uchun ishlaydi va modullar uchun e'tiborga olinmaydi. Shuningdek, yadroga o'rnatilgan drayverlar uchun atribut __Chiqish bu atribut bilan belgilangan butun funksiyani e'tiborsiz qolishiga olib keladi. Modullar uchun bu bayroq ham e'tiborga olinmaydi.

Atributlardan foydalanish __init(va __initdata ma'lumotlarni tavsiflash uchun) yadro tomonidan ishlatiladigan xotira hajmini kamaytirishi mumkin. Belgilash __init modulni ishga tushirish funksiyasi hech qanday foyda yoki zarar keltirmaydi. Ushbu ishga tushirish usulini boshqarish modullar uchun hali amalga oshirilmagan, ammo bu kelajakda amalga oshirilishi mumkin.

Xulosa qilish

Shunday qilib, taqdim etilgan material natijasida biz "Salom dunyo" modulining quyidagi versiyasini taqdim etishimiz mumkin:

Modul manba fayl kodi =============================================== # o'z ichiga oladi #o'z ichiga oladi #o'z ichiga oladi statik int __init my_init_module (bekor) (EXPORT_NO_SYMBOLS; printk ("<1>Salom dunyo \ n "); qaytish 0;); statik bekor __tozalash_modulimdan chiqish (void) (printk ("<1>Xayr \ n "); module_init (mening_init_module); module_exit (mening_tozalash_modulim); MODULE_LICENSE ("GPL"); ======================= ====================== Modulni kompilyatsiya qilish uchun Makefile ====================== = ==================== CFLAGS = -Wall -D__KERNEL__ -DMODULE -I / lib / modullar / $ (qobiq unname -r) / qurish / salom o'z ichiga oladi. o: ================================================ ================================

Makefile faylini yozishda biz CFLAGS o'zgaruvchisi va tizimda mavjud kompilyator asosida ob'ekt faylini qanday yaratishni mustaqil ravishda aniqlashi mumkin bo'lgan GNU konventsiyasidan foydalanganmiz.

Resurslardan foydalanish

Xotira, kiritish/chiqarish portlari, kiritish/chiqarish xotirasi, uzilish liniyalari va DMA kanallari kabi tizim resurslaridan foydalanmasdan modul o‘z vazifasini bajara olmaydi.

Dasturchi sifatida siz yig'ish boshqaruvi bilan allaqachon tanish bo'lishingiz kerak. Yadrodagi to'plarni boshqarish tubdan farq qilmaydi. Dasturingiz funksiya yordamida xotirani olishi mumkin kmalloc () va uni ozod qiling kfree ()... Bu funktsiyalar tanish malloc () va bepul () ga juda o'xshaydi, bundan tashqari qo'shimcha ustuvor argument kmalloc () ga uzatiladi. Odatda ustuvorlik GFP_KERNEL yoki GFP_USER hisoblanadi. GFP - bu "bepul sahifa olish" ning qisqartmasi - bepul sahifani oling. Yadro to'plamini boshqarish "Xotirani qo'lga kiritish" 7-bobida batafsil yoritilgan.

Ajam drayverni ishlab chiquvchisi kirish/chiqarish portlarini, kiritish-chiqarish xotirasini va uzilish liniyalarini aniq ajratish zaruratidan hayron bo'lishi mumkin. Shundagina yadro moduli ushbu resurslarga osongina kirishi mumkin. Tizim xotirasi har qanday joydan ajratilishi mumkin bo'lsa-da, kiritish-chiqarish xotirasi, portlar va uzilish liniyalari alohida rol o'ynaydi va boshqacha taqsimlanadi. Misol uchun, haydovchi ma'lum portlarni ajratishi kerak, emas
hamma narsa, lekin u qurilmani boshqarishi kerak bo'lgan narsalar. Ammo haydovchi bu resurslardan boshqa birov tomonidan foydalanilmayotganiga ishonch hosil qilmaguncha foydalana olmaydi.

Periferik qurilmaga tegishli xotira maydoni odatda tizim operativ xotirasidan (RAM) farqlash uchun kirish / chiqish xotirasi deb ataladi, oddiygina xotira.

Kirish-chiqarish portlari va xotira

Odatda haydovchining ishi asosan o'qish va yozish portlari va kiritish-chiqarish xotirasidan iborat. Portlar va kirish/chiqarish xotirasi birgalikda kirish/chiqarish hududi (yoki hududi) deb ataladi.

Afsuski, har bir avtobus arxitekturasi har bir qurilmaga tegishli kirish / chiqish hududini aniq belgilay olmaydi va haydovchi unga tegishli hududning joylashishini taxmin qilishi yoki hatto mumkin bo'lgan manzil bo'shliqlarini o'qish / yozish operatsiyalarini sinab ko'rishi mumkin. . Bu muammo ayniqsa
ISA avtobusiga tegishli bo'lib, u hali ham shaxsiy kompyuterga oddiy qurilmalarni o'rnatish uchun ishlatiladi va sanoat dunyosida PC / 104 ni amalga oshirishda juda mashhur (15-bobdagi "Kompyuter / 104 va PC / 104 +" bo'limiga qarang. "Periferik avtobuslarning umumiy ko'rinishi").

Uskuna qurilmasini ulash uchun qaysi avtobus ishlatilmasin, drayverlar o'rtasidagi to'qnashuvlarning oldini olish uchun qurilma drayveriga uning kiritish-chiqarish hududiga eksklyuziv kirish kafolatlanishi kerak. Agar modul o'z qurilmasiga taalluqli bo'lsa, unga tegishli bo'lmagan qurilmaga yozsa, bu halokatli oqibatlarga olib kelishi mumkin.

Linux ishlab chiquvchilari, asosan, turli qurilmalar o'rtasidagi to'qnashuvlarning oldini olish uchun kirish / chiqish hududlari uchun so'rov / chiqarish mexanizmini amalga oshirdilar. Ushbu mexanizm uzoq vaqtdan beri kirish / chiqish portlari uchun ishlatilgan va yaqinda umuman olganda resurslarni boshqarish mexanizmiga umumlashtirildi. E'tibor bering, ushbu mexanizm dasturiy ta'minot abstraktsiyasi bo'lib, apparat imkoniyatlariga taalluqli emas. Masalan, apparat darajasida kirish/chiqarish portlariga ruxsatsiz kirish “segmentatsiya xatosi”ga o'xshash xatolikka olib kelmaydi, chunki apparat o'z resurslarini ajratmaydi va avtorizatsiya qilmaydi.

Ro'yxatdan o'tgan resurslar haqida ma'lumot matn shaklida / proc / ioports va / proc / ioem fayllarida mavjud. Ushbu ma'lumot Linuxda yadro 2.3 dan beri taqdim etilgan. Eslatib o'tamiz, ushbu kitob birinchi navbatda 2.4 yadrosiga qaratilgan va muvofiqlik eslatmalari bobning oxirida taqdim etiladi.

Portlar

Quyida / proc / ioports faylining odatiy mazmuni keltirilgan:

0000-001f: dma1 0020-003f: pic1 0040-005f: taymer 0060-006f: klaviatura 0080-008f: dma sahifasi reg 00a0-00bf: pic2 00c0-00df: dma700017-0017: f17-001f : ide0 02f8-02ff: seriyali (to‘plam) 0300-031f: NE2000 0376-0376: ide1 03c0-03df: vga + 03f6-03f6: ide0 03f8-03ff: serial (to‘plam) 10f8-03ff: serial (to‘plam) 10f8-03ff: Intel 10f8-01-01-1000-010-000-000-000-000-0000-0000-000-000-0000-000-00-00-00-00-00-01 1003 : acpi 1004-1005: acpi 1008-100b: acpi 100c-100f: acpi 1100-110f: Intel korporatsiyasi 82371AB PIIX4 IDE 1300-131f: pcnet_cs 14004-1005: pcnet_cs 1400000PI IX800PIAC korporatsiyasi #3800-01-Pcnet_cs - 1cff: PCI CardBus # 04 5800-581f: Intel korporatsiyasi 82371AB PIIX4 USB d000-dfff: PCI avtobus # 01 d000-d0ff: ATI Technologies Inc 3D Rage LT Pro AGP-133

Ushbu faylning har bir satri drayver yoki qurilma egasi bilan bog'langan portlar diapazonini o'n oltilik tizimda ko'rsatadi. Yadroning oldingi versiyalarida fayl bir xil formatga ega, faqat port ierarxiyasi ko'rsatilmagan.

Tizimga yangi qurilma qo'shganda port to'qnashuvining oldini olish uchun fayldan foydalanish mumkin. Bu, ayniqsa, jumperlarni (jamperlarni) almashtirish orqali o'rnatilgan uskunani qo'lda sozlashda qulaydir. Bunday holda, foydalanuvchi foydalanilgan portlar ro'yxatini osongina ko'rishi va o'rnatilgan qurilma uchun bo'sh diapazonni tanlashi mumkin. Garchi zamonaviy qurilmalarning aksariyati qo'lda o'tish moslamalarini umuman ishlatmasa ham, ular hali ham kichik o'lchamli qismlarni ishlab chiqarishda qo'llaniladi.

Eng muhimi, / proc / ioports fayli bilan bog'liq bo'lgan dasturiy jihatdan mavjud bo'lgan ma'lumotlar tuzilmasi mavjud. Shuning uchun, qurilma drayveri ishga tushirilganda, u kirish / chiqish portlarining band bo'lgan diapazonini bilib oladi. Bu shuni anglatadiki, agar yangi qurilmani qidirishda portlarni skanerlash kerak bo'lsa, haydovchi xorijiy qurilmalar egallagan portlarga yozish holatidan qochishga qodir.

ISA avtobusini skanerlash xavfli vazifa ekanligi ma'lum. Shuning uchun, rasmiy Linux yadrosi bilan tarqatilgan ba'zi drayverlar modulni yuklashda ushbu skanerdan qochishadi. Shunday qilib, ular boshqa uskunalar tomonidan ishlatiladigan portlarga yozish orqali ishlaydigan tizimga zarar etkazish xavfidan qochishadi. Yaxshiyamki, zamonaviy avtobus arxitekturalari bu muammolardan himoyalangan.

I/U registrlariga kirish uchun foydalaniladigan dasturlash interfeysi quyidagi uchta funktsiyadan iborat:

Int check_region (imzosiz uzoq start, unsigned long len); struct resource * request_region (imzosiz uzoq start, unsigned long len, char * name); void release_region (imzosiz uzoq start, unsigned long len);

Funktsiya check_region () belgilangan port diapazoni bandligini tekshirish uchun chaqirilishi mumkin. Agar javob salbiy bo'lsa, u salbiy xato kodini qaytaradi (masalan, -EBUSY yoki -EINVAL).

Funktsiya so'rov_mintaqasi () ko'rsatilgan manzillar oralig'ini taqsimlashni amalga oshiradi, muvaffaqiyatga nol bo'lmagan ko'rsatgichni qaytaradi. Haydovchi qaytarilgan ko'rsatgichni saqlashi yoki ishlatishi shart emas. Siz qilishingiz kerak bo'lgan yagona narsa uni NULL uchun tekshirish. Faqat yadro 2.4 (yoki undan yuqori) bilan ishlashi kerak bo'lgan kod umuman check_region () ni chaqirishi shart emas. Bu tarqatish usulining afzalligi shubhasiz, chunki
check_region () va request_region () ga qo'ng'iroqlar o'rtasida nima bo'lishi noma'lum. Agar siz yadroning eski versiyalari bilan moslikni saqlamoqchi bo'lsangiz, request_region () dan oldin check_region () ni chaqirish kerak.

Funktsiya reliz_mintaqasi () haydovchi ilgari ishlatilgan portlarni chiqarganda chaqirilishi kerak.

request_region () tomonidan qaytarilgan haqiqiy ko'rsatkich qiymati faqat yadroda ishlaydigan resurs taqsimlovchi tomonidan ishlatiladi.

Bu uchta funktsiya aslida makrolarda belgilangan .

Quyida portlarni ro'yxatga olish uchun foydalaniladigan qo'ng'iroqlar ketma-ketligidan foydalanishga misol keltirilgan. Misol bosh suyagi haydovchi kodidan olingan. (Skull_probe_hw () funksiyasi uchun kod bu yerda ko‘rsatilmagan, chunki u apparatga bog‘liq kodni o‘z ichiga oladi.)

#o'z ichiga oladi #o'z ichiga oladi static int skull_detect (imzosiz int port, unsigned int diapazoni) (int err; if ((err = check_region (port, diapazon)))< 0) return err; /* busy */ if (skull_probe_hw(port,range) != 0) return -ENODEV; /* not found */ request_region(port,range,"skull"); /* "Can"t fail" */ return 0; }

Ushbu misol birinchi navbatda kerakli port diapazonining mavjudligini tekshiradi. Agar portlar mavjud bo'lmasa, u holda uskunaga kirish mumkin emas.
Qurilmaning haqiqiy port joylarini skanerlash orqali tekshirish mumkin. Ushbu misolda request_region () funksiyasi bo'lmasligi kerak.
muvaffaqiyatsiz yakunlanadi. Yadro bir vaqtning o'zida bir nechta modulni yuklay olmaydi, shuning uchun port to'qnashuvi bo'lmaydi.
kerak.

Haydovchi tomonidan ajratilgan har qanday kirish/chiqarish portlari keyinchalik chiqarilishi kerak. Bizning bosh suyagi drayverimiz buni cleanup_module () funksiyasida bajaradi:

Statik void skull_release (imzosiz int port, unsigned int diapazon) (release_region (port, diapazon);)

Resurslarni so'rash / chiqarish mexanizmi modullarni ro'yxatdan o'tkazish / ro'yxatdan o'chirish mexanizmiga o'xshaydi va yuqorida tavsiflangan goto bayonoti asosida mukammal tarzda amalga oshiriladi.

Xotira

Kirish / chiqish xotirasi haqida ma'lumot / proc / iomem fayli orqali mavjud. Quyida shaxsiy kompyuter uchun bunday faylning odatiy namunasi keltirilgan:

00000000-0009fbff: System RAM 0009fc00-0009ffff: himoyalangan 000a0000-000bffff: Video RAM maydoni 000c0000-000c7fff: Video ROM 000f0000-000fffff: System ROM 00100000-03feffff: System RAM 00100000-0022c557: Kernel kodi 0022c558-0024455f: Kernel ma'lumotlar 20000000 2fffffff : Intel korporatsiyasi 440BX / ZX - 82443BX / ZX Xost ko'prigi 68000000-68000fff: Texas Instruments PCI1225 68001000-68001fff: Texas Instruments PCI1225 (# 2) e0000000 # e0000000 # e0000000 PCI e0000000 e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e0000000 # e00000000 ATI Technologies Inc 3D Rage LT Pro AGP-133 e6000000-e6000fff: ATI Technologies Inc 3D Rage LT Pro AGP-133 fffc0000-ffffffff: himoyalangan

Manzil diapazonlari uchun qiymatlar o'n oltilik yozuvda ko'rsatilgan. Har bir manzil diapazoni uchun uning egasi ko'rsatiladi.

Kirish/chiqish xotirasiga kirishni ro'yxatdan o'tkazish kirish/chiqarish portlarini ro'yxatdan o'tkazishga o'xshaydi va yadrodagi bir xil mexanizmga qurilgan.

I/U xotira manzillarining kerakli diapazonini olish va chiqarish uchun haydovchi quyidagi qo'ng'iroqlardan foydalanishi kerak:

Int check_mem_region (imzosiz uzoq boshlash, imzosiz uzun len); int request_mem_region (imzosiz uzoq boshlash, imzosiz uzun len, char * nomi); int release_mem_region (imzosiz uzoq boshlash, imzosiz uzun len);

Odatda, drayver kiritish-chiqarish xotira manzillari diapazonini biladi, shuning uchun ushbu resurs uchun ajratish kodi port diapazonini ajratish misoliga nisbatan qisqartirilishi mumkin:

Agar (check_mem_region (mem_addr, mem_size)) (printk ("drayver nomi: xotira allaqachon ishlatilgan \ n"); return -EBUSY;) request_mem_region (mem_addr, mem_size, "drivername");

Linuxda resurslarni taqsimlash 2.4

Joriy resurslarni taqsimlash mexanizmi Linux 2.3.11 yadrosida joriy qilingan va tizim resurslarini boshqarish uchun moslashuvchan kirishni ta'minlaydi. Ushbu bo'limda ushbu mexanizm qisqacha tavsiflanadi. Biroq, asosiy resurslarni taqsimlash funktsiyalari (masalan, so'rov_region () va boshqalar) hali ham makroslar sifatida amalga oshiriladi va yadroning oldingi versiyalari bilan orqaga qarab muvofiqligi uchun ishlatiladi. Aksariyat hollarda siz haqiqiy tarqatish mexanizmi haqida hech narsa bilishingiz shart emas, lekin murakkabroq drayverlarni yaratishda qiziqarli bo'lishi mumkin.

Linuxda amalga oshirilgan resurslarni boshqarish tizimi ixtiyoriy resurslarni yagona ierarxik tarzda boshqarishi mumkin. Global tizim resurslari (masalan, I/U portlari) kichik to'plamlarga bo'linishi mumkin - masalan, apparat shinasi uyasi bilan bog'langanlar. Ayrim drayverlar, agar kerak bo'lsa, qo'lga kiritilgan resurslarni mantiqiy tuzilishiga ko'ra qismlarga bo'lishlari mumkin.

Ajratilgan resurslar diapazoni sarlavha faylida e'lon qilingan strukturaviy resurs strukturasi orqali tavsiflanadi. :

Struktura resursi (const char * nomi; imzosiz uzun boshlanish, tugatish; imzosiz uzun bayroqlar; struktur resurs * ota-ona, * aka-uka, * bola;);

Global (ildiz) manba diapazoni yuklash vaqtida yaratiladi. Masalan, kiritish-chiqarish portlarini tavsiflovchi resurs strukturasi quyidagicha yaratilgan:

Struktura resursi ioport_resource = ("PCI IO", 0x0000, IO_SPACE_LIMIT, IORESOURCE_IO);

U noldan IO_SPACE_LIMIT gacha bo'lgan manzil oralig'ini qamrab oluvchi PCI IO nomli resursni tavsiflaydi. Ushbu o'zgaruvchining qiymati ishlatiladigan platformaga bog'liq va 0xFFFF (x86, IA-64, Alpha, M68k va MIPS arxitekturalari uchun 16 bitli manzil maydoni), 0xFFFFFFFF (SPARC, PPC uchun 32 bitli bo'sh joy, SH) yoki 0xFFFFFFFFFFFFFFFF (64-bit, SPARC64).

Ushbu resursning pastki diapazonlarini allocate_resource () chaqirish orqali yaratish mumkin. Masalan, PCI shinasini ishga tushirish vaqtida ushbu avtobusning manzil mintaqasi uchun yangi resurs yaratiladi, u jismoniy qurilmaga tayinlanadi. PCI avtobus menejeri yadro kodi port va xotira topshiriqlarini qayta ishlaganda, u faqat shu hududlar uchun yangi resurs yaratadi va ularni ioport_resource () yoki iomem_resource () qo'ng'iroqlari yordamida ajratadi.

Keyin drayver resursning quyi to'plamini (odatda global resursning bir qismi) so'rashi va uni band deb belgilashi mumkin. Resurs so'ralgan resursni tavsiflovchi yangi struktura manbasiga ko'rsatgichni yoki xatolik yuz berganda NULLni qaytaradigan request_region () ga qo'ng'iroq qilish orqali olinadi. Ushbu tuzilma global resurs daraxtining bir qismidir. Yuqorida aytib o'tilganidek, resursni olgandan so'ng, haydovchiga ushbu ko'rsatgichning qiymati kerak emas.

Qiziqqan o'quvchi ushbu manbalarni boshqarish sxemasi tafsilotlarini yadro manbalari katalogida joylashgan yadro / resource.c faylida ko'rishni yoqtirishi mumkin. Biroq, allaqachon aytib o'tilgan bilimlar ko'pchilik ishlab chiquvchilar uchun etarli bo'ladi.

Resurslarni taqsimlashning qatlam mexanizmi ikki baravar foyda keltiradi. Bir tomondan, u yadro ma'lumotlar tuzilmalarining vizual tasvirini beradi. Keling, / proc / ioports faylining misolini yana ko'rib chiqaylik:

E800-e8ff: Adaptec AHA-2940U2 / Vt / 7890 e800-e8be: aic7xxx

e800-e8ff diapazoni o'zini PCI avtobus drayveri sifatida ko'rsatgan Adaptec adapteriga ajratilgan. Ushbu diapazonning aksariyati aic7xxx drayveri tomonidan so'ralgan.

Bunday resurslarni boshqarishning yana bir afzalligi - bu uskunaning haqiqiy o'zaro bog'lanishini aks ettiruvchi manzillar maydonini kichik diapazonlarga bo'lish. Resurs menejeri noto'g'ri ishlaydigan drayverni o'rnatishga to'sqinlik qilishi mumkin bo'lgan bir-biriga mos keladigan pastki diapazonlarni ajrata olmaydi.

Avtomatik va qo'lda konfiguratsiya

Drayv tomonidan talab qilinadigan ba'zi parametrlar tizimdan tizimga farq qilishi mumkin. Masalan, haydovchi joriy kirish/chiqarish manzillari va xotira diapazonlari haqida bilishi kerak. Bu yaxshi tashkil etilgan avtobus interfeyslari uchun muammo emas. Biroq, ba'zida siz drayverga o'z qurilmasini topishga yordam berish yoki uning ba'zi funktsiyalarini yoqish / o'chirish uchun parametrlarni yuborishingiz kerak.

Drayvning ishlashiga ta'sir qiluvchi ushbu parametrlar qurilmaga bog'liq. Masalan, bu o'rnatilgan qurilmaning versiya raqami bo'lishi mumkin. Albatta, bu ma'lumot haydovchining qurilma bilan to'g'ri ishlashi uchun zarurdir. Bunday parametrlarning ta'rifi (haydovchi konfiguratsiyasi) etarli
haydovchi ishga tushirilganda bajariladigan qiyin vazifa.

Odatda, ushbu parametr uchun to'g'ri qiymatlarni olishning ikki yo'li mavjud - yoki foydalanuvchi ularni aniq belgilaydi yoki haydovchi uskunani so'rov asosida mustaqil ravishda belgilaydi. Qurilmani avtomatik aniqlash, shubhasiz, drayverni sozlash uchun eng yaxshi yechim bo'lsa-da,
maxsus konfiguratsiyani amalga oshirish ancha oson. Drayv ishlab chiquvchisi iloji boricha drayverni avtomatik sozlashni amalga oshirishi kerak, lekin shu bilan birga u foydalanuvchini qo'lda sozlash mexanizmi bilan ta'minlashi kerak. Albatta, qo'lda konfiguratsiya avtokonfiguratsiyadan ustun bo'lishi kerak. Rivojlanishning dastlabki bosqichlarida, qoida tariqasida, faqat parametrlarni haydovchiga qo'lda uzatish amalga oshiriladi. Iloji bo'lsa, avtokonfiguratsiya keyinroq qo'shiladi.

Ko'pgina drayverlar, ularning konfiguratsiya parametrlari orasida, drayverning operatsiyalarini boshqaradigan parametrlarga ega. Masalan, Integrated Device Electronics (IDE) interfeysi drayverlari foydalanuvchiga DMA operatsiyalarini boshqarish imkonini beradi. Shunday qilib, agar drayveringiz apparatni avtomatik aniqlashda yaxshi ish qilsa, foydalanuvchiga drayverning funksionalligi ustidan nazoratni berishni xohlashingiz mumkin.

Parametr qiymatlari modulni yuklashda insmod yoki modprobe buyruqlari bilan o'tkazilishi mumkin. So'nggi paytlarda konfiguratsiya faylidan (odatda /etc/modules.conf) parametrlarning qiymatini o'qish mumkin bo'ldi. Butun va satr qiymatlari parametr sifatida o'tkazilishi mumkin. Shunday qilib, agar siz skull_ival parametri uchun butun son qiymatini va skull_sval parametri uchun satr qiymatini o'tkazishingiz kerak bo'lsa, modulni yuklash paytida ularni insmod buyrug'ining qo'shimcha parametrlari bilan o'tkazishingiz mumkin:

Insmod bosh suyagi skull_ival = 666 skull_sval = "hayvon"

Biroq, insmod modul parametrlarining qiymatlarini o'zgartirishdan oldin, modul ushbu parametrlarni mavjud bo'lishi kerak. Parametrlar module.h sarlavha faylida aniqlangan MODULE_PARM makros yordamida e'lon qilinadi. MODULE_PARM makrosi ikkita parametrni oladi: o'zgaruvchi nomi va uning turini belgilovchi qator. Ushbu so'l ta'rif har qanday funktsiyalardan tashqarida joylashtirilishi kerak va odatda o'zgaruvchilar ta'rifidan keyin faylning boshida joylashgan. Shunday qilib, yuqorida aytib o'tilgan ikkita parametrni quyidagicha e'lon qilish mumkin:

Int skull_ival = 0; char * skull_sval; MODULE_PARM (skull_ival, "i"); MODULE_PARM (skull_sval, "s");

Hozirgi vaqtda modul parametrlarining besh turi qo'llab-quvvatlanadi:

  • b - bir baytlik qiymat;
  • h - (qisqa) ikki baytli qiymat;
  • i - butun;
  • l - uzun butun son;
  • s - satr (char *);

String parametrlari bo'lsa, modulda ko'rsatgich (char *) e'lon qilinishi kerak. Insmod buyrug'i o'tkazilgan satr uchun xotirani ajratadi va uni kerakli qiymat bilan ishga tushiradi. MODULE_PARM makrosidan foydalanib, siz parametr massivlarini ishga tushirishingiz mumkin. Bunday holda, tip harfidan oldingi butun son massiv uzunligini aniqlaydi. Chiziq bilan ajratilgan ikkita butun sonni belgilashda ular uzatiladigan qiymatlarning minimal va maksimal sonini aniqlaydi. Ushbu makrosning ishlashini batafsilroq tushunish uchun sarlavha fayliga qarang .

Masalan, parametr massivi kamida ikkita va kamida to'rtta butun qiymat bilan ishga tushirilishi kerak deylik. Keyin uni quyidagicha ta'riflash mumkin:

Int skull_array; MODULE_PARM (skull_massivi, "2-4i");

Bundan tashqari, dasturchining asboblar to'plami MODULE_PARM_DESC makro ta'rifini o'z ichiga oladi, bu sizga uzatilgan modul parametrlariga sharhlar joylashtirish imkonini beradi. Ushbu sharhlar modul ob'ekt faylida saqlanadi va ularni, masalan, objdump yordam dasturi yoki avtomatlashtirilgan tizim boshqaruvi vositalari yordamida ko'rish mumkin. Ushbu makro ta'rifdan foydalanishga misol:

Int base_port = 0x300; MODULE_PARM (base_port, "i"); MODULE_PARM_DESC (base_port, "Asosiy I/U porti (standart 0x300)");

Modulning barcha parametrlari standart qiymatlarga ega bo'lishi maqsadga muvofiqdir. Ushbu qiymatlarni insmod bilan o'zgartirish faqat kerak bo'lganda talab qilinishi kerak. Modul joriy qiymatlarni standart qiymatlar bilan tekshirish orqali parametrlarning aniq sozlanishini tekshirishi mumkin. Keyinchalik, siz quyidagi diagramma asosida avtokonfiguratsiya mexanizmini amalga oshirishingiz mumkin. Agar parametr qiymatlari standart qiymatlarga ega bo'lsa, avtokonfiguratsiya amalga oshiriladi. Aks holda, joriy qiymatlar ishlatiladi. Ushbu sxema ishlashi uchun standart qiymatlar mumkin bo'lgan real dunyo tizim konfiguratsiyasiga mos kelmasligi kerak. Keyin bunday qiymatlarni qo'lda konfiguratsiyada foydalanuvchi o'rnatib bo'lmaydi deb taxmin qilish mumkin.

Quyidagi misol bosh suyagi drayveri qurilma portining manzil maydonini qanday avtomatik aniqlashini ko'rsatadi. Yuqoridagi misolda avtomatik aniqlash bir nechta qurilmalarni ko'rib chiqishdan foydalanadi, qo'lda sozlash esa drayverni bitta qurilma bilan cheklaydi. Oldinroq kiritish/chiqarish portlarini tavsiflovchi bo'limda skull_detect funksiyasini ko'rgansiz. skull_init_board () funktsiyasining amalga oshirilishi ko'rsatilmagan, chunki u
apparatga bog'liq ishga tushirishni amalga oshiradi.

/ * * port diapazonlari: qurilma 0x10 qadamda * 0x280 va 0x300 oralig'ida joylashishi mumkin. U 0x10 portlardan foydalanadi. * / #define SKULL_PORT_FLOOR 0x280 #define SKULL_PORT_CEIL 0x300 #define SKULL_PORT_RANGE 0x010 / * * insmod tomonidan "skull_port_base" insmod tomonidan "skull_port_base" insmod tomonidan ma'lum bir * qiymat tayinlanmagan bo'lsa, quyidagi funksiya avtomatik aniqlashni amalga oshiradi =_0; / * 0 kuchlarni avtomatik aniqlash * / MODULE_PARM (skull_port_base, "i"); MODULE_PARM_DESC (skull_port_base, "Base I/O port for Boshsuyagi"); static int skull_find_hw (void) / * qurilmalarning # sonini qaytaradi * / (/ * tayanch yuklanish vaqti qiymati yoki birinchi sinovdir * / int base = skull_port_base? skull_port_base: SKULL_PORT_FLOOR; int result = 0; / * loop one qiymat tayinlangan bo'lsa vaqt; avtomatik aniqlashda hammasini sinab ko'ring * / bajaring (agar (skull_detect (tayanch, SKULL_PORT_RANGE) == 0) (skull_init_board (baza); natija ++;) base + = SKULL_PORT_RANGE; / * keyingi sinovga tayyorlanish * / ) esa (skull_port_base == 0 && tayanch< SKULL_PORT_CEIL); return result; }

Agar konfiguratsiya o'zgaruvchilari faqat drayverning ichida ishlatilsa (ya'ni, ular yadro belgilari jadvalida e'lon qilinmagan bo'lsa), u holda dasturchi o'zgaruvchilar nomlarida prefikslardan foydalanmaslik orqali foydalanuvchi hayotini biroz soddalashtirishi mumkin (bizning holatda, skull_ prefiksi). . Foydalanuvchi uchun bu prefikslar kam ma'noga ega va ularning yo'qligi klaviaturadan buyruqlarni kiritishni osonlashtiradi.

To'liqlik uchun biz ob'ekt faylida ba'zi sharhlarni joylashtirish imkonini beruvchi yana uchta makrosning tavsifini beramiz.

MODULE_AUTHOR (ism) Obyekt faylida muallif nomi bilan qatorni joylashtiradi. MODULE_DESCRIPTION (pastlash) Ob'ekt faylida modul uchun umumiy tavsif qatorini joylashtiradi. MODULE_SUPPORTED_DEVICE (ishlab chiquvchi) Modul tomonidan qo'llab-quvvatlanadigan qurilmani tavsiflovchi qatorni joylashtiradi. V
Linux: To'liq qo'llanma Kolisnichenko Denis Nikolaevich

28.2. Modulni kompilyatsiya qilish

28.2. Modulni kompilyatsiya qilish

modul.c faylini kompilyatsiya qilamiz. Buning uchun o'rnatilgan gcc kompilyatori, sarlavha fayllari va yadro manbalari kerak bo'ladi. Agar siz ushbu bobdan oldin kitobni o'qigan bo'lsangiz, unda sizda allaqachon paketlar o'rnatilgan bo'lishi kerak:

1. cpp - cpp preprocessor;

2. binutils - turli xil yordamchi dasturlar to'plami (as, gprof, ld);

3.glibc-kerheaders - yadro sarlavhalari;

4. glibc-devel - standart C kutubxonasidan foydalangan holda ilovalarni ishlab chiqish uchun yordamchi fayllar;

5.gcc gcc kompilyatoridir.

Yadro manba paketini o'rnatish qoladi - Linux yadrosi manbalari. Bundan tashqari, yadro dinamik yuklanadigan modullarni qo'llab-quvvatlashiga ishonch hosil qilishingiz kerak (20.3.2.3-bo'lim). Agar variant Yuklanadigan modulni yoqish o‘chirilgan, siz uni yoqishingiz, yadro konfiguratsiya faylini saqlashingiz va yadroni qayta kompilyatsiya qilishingiz kerak.

Gcc kompilyatorini ko'p variantlar bilan chaqirish kerak, shuning uchun ishimizni osonlashtirish uchun biz makefile yozamiz (21.2-bo'lim):

Ro'yxat 28.5. Modulni yaratish uchun Makefile

PATH = / usr / o'z ichiga /usr/src/linux-2.4/include

MODFLAGS: = -O3 -Wall -DLINUX -D__KERNEL__ -I $ (PATH)

modul.o: modul.c

$ (CC) $ (MODFLAGS) -c modul.c

Kompilyator variantlari quyidagilarni anglatadi:

O3: optimallashtirishning uchinchi darajasi qo'llaniladi (bu nima ekanligini siz yordam tizimida bilib olasiz gcc: man gcc);

Devor: barcha ogohlantirishlarni yoqing;

DLINUX: Linux uchun kod yaratish;

I $ (PATH): sarlavha fayllari uchun qidiruv yo'lini aniqlang. Odatiy bo'lib, kompilyator / usr / include katalogida sarlavhali fayllarni qidiradi, lekin u erda bo'lmasligi mumkin. Masalan, ALT Linux tarqatish (yadro 2.4.21) uchun sarlavha fayllari /usr/include/linux-2.4.21rel-std-up katalogida joylashgan.

Makefaylni modul.c bilan bir xil katalogga joylashtiring va make faylini ishga tushiring. Uni to'ldirgandan so'ng siz modul.o faylini olasiz, u xuddi shu katalogda joylashgan.

# insmod moduli.o

Siz xabarni ko'rasiz Mening modulim: Boshlanmoqda ... Xuddi shu xabar jurnal fayliga / var / log / xabarlarga yoziladi.

C ++ kitobidan Hill Myurrey tomonidan

1.1.2 Kompilyatsiya Cout chiqish oqimi va "" chiqish operatsiyasi uchun kod qaerdan kelgan? Bajariladigan kodni olish uchun C++ da yozilgan dastur kompilyatsiya qilinishi kerak. Asosiysi, kompilyatsiya jarayoni C bilan bir xil va kirishning ko'p qismi

Fedora 8 foydalanuvchi qo'llanmasidan muallif

3.4.3. Kompilyatsiya Qoida tariqasida, dasturlarning manba kodlari "ikki marta kengaytma" -.tar.gz bilan arxiv ko'rinishida tarqatiladi. Manba kodini / usr / src katalogiga ochish odatiy holdir. Shuning uchun, arxivni ochish uchun siz quyidagi buyruqlarni bajarishingiz kerak: sucd / usr / srcgunzip archive.tar.gztar xvf

Foydalanuvchi uchun Linux kitobidan muallif Kostromin Viktor Alekseevich

200 ta eng yaxshi Linux dasturiy taʼminotidan muallif Yaremchuk Sergey Akimovich

17.5.6. Modullarni kompilyatsiya qilish Agar siz ba'zi drayverlarni alohida modullar sifatida sozlagan bo'lsangiz (ba'zi savollarga javob berishda "m" variantini tanlagansiz), u holda endi make modules buyrug'ini va keyin make modules_install buyrug'ini ham ishga tushirishingiz kerak. Documentation / modules.txt faylida siz mumkin

C # 2005 dasturlash tili va .NET 2.0 platformasi kitobidan. muallif Troelsen Endryu

Dasturlarni kompilyatsiya qilish Hatto allaqachon kompilyatsiya qilingan dasturlar bo'lgan paketlar paydo bo'lgandan keyin ham kompilyatsiya uzoq vaqt saqlanib qoldi va ba'zilar uchun u o'rnatishning asosiy vositasi bo'lib qolmoqda. Eslatma Birinchi oldindan tuzilgan to'plamlar paydo bo'ldi

Asterisk ™ kitobidan: Telefoniya kelajagi, Ikkinchi nashr muallif Meggelen Jim Van

Shartli kompilyatsiya Preprotsessor direktivalarining boshqa paketi (#if, #elif, #else, #endif) oldindan belgilangan belgilar asosida kodlar blokini shartli ravishda kompilyatsiya qilish imkonini beradi. Ushbu direktivalar uchun klassik foydalanish holati blokni identifikatsiya qilishdir

Linux tarmog'i kitobidan muallif Smit Roderik V.

Shaxsiy kompyuter uchun C dasturlash tili kitobidan muallif Bochkov S.O.

libprini kompilyatsiya qilish Libri kutubxonalari qurish muhitini yoki qurish komponenti selektorini sozlash uchun autoconf dan foydalanmaydi, chunki ular kerak emas; shunday qilib, o'rnatish soddalashtirilgan. libpri turli apparat ishlab chiqaruvchilari tomonidan qo'llaniladi

Linux kitobidan: To'liq qo'llanma muallif Kolisnichenko Denis Nikolaevich

Yulduzchani kompilyatsiya qilish Zaptel va libpri paketlarini kompilyatsiya qilish va o'rnatishdan so'ng (agar kerak bo'lsa) Asteriskni o'rnatishga o'tishingiz mumkin. Ushbu bo'lim standart o'rnatishni o'z ichiga oladi va ba'zi muqobil argumentlarni taqdim etadi

Misol bo'yicha Linux dasturlash kitobidan muallif Robbins Arnold

Yadroni kompilyatsiya qilish Ushbu bobning boshida make xconfig yoki boshqa buyruqni ishga tushirish orqali tizimingiz yadrosini sozlaganingizdan so'ng, yadroni kompilyatsiya qilishingiz va uning modullarini o'rnatishingiz kerak. Buning uchun quyidagi buyruqlarni bajaring: # make dep # make bzImage # make modules # make

C tili - yangi boshlanuvchilar uchun qo'llanma kitobidan Prata Stiven tomonidan

Shartli kompilyatsiya Ushbu bo'lim shartli kompilyatsiyani boshqaruvchi direktivalarni tavsiflaydi. Ushbu direktivalar shartlarni (doimiy

Linux kitobidan xaker ko'zlari bilan muallif Flenov Mixail Evgenievich

20.5. Yadroni kompilyatsiya qilish 20.5.1. Nega yadroni yangilash kerak? Linux boshqa operatsion tizimlarga qaraganda tezroq rivojlanmoqda. Yangi funktsiyalarni amalga oshiradigan yadroning yangi versiyalari muntazam ravishda paydo bo'ladi. Masalan, 2.6.11 yadrosidagi Fedora Core 4 tarqatilishi zo'rg'a chiqishga ulgurdi va www.kernel.org allaqachon barqarorlikka ega.

UNIX Operating System kitobidan muallif Robachevskiy Andrey M.

15.2. Nosozliklarni tuzatish uchun kompilyatsiya Manba tuzatuvchidan foydalanish uchun tuzatilayotgan bajariladigan fayl -g kompilyator opsiyasi bilan kompilyatsiya qilinishi kerak. Ushbu parametr kompilyatorni ob'ekt kodiga qo'shimcha disk raskadrovka identifikatorlarini kiritishga majbur qiladi; ya'ni

Muallifning kitobidan

Nima uchun kompilyatsiya qilish kerak? BASIC o'quvchilari dasturni bajarish uchun nima uchun juda ko'p qadamlar borligiga hayron bo'lishi mumkin. Ko'rinishidan, ushbu kompilyatsiya usuli ko'proq vaqt talab etadi (va ba'zi hollarda bu haqiqatda bo'lishi mumkin). Ammo yildan beri

Muallifning kitobidan

3.8.3. Yadroni kompilyatsiya qilish RPM paketidan o'rnatishda biz modulli yadroga ega bo'lamiz, unda qurilma drayverlarini yadro bilan bir qismga yig'ish yoki alohida yuklash mumkin. Bunday yadro sekinroq ishlaydi, lekin drayverlarni oddiy almashtirish bilan yangilash imkonini beradi

Muallifning kitobidan

Kompilyatsiya Ko'pgina ilovalarni yaratish tartibi umumiy bo'lib, rasmda ko'rsatilgan. 2.2. Guruch. 2.2. Dasturni kompilyatsiya qilish sxemasi Birinchi bosqich kompilyatsiya bosqichi bo'lib, dasturning manba fayllari, shu jumladan sarlavha fayllari kompilyator tomonidan qayta ishlanadi.