ابزارهای لازم برای کانفیگ و کامپایل کرنل
برای کانفیگ و کامپایل کرنل به تعدادی ابزار نیاز داریم که بعضیاش توضیحات مختصری دارن ولی برخی ازونا رو صلاح میدونم بیشتر توضیح بدم. برای همین سعی میکنم هرکدوم رو جدا نام ببرم.
۱- ابزاری برای دانلود سورس کد کرنل. ابزارهای زیادی وجود دارند. من دوتا ازونها رو نام میبرم: wget و curl
۲-ابزاری برای تایید صحت فایل سورسی که دانلود کردیم: gnupg
۳- ابزاری برای اکسترکت کردن سورس کرنل: tar
موارد بالا ابزارهای اولیه برای کارهای مقدماتی بودند(دانلود و تایید
صحت و اکسترکت). هنوز در مورد چگونگی کار باهاشون چیزی نگفتیم. صرفا فعلا
فقط اینها رو نصب کنید.
ابزارهای بعدی ابزارهای لازم برای کانفیگ و کامپایل هستند:
۱- کامپایلر:
قسمت اعظم کرنل لینوکس با C و مقدار کمی با اسمبلی نوشته شده. برای کامپایل
کرنل به یک کامپایلر C هم نیاز داریم.کامپایل کدهای C کرنل برعهده gcc و
پردازش کدهای اسمبلی با اسمبلر انجام میشه.
نام بسته: gcc
پیدا کردن نسخه نصب شده:
1 |
$ gcc --version |
۲- لینکر
اینجا لازمه اول توضیح مختصری در مورد لینکر بدم. لینکر چیه و کارش چیه؟
خب شما سورس کرنل یا سورس ساده برنامه های خودتون رو که با C نوشتید نگاه
کنید تعدادی هدر میبینید. مثلا به این شکل: stdio.h یا linux.h
خب اینها یک سری کدها و دستورالعملها هستند که از پیش نوشته شدهاند تا دیگه لازم نباشه همه بخوان چرخ رو از نو اختراع کنن و دوباره این مسیر رو برن. اینارو آوردن در قالب مجموعه ای از کتابخانه ها قرار دادند. در واقع وقتی شما میزنید include فلان چیز، یعنی به کامپایلر میگی من اون کتابخانه رو نیاز دارم پس لطفا اون رو برام لحاظ کن. اما کی لحاظش میکنه؟ لینکر. این لینکره که میره اون کتابخانه رو include میکنه. این include کردن مثل کپی پیست کردنه. در واقع اگر شما برید محتویات فایل stdio.h رو بیارید در ابتدای برنامه C که نوشتید قرار بدید دیگه نیاز به include کردن ندارید. ولی اتلاف وقته وقتی که چنین قابلیتی در C هست چرا باید این کار رو بکنید؟
وظیفه دیگه لینکر پیوند دادن فایلها برای ساخت فایل نهاییه. پیوند دادن تمام کتابخانهها و فایلهای آبجکت که با پسوند o. میبینید
پس برای لینک کردن هدرها و پیوند دادن آبجکتها و کتابخانهها، ما به یک
لینکر نیاز داریم. در حقیقت کار لینکر ترکیب کردن اجزای مختلف برنامه
بمنظور ساخت خروجی نهائیه.
بسته binutils شامل gnu ld هم میشه و با نصب کردن binutils شما gnu ld رو هم خواهید داشت.همچنین اسمبلر نیز در این بسته وجود داره.
binutils
1 |
$ ld -v |
۳- make
اینجا رو باید با وسواس بیشتری بگم. به دوستانی که نمیدونن کار make چیه، توصیه میکنم این رو با دقت بیشتری بخونن.
وقتی ما سورس کرنل رو دانلود میکنم برای سیستم خودمون، این سورس همون
سورسیه که گوگل برای Android و IBM برای ابرکامپیوترهاش میگیره. ما هم همون
رو برای سیستم خودمون گرفتیم. اما ازینجا ببعد راهها جدا میشن.در هنگام
کانفیگ کرنل ما چند گزینه پیش رو داریم:
در کرنل نهایی قرار بگیرد = y
در کرنل نهایی قرار نگیرد = n
در کرنل نهایی بصورت ماجول قرار بگیره =m
خب در هر حالتی که شما انتخاب کنید، سورسش از قبل وجود داره. اگر قرار باشه
همه چیز کامپایل بشه دیگه انتخاب کردن و کانفیگ معنا نداره. اینجاست که
کارکرد make مشخص میشه. در حقیقت make در سرتاسر سورس میگرده ببینه که کدوم
باید کامپایل شه و کدم نباید کامپایل بشه. اما خود make از کجا میفهمه؟
هوشمند که نیست. درسته. بعد از کانفیگ کرنل یک فایل بنام makefile در
دایرکتوری ریشه سورس کرنل generate میشه و make از روی داده های این فایل
تصمیم میگیره با هر کد چه کاری بکنه. پس make سورسی رو که باید کامپایل بشه
رو در اختیار gcc یا دیگر ابزارهای ساخت قرار میده که کامپایلش کنه. برای
ساخت کرنل لینوکس از gnu make استفاده میشه.
make
1 |
$ make -v |
۴- automake
این در رابطه مستقیمه با make. در حقیقت فایل makefile رو این generate میکنه.
automake
1 |
$ automake --version |
۵- autoconf
ابزاری برای کانفیگ خودکار سورس کدهای کرنل. اما به چه معنا. در حقیقت وقتی شما در هنگام کانفیگ کرنل نوع ماشین خودتون و معماری سیستمون و دیگر خصوصیات ویژه ماشینتون رو تعریف کردید، autoconf میاد این سورس رو برای ماشین و معماری و تنظیمات شما بهینه میکنه. که کرنل نهایی در تطابق کامل با سخت افزار شما باشه. ابزار autoconf برای پردازش ماکروها از gnu m4 استفاده میکنه.
autoconf
1 |
$ autoconf --version |
۶- M4
این ابزار یک ابزار پردازش ماکرو است. پردازش ماکروهای موجود در سورس کرنل توسط این ابزار انجام میشه
m4
1 |
$ m4 --version |
۷- bison
برگرفته از ویکیپیدا:
بایسون گنو (به انگلیسی: GNU bison) بخشی از پروژه گنو است که مسئولیت
تجزیه زبانهای مستقل از متن را بر عهده دارد. بایسون مشخصههای یک زبان
مستقل از متن را خوانده، هر جا که با ابهام در تجزیه روبرو شود، هشداری را
صادر کرده، سپس یک تجزیهگر واژگانی را تولید میکند (برای زبانهای سی،
سی++ یا جاوا) که این تجزیهگر، خود میتواند دنبالهای از توکنها را
بخواند و تصمیم بگیرد که آیا این دنباله، با ساختار دستوری که توسط گرامر
اولیه مشخص شده، همخوانی دارد یا نه. بایسون به صورت پیشفرض تجزیهگرهای
نوع LALR تولید میکند، اما قادر به تولید کردن تجزیهگرهای GLR هم است.
bison
1 |
$ bison --version |
۸- fakeroot
همچنان که از اسمش پیداست، وظیفهش ایجاد یک محیط روت مجازیه که اگر برنامه به روت واقعی نیاز داشت، دایرکتوری والد رو براش روت / تعبیر کنه.
fakeroot
1 |
$ fakeroot -v |
۹- flex
ابزار flex یک تحلیلگر واژگانی است. flex مخفف Fast Lexical Analyzer است و یک برنامه آزاد غیر گنویی است که از lex در سیستم عامل Unix اقتباس شده است.
اما وظیفه flex چیست و تحلیلگر واژگانی به چه معناست؟
به این مثال دقت کنید. فرض کنید قسمتی از یک برنامه C باشد:
1 |
x = a + b * 2; |
ابزار flex میاد این رو اینگونه برای کامپایلر اینگونه تحلیل و تفسیر میکنه:
1 |
[(identifier, x), (operator, =), (identifier, a), (operator, +), (identifier, b), (operator, *), (literal, 2), (separator, ;)] |
قطعا این یک مثاله که برای ادمیزاد قابل فهم باشه. اما flex میاد به همین قشنگی برای کامپایلر توضیح میده.
flex
1 |
$ flex --version |
۱۰- file
ابزاری برای بررسی نوع فایل. این از این جهت مهمه که در کنار سایر ابزارهای تجزیه و تحلیل، اطلاعات سورسها رو به درستی به خورد کامپایلر میده، مثلا اگر یه سورس شامل FIFO و سوکت باشه میتونه به کامپایلر اطلاع بده. در گنو/لینوکس همه چی مثل لگو کنار همن. هرچیزی یک وظیفه کوچیک داره اما به دقت انجامش میده ونتیجه شو میده به دیگری.
file
1 |
$ file -v |
۱۱- findutils
ابزاری برای یافتن محل فایلها.
findutils
1 |
$ find --version |
۱۲- gawk
نسخه گنویی awk. ابزار gawk یک زبان برنامه نویسی که برای پردازش متن تخصصی شده است.
gawk
1 |
$ gawk --version |
۱۳- grep
ابزاری برای جستجوی رشته ها. ممکن هست بگید این ابزارها به چه دردی میخورن و چرا کرنل باید اینها رو بخواد برای کامپایل. اما حقیقت اینه که برای کامپایل کرنل مجموعهای از ابزارها برای تجزیه و تحلیل و یافتن قسمت خاصی از یک کد در جایی لازمه.
grep
1 |
$ grep --version |
۱۴- libtool
برگرفته از ویکیپدیا:
گنو لیبتول (به انگلیسی: Libtool) ابزاری برای برنامهنویسی رایانه است و
جزئی از سیستم ساخت و کامپایل گنو به حساب میآید. این ابزار برای ساختن
کتابخانههای کامپایل شده قابل حمل استفاده میشود.
سیستمعاملهای مختلف، کتابخانههای اشتراکی را به روشهای متفاوتی مدیریت
میکنند. برخی از سکوها هم اصلاً از کتابخانههای اشتراکی استفاده
نمیکنند. این مسئله توسعه دادن یک برنامه به صورت قابل حمل را مشکل
میکند. کامپایلر زبان سی از یک سیستم به سیستم دیگر متفاوت است. برخی از
توابع کتابخانهای در برخی از سیستمها وجود ندارند، فایلهای سرایند در
برخی از سیستمها دارای اسامی مختلفی هستند و غیره. یک راه برای مدیریت
کردن این مشکل استفاده از کد شرطی است که با استفاده از دستور پیشپردازنده
#ifdef انجام میشود. اما به خاطر اینکه محیطهای کامپایل و ساخت برنامه
بسیار متفاوت هستند، چنین رویکردی بزودی غیرقابل مدیریت میشود. گنو
لیبتول برنامهای است که با هدف حل این مشکل به روشی بهتر و قابل
مدیریتتر ایجاد شده است.
برنامه لیبتول، به مدیریت کردن ایجاد کتابخانههای پویا و ایستا در سیستمعاملهای شبه یونیکس کمک میکند. لیبتول این کار را با انتزاعی کردن فرایند ایجاد کتابخانه انجام میدهد و تفاوتهای موجود بین سیستمهای مختلف را مخفی میکند. (برای مثال لینوکس و سولاریس).
گنو لیبتول برای ساده کردن فرایند کامپایل یک برنامه بر روی یک سیستم جدید طراحی شده است، این کار با کپسوله کردن وابستگیهای مخصوص آن سکو و همچنین رابط کاربر در یک اسکریپت configure انجام میشود. لیبتول عموماً با ابزارهای اتومیک و اتوکانف استفاده میشود، اما طوری طراحی شده که به هیچکدام از آنها وابسته نباشد.
libtool
1 |
$ libtoolize --version |
۱۵- patch
ابزاری برای پچ کردن و در بحث ما پچ کردن کرنل
اصولا پچ کردن چی هست؟ پچ کردن یعنی پینه زدن. این خیلی کمک میکنه به فهمیدن ساز و کار پچ.
فرض کنید شما یه پیراهن دارید که یک گوشهش پاره شده یا سوراخه. شما دقیقا همونجا رو پینه میکنید و میدوزید. در کرنل هم بهمین صورته.
فرض کنید یه متغیری در کرنل بولینه. و مقدار فعلیش true یا ۱ باشه. چند وقت
بعد مشخص بشه این یک باگه و باید رفع بشه. آیا منطقیه که برای تبدیل این ۱
به ۰ بیان یک شاخه دیگه تو گیت باز کنن و شماره بزرگ دیگری به کرنل بدن؟
قطعا نه. در عوض میان و پچ ارائه میدن. اما چجوری؟
پچ کرنل تفاوت نسخه قبلی و نسخه جدیدیه که اون باگ درش رفع شده و با diff
بدست میاد. ابزار diff میاد تفاوتها رو جدا میکنه و میگه این قسمت از کرنل
اصلاح شده، با همین قسمت از کرنل قبلی در این شاخه تقاوت داره. و با ابزار
پچ اون باگ پینه میشه. اما پچ از کجا میفهمه که این قسمت فقط باید پچ شه و
نه جاهای دیگه؟ از روی metadata یا فرادادهای که همراهشه. اون فراداده نقش
دست رو داره. سوزن رو دقیق میزاره رو نقطهای که سوراخه تا سوزن اونجا رو
پینه کنه.
الان نمیخوایم در جزئیات پچ غرق بشیم. فقط خواستم یه کلیت دستتون بیاد.
patch
1 |
$ patch -v |
۱۶- pkgconf
ابزاری که در همراهی با autoconf و automake کار میکنه و همین ابزاره که به شما اجازه میده برای کامپایلر gcc و لینکر فلگ بزارید. باهاش دوست باشید چون خیلی خیلی خوبه.
pkgconf
1 |
$ pkgconf --version |
۱۷- util-linux
این بسته توسط خود توسعه دهدندگان کرنل توسعه داده میشه و شامل بسیاری
از بسته های کوچک و بنیادی سیستمه که برای کامپایل کرنل لازمند.
بسته util-linux شامل این ابزارهاست:
addpart agetty blkdiscard blkid blkzone blockdev cal cfdisk chcpu chfn chmem choom chrt chsh col (legacy) colcrt colrm column ctrlaltdel delpart dmesg eject fallocate fdformat fdisk findfs findmnt flock fsck fsck.cramfs fsck.minix fsfreeze fstrim getopt hexdump hwclock (query and set the hardware clock (RTC)) ionice ipcmk ipcrm ipcs isosize kill last ldattach line (legacy) logger login look losetup lsblk lscpu lsipc lslocks lslogins lsmem mcookie mesg mkfs (legacy) mkfs.bfs mkfs.cramfs mkfs.minix mkswap more mount mountpoint namei newgrp nologin nsenter partx pg (legacy) pivot_root prlimit raw readprofile rename renice reset (legacy) resizepart rev rfkill rtcwake runuser script scriptreplay setarch (including architecture symlinks such as i386, linux32, linux64, x86_64, etc.) setpriv setsid setterm sfdisk su sulogin swaplabel swapoff swapon switch_root tailf (legacy) taskset tunelp (deprecated) ul umount unshare utmpdump uuidd uuidgen uuidparse vipw (including symlink to vigr) wall wdctl whereis wipefs write zramctl
util-linux
1 2 3 |
$ fdformat --version $ rpm –qa | grep util-linux $ dpkg -l |grep util-linux |
۱۸- module-init-tools
یه ابزار خاص با کارکردی عالی.
لابد بارها براتون پیش اومده که ماجولی رو بخواهید لود کنید. ماجول چیه؟ ماجول یه کده که بصورت عادی بارگزاری نمیشه تو حافظه بلکه باید در شرایط خاصی بارگزاری بشه تو آدرس اسپیس کرنل. این ماجولها خیلی مفیدن. باعث میشه که ما یه کرنل بزرگ و سنگین نداشته باشیم، و فقط زمانی که به چیزی نیاز داریم اون چیز لود بشه تو کرنل. فایده دیگر ماجولها اینه که وقتی کرنل زنده زنده در حین کار هم باشه، ماجول میتونه بهش افزوده بشه و نیازی به راه اندازی مجدد نباشه.
چنانچه میخواهید درایوری رو بصورت ماجول کامپایل کنید، شما به این ابزار نیاز دارید. اما واقعا نیاز ندارید. چون ابزار جدید تری با امکانات بیشتری به نام kmod اومده و اون کار module-init-tools رو به نحو بهتری براتون انجام میده. چیزی که در مورد kmod وجود داره اینه که درخت وابستگی رو میفهمه. میفهمه که اگر این درایور بعنوان ماجول لود بشه، چه ماجولهای دیگری باید لود بشن تا این ماجول کار کنه. در حقیقت ابزارهای modprobe و lsmod یه لینک هستند به kmod.
1 |
$ ls -l /sbin/depmod |
lrwxrwxrwx 1 root root 9 Oct 24 02:50 /sbin/depmod -> /bin/kmod
اسم kmod مخفف kernel module است.
kmod
1 |
$ depmod -V |
۱۹- init system
در کرنلی که ما کامپایل میکنیم تنها init استانداردی که وجود داره systemd است. در کرنلهای هک شده برای سیستمهای خاص یا توزیعهایی مثل جنتو، میتونید openrc رو هم داشته باشید. اما چیزیه که در کرنلی که ما استاندارد از گیت دانلود میکنیم وجود نداره.
systemd
1 |
$ systemd --version |
۲۰- OpenSSL
در سورس کرنل از کدهای ssl برای ارتباطات امن سوکت TCP استفاده شده است. پیش از کامپایل کرنل باید این ابزار و کتابخانه libssl-dev را نصب داشته باشید.
openssl
libssl-dev
1 |
$ openssl version |
۲۱- bc
برگرفته از ویکیپدیا:
بیسی، برگرفته از حروف اول عبارت انگلیسی basic calculator (ماشینحساب
پایه) یک زبانِ ماشین حسابی با دقت دلخواه است و نحوی شبیه به زبان
برنامهنویسی سی دارد. بیسی معمولاً به عنوان زبان پردازهنویسی ریاضیاتی
یا یک پوسته ریاضیاتی تعاملی به کار گرفته میشود
bc
1 |
$ bc --version |
۲۲- ncurses
برگرفته از ویکیپدیا:
انکرسز (به انگلیسی: Ncurses) که نامش مختصر شدهٔ New Curses است، یک
کتابخانه برنامهنویسی است که رابطهای برنامهنویسی نرمافزاری را فراهم
میکند که یک برنامهنویس به کمک آنها میتواند رابط کاربری مبتنی بر متن
ایجاد کند. این رابطهای کاربری مستقل از ترمینال هستند. به عبارت دیگر،
رابطهای کاربری که توسط این کتابخانه طراحی میشوند، به صورت شبه-گرافیکی
هستند و تحت یک شبیهسازی ترمینال به اجرا درمیآیند. این کتابخانه، یکی از
معدود پروژههای نرمافزاری گنو است که تحت پروانهای به غیر از جیپیال
یا الجیپیال منتشر میشود.
ncurses
1 |
$ dpkg -l |grep ncurses |
۲۳- libelf
لایبرریهایی برای ساخت فایلهای مستقل از نوع معماری که برای خواندن و نوشتن فایلهای ELF ضروری هستند.
اما ELF چیه؟
Executable and Linkable Format
شاید شما با فرمتهای فایلهای باینری مثل exe و bin آشنا باشید.
فایلهای باینری فایلهای صلب و تغییر ناپذیری هستند. یعنی پس ازینکه ساخته
شدند، امکان نداره بتونید در اون تغییری ایجاد کنید، مگر با کامپایل مجدد و
ساخت مجدد اون فایل.
اما در فایلهای elf قضیه اینگونه نیست. در حقیقت ELF یک اجرایی با یک رپر
غیر باینری است که فراداده هایی در مورد اون باینری باهاشه و امکان جابجایی
و انعطاف رو به برنامه در مموری میده.
در رایانش، فرمت اجرایی و مرتبط (ELF، که قبلاً به نام Extensible Linking
Format نامیده میشد) یک استاندارد فرمت فایل برای فایلهای اجرایی، کد هدف
(object code)، کتابخانههای اشتراکی و تخلیهٔ هسته (core dump) است.
برنامه قابل اجرایی که باینری نیست. یعنی در خلال هربار اجرا میتونه
آفستهاش نسبت به محلی از حافظه که الان در اون قرار گرفته تغییر کنه و نسبت
به محل جدید آفست رو تنظیم کنه. اما در کجا میتونید این آفستها و کار elf
رو ببینید؟
این جزو کارمون نیست اما صرفا برای فهمیدنه.
اول از همه اینکه بعنوان مثال ببینیم ابزار ls از چه لایبرری هایی استفاده میکنه:
1 |
$ ldd /bin/ls |
در خروجی کتابخانه های مورد استفاده ls رو میبینید. حالا یکی ازونا رو انتخاب میکنید. مثلا libdl.so.2
حالا:
1 |
$ readelf -d /lib/x86_64-linux-gnu/libdl.so.2 |
در خروجی آفست کامل libdl.so.2 رو میبینید.
libelf
1 |
$ ldconfig | grep libel |