فصل دوم : گام های آغازین
۲ گام های آغازین
توسعه سیستم عامل کاری آسان نیست، و این پرسش که "چگونه
می توانم شروع به حل این مسئله کنم؟" نیز به تجربه مشکلات مختلف در طول
کار برروی چند پروژه متفاوفت خواهد انجامید. مطالعه این فصل به شما در راه
اندازی محیط توسعه و بوت کردن یک سیستم عامل بسیار کوچک (و غیر انحصاری)
کمک خواهد کرد.
۲-۱ ابزارها
۲-۱-۱ راه اندازی سریع
ما (مولفان) از سیستم عامل Ubuntu نسخه 6 برای کار
برروی توسعه سیستم عامل استفاده کردیم، و آن را به صورت فیزیکی و مجازی (با
استفاده از ماشین مجازی Virtual Box) اجرا کردیم. یک راه سریع برای آماده
سازی همه ی موارد و اجرا این است که از همان ابزاری که ما برای راه اندازی
استفاده می کنیم استفاده کنید، به این خاطر که ما می دانیم این ابزارها با
مثال های آورده شده در این کتاب کارخواهند کرد.
به محض اینکه Ubuntu نصب شد، چه نصب فیزیکی و یا مجازی، بسته های زیر باید با استفاده از apt-get نصب شوند :
sudo apt-get install build-essential nasm genisoimage bochs bochs-sdl
۲-۲-۱ زبان های برنامه نویسی
سیستم عامل ما با استفاده زبان C و بهره گیری از
کامپایلر GCC نوشته خواهد شد. به این خاطر از C استفاده می کنیم که توسعه
سیستم عامل به کنترل بسیار دقیقی برروی کد تولید شده و دسترسی به حافظه
نیاز دارد. سایر زبان های که بتوانند این ویژگی ها را ارائه دهند نیز می
توانند مورد استفاده قرار گیرند، امّا این کتاب تنها C را پوشش می دهد.
این کد یکی از ویژگی های نوع داده ای است که مخصوص GCC است :
__attribute__((packed))
این ویژگی به ما اطمینان می دهد که کامپایلر از شکل
دقیقی که ما در کدمان برای تعریف یک struct بکار برده ایم تبعیت می کند.
این ویژگی را در فصل بعدی با جزئیات بیشتری توضیح خواهیم داد.
به موجب استفاده از این مشخصه، کامپایل کدهای نمونه با استفاده از کامپایلرهای دیگری بجز GCC ممکن است سخت باشد.
برای
نوشتن کدهای اسمبلی، ما Nasm را بعنوان اسمبلر انتخاب کرده ایم، به این
خاطر که ما نحو دستوری Nasm را به اسمبلر GNU) GAS) ترجیح می دهیم.
زبان اسکریپتی که ما در کل این کتاب از آن بهره می بریم Bash خواهد بود.
۲-۳-۱ سیستم عامل میزبان
تمام کدهای نمونه با فرض اینکه برروی یک سیستم عامل شبه
Unix کامپایل می¬شوند قرار داده شده اند. تمام نمونه کدها به شکلی موفقیت
آمیز برروی Ubuntu 6 یعنی نسخه 11.04 و 11.10 کامپایل شده اند.
۲-۴-۱ ساختن سیستم
برای ساختن نمونه های Makefile از نحو دستوری برنامه Make استفاده شده است.
۲-۵-۱ ماشین مجازی
در هنگام توسعه سیستم عامل بسیار مطلوب است که کدها را
بجای یک کامپیوتر فیزیکی برروی یک ماشین مجازی اجرا کنیم، به این دلیل که
اگرکار بروی سیستم عاملتان را در ماشین های مجازی آغاز کنید سرعت مشاهده
نتایج بسیار بیشتر از شکل اجرای فیزیکی آن خواهد بود و در نتیجه شما پس از
اطمینان می توانید آن را برروی ماشین فیزیکی خود اجرا کنید. مقلّد Bochs یک
مقلّد برای معماری x86 (یعنی IA-32) است که با داشتن ویژگی های خطایابی
یکی از ابزارهای خوب و مناسب جهت توسعه سیستم عامل بشمار می رود. دیگر
انتخاب مورد توجه QEMU و Virtual Box هستند. این کتاب از Bochs استفاده می
کند.
با استفاده از یک ماشین مجازی ما نمی توانیم اطمینان حاصل کنیم که
سیستم عامل مان برروی سخت افزار واقعی نیز کار می کند. محیط های شبیه سازی
شده توسط ماشین های مجازی بگونه ای طراحی شده اند که شباهت زیادی با بخش
های فیزیکی همتای خود داشته باشند، و سیستم عامل می تواند برروی یکی از آن
ها از طریق یک کپی اجرایی برروی یک CD و پیدا کردن ماشین مجازی مناسب
آزمایش شود.
۲-۲ بوت کردن
بوت کردن یک سیستم عامل رویه ایست که شامل انتقال کنترل
از طریق زنجیره ای از برنامه های کوچک است، هر یک از این برنامه ها
قدرتمند تر از قبلی است، حال آنکه سیستم عامل آخرین برنامه می باشد. مشاهده
ی شکل زیر مثالی از یک فرآیند بوت می باشد:
رسم توضیحی 1: مثالی از پروسه بوت شدن سیستم. هر جعبه یک برنامه می باشد.
۲-۲-۱ بایاس
زمانی که PC روشن شود، کامپیوتر برنامه کوچکی را که
خلاصه ی عبارت سیستم ورودی خروجی پایه (BIOS) استاندارد است اجرا می کند.
این برنامه معمولاً برروی یک تراشه فقط خواندنی برروی برد اصلی PC ذخیره
شده است. نقش اصلی برنامه BIOS این بود که برخی از توابع را برای چاپ کردن
برروی صفحه، خواندن از صفحه کلید و ... ارائه دهد. سیستم عامل های مدرن از
توابع BIOS استفاده نمی کنند، آن ها از راه اندازهایی(Driver) که بشکل
مستقیم با سخت افزار ارتباط برقرار می کنند بهره می برند و از BIOS گذر می
کنند. امروزه، BIOS اصولاً برای اجرای چند خطایابی اولیه (خود آزمون زمان
روشن شدن ) و انتقال کنترل به بوت لودر استفاده می شوند.
۲-۲-۲ بوت لودر
برنامه برنامه BIOS کنترل PC را به برنامه ای که
Bootloader نام دارد منتقل می کند. وظیفه Bootloader این است که کنترل را
به ما، یعنی توسعه دهندگان سیستم عامل، و کد ما منتقل کند. بهرروی، به سبب
برخی از محدودیت های سخت افزاری بدلیل سازگاری با سیستم های پیشین، بوت
لودر اغلب به دو قسمت تقسیم می شود: بخش اول بوت لودر که کنترل را به بخش
دوم منتقل می کند، و این بخش نهایتاً کنترل کامپیوتر را به سیستم عامل می
دهد.
نوشتن بوت لودر درگیر نوشتن بسیاری از کدهای سطح پائین است که
بتوانند با BIOS ارتباط برقرار کنند. بنابراین از یک Bootloader آماده
استفاده شده است : بوت لودر GRUB .
با استفاده از GRUB سیستم عامل می
تواند بمانند یک فایل اجرایی ELF ساخته شود، در نتیجه این فایل توسط GRUB
در جای مناسبی از محل های حافظه بارگذاری خواهد شد. کامپایل کردن هسته
مستلزم کدهای قرار گرفته به شکلی مشخص، در حافظه می باشد (چگونگی کامپایل
کردن هسته در فصل بعدی بحث خواهد شد).
۲-۲-۳ سیستم عامل
GRUB کنترل را از طیق پرش به محلی از حافظه به سیستم
عامل منتقل می کند. قبل از پرش، GRUB به دنبال یک عدد طلایی جهت حصول
اطمینان از اینکه به یک سیستم عامل واقعی پرش می کند (نه یک کد تصادفی) می
گردد. این عدد تصادفی بخشی از مشخصات multiboot است که GRUB به آن وفادار
می باشد. به محض اینکه GRUB پرش را انجام داد، سیستم عامل کنترل کامل سیستم
را در دست می گیرد.
۲-۳ سلام به قهوه سرای کودکان
این بخش نحوه پیاده سازی کوچکترین سیستم عاملی را که می
تواند با GRUB استفاده شود را شرح می دهد. تنها کاری که سیستم عامل انجام
می دهد این است که عبارت 0xCAFEBABE (همان قهوه سرای کودکان) را در ثبات
eax بنویسد (اکثر برنامه نویسان این را حتی یک سیستم عامل نمی دانند).
۲-۳-۱ کامپایل کردن سیستم عامل
این بخش سیستم عامل باید با کدهای اسمبلی نوشته شود،
زیرا C به یک پشته نیاز دارد که موجود نیست (فصل ورود به C نحوه راه اندازی
یکی از آن ها را توضیح می دهد). کدهای زیر را در فایلی به نام Loader.s
ذخیره کنید :
global loader ; the entry symbol for ELF
MAGIC_NUMBER equ 0x1BADB002 ; define the magic number constant
FLAGS equ 0x0 ; multiboot flags
CHECKSUM equ -MAGIC_NUMBER ; calculate the checksum
; (magic number + checksum + flags should equal 0)
section .text: ; start of the text (code) section
align 4 ; the code must be 4 byte aligned
dd MAGIC_NUMBER ; write the magic number to the machine code,
dd FLAGS ; the flags,
dd CHECKSUM ; and the checksum
loader: ; the loader label (defined as entry point in linker script)
mov eax, 0xCAFEBABE ; place the number 0xCAFEBABE in the register eax
.loop:
jmp .loop ; loop forever
تنها کاری که این سیستم عامل انجام می دهد این است که عدد کاملاً مشخص 0xCAFEBABE را در ثبات eax ذخیره می کند. خیلی بعید است که عدد 0xCAFEBABE پیش از آنکه سیستم عامل آن را در ثبات eax قرار دهد در آن قرار گرفته باشد.
فایل Loader.s می تواند از طریق کد زیر به یک فایل Object 32بیتی در قالب ELF کامپایل بشود :
nasm -f elf32 loader.s
۲-۳-۲ پیوند دادن هسته
حال می بایست کد به منظور تولید یک فایل اجرایی پیوند داده شود، که انجاک این کار نیازمند اطلاعات اضافی است که در مقایسه با عمل پیوند دادن اغلب برنامه ها مورد نیاز است. می خواهیم که GRUB هسته ما را در آدرسی بزرگتر یا مساوی با 0x00100000 (یعنی 1 مگابایت) بارگذاری کند، زیرا آدرس های کمتر از 1 مگابایت توسط خود GRUB و دستگاه های ورودی خروجی نگاشت شده در حافظه اشغال شده اند. در نتیجه، اسکریپت پیوند زیر نیاز است (برای پیوند دهنده LD GNU نوشته شده) :
ENTRY(loader) /* the name of the entry label */
SECTIONS {
. = 0x00100000; /* the code should be loaded at 1 MB */
.text ALIGN (0x1000) : /* align at 4 KB */
{
*(.text) /* all text sections from all files */
}
.rodata ALIGN (0x1000) : /* align at 4 KB */
{
*(.rodata*) /* all read-only data sections from all files */
}
.data ALIGN (0x1000) : /* align at 4 KB */
{
*(.data) /* all data sections from all files */
}
.bss ALIGN (0x1000) : /* align at 4 KB */
{
*(COMMON) /* all COMMON sections from all files */
*(.bss) /* all bss sections from all files */
}
}
اسکریپت پیوند دهنده را در فایلی با نام link.ld ذخیره کنید. حال فایل اجرایی می تواند با دستور زیر پیوند داده شود :
ld -T link.ld -melf_i386 loader.o -o kernel.elf
فایل اجرایی نهایی kernel.elf نامیده می شود.
۲-۳-۳ بدست آوردن GRUB
نسخه ای از GRUB که ما از آن استفاده می کنیم نسخه legacy یا میراث قدیمی GRUB است، زیرا تصویر فایل ISO سیستم عامل می تواند با استفاده از نسخه legacy یا نسخه شماره 2 نرم افزار GRUB تولید شود. به طور مشخص تری بوت لودر GRUB Legacy با نام stage2_eltorito مورد استفاده قرار می گیرد. این فایل می تواند از طریق GRUB نسخه 0.97 و بعد از دانلود کد منبع آن از آدرس زیر تولید شود :
ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz
بهرروی اسکریپت Configure آن با Ubuntu خوب کار نمی کند، پس فایل دودویی آن را می توانید از آدرس زیر دانلود کنید :
http://littleosbook.github.com/files/stage2_eltorito
این فایل را در پوشه ای که فایل های Loader.s و link.ld را قرار داده اید جای دهید.
۲-۳-۴ ساختن یک تصویر ISO
فایل اجرایی باید در رسانه ای قرار گیرد که بتواند توسط یک ماشین مجازی یا حقیقی بارگذاری شود. در این کتاب ما از فایل تصویر ISO بعنوان رسانه بهره می بریم، اما یکی از راه های دیگر استفاده از تصاویر Floppy است، بسته به آنکه ماشین مجازی یا حقیق شما کدامیک را پشتیبانی می کند.
تصویر iso هسته را با برنامه genisoimage می سازیم. یک پوشه برای آنچه که در تصویر iso وجود خواهد داشت باید ایجاد شود. دستور زیر پوشه مدنظر را ایجاد می کند و فایل ها را در محل مناسب نسخه برداری می کند :
mkdir -p iso/boot/grub # create the folder structure
cp stage2_eltorito iso/boot/grub/ # copy the bootloader
cp kernel.elf iso/boot/ # copy the kernel
یک فایل پیکربندی به نام menu.lst باید برای GRUB ایجاد شود. این فایل به GRUB می گوید که هسته در کجا قرار گرفته است و برخی از گزینه ها را پیکربندی می کند :
default=0
timeout=0
title os
kernel /boot/kernel.elf
فایل menu.lst را در پوشه iso/boot/grub قرار دهید. حال محتوای پوشه iso باید شکلی بمانند زیر داشته باشند :
iso
|-- boot
|-- grub
| |-- menu.lst
| |-- stage2_eltorito
|-- kernel.elf
تصویر iso می تواند از طریق دستورات زیر تولید شود :
genisoimage -R \
-b boot/grub/stage2_eltorito \
-no-emul-boot \
-boot-load-size 4 \
-A os \
-input-charset utf8 \
-quiet \
-boot-info-table \
-o os.iso \
iso
برای کسب اطلاعات بیشتر در ارتباط با پرچم¬های استفاده شده در دستور به راهنماهای (manual) برنامه genisoimage مراجعه کنید.
تصویر ISO با نام os.iso در حال حاضر شامل هسته اجرایی، بوت لودر GRUB و فایل پیکر بندی می باشد.
۲-۳-۵ اجرای Bochs
حال ما می توایم سیستم عامل را با استفاده از تصویر iso فایل os.iso در مقلّد Bochs اجرا کنیم. مقلّد bochs به یک فایل پیکربندی به جهت شروع نیاز دارد و نمونه ای از فایل پیکر بندی در زیر قرار گرفته شده است:
megs: 32
display_library: sdl
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=os.iso, status=inserted
boot: cdrom
log: bochslog.txt
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000
ممکن است شما نیاز داشته باشید که مسیر romimage و vgaromimage را بسته به نحوه نصب bochs تغییر دهید. برای کسب اطلاعات بیشتر درباره فایل پیکربندی bochs می توانید به تارنمای Bochs مراجعه کنید.
اگر فایل پیکربندی را با نام bochsrc.txt ذخیره کرده اید می توانید با استفاده از دستور زیر bochs را اجرا کنید:
bochs -f bochsrc.txt -q
پرچم f- به bochs می گوید که از فایل پیکربندی استفاده کند و پرچم q- به bochs می گوید که از نمایش منوی شروع تعاملی صرف نظر کند. در این زمان شما باید شروع کار bochs و نمایش کنسولی با اندکی اطلاعات از GRUB در آن را ببینید.
بعد از خاتمه ی اجرای bochs، فایل رخداد نگار تولید شده توسط bochs را نمایش دهید :
cat bochslog.txt
حال شما باید محتوای ثبات های پردازنده را که توسط Bochs شبیه سازی شده اند را در جایی از خروجی دستور بالا ببینید. اگر RAX=00000000CAFEBABE یا EAX=CAFEBABE را (بسته به آنکه آیا Bochs را با پشتیبانی 64 بیتی یا بدون آن اجرا کرده اید) در خروجی پیدا کردید پس سیستم عامل شما بدرستی بوت شده است !
۲-۴ مطالعه های بعدی
گوستاوو دورتس مقاله ای مفصل درباره آنچه که در کامپیوترهای x86 در زمان بوت شدن اتفاق می افتد نوشته است، برای مطالعه این مقاله به آدرس زیر مراجعه کنید :
http://duartes.org/gustavo/blog/post/how-computers-boot-up
گوستاوو در ادامه مقاله قبلی، مقاله ای در ارتباط با نحوه عملکرد هسته در گام های آغازین نوشته که آن را نیز می توانید در آدرس زیر مطالعه نمائید :
http://duartes.org/gustavo/blog/post/kernel-boot-process
دانشنامه OSDev نیز شامل مقاله ی خوبی در ارتباط با روند بوت شدن در کامپیوترهای x86 قرار داده است که آن را نیز از آدرس زیر می توانید تهیه کنید :
http://wiki.osdev.org/Boot_Sequence
* صفحه بندی این کتاب فصل به فصل انجام شده و در این ارسال افزوده خواهد شد.
- ۹۴/۰۹/۱۰
خیلی خوشحال شدم وقتی تلاش شما را دیدم و خیلی ناراحت از اینکه ظاهرا یک سال هست که کار را تعطیل کرده اید. به هر حال یکی دو تا از کتابهایی که معرفی کرده اید را دیدم همه از ماشین مجازی استفادده کرده اند. من در ماشین مجازی توانسته ام خروجی بگیرم اما هرکاری کردم در کامبیوتر خودم نشد. فایل بوت لودر را روی سکتور فلابی هم کبی کردم نشد. در سی دی هم رایت کردم نشد. هنگام لود شدن بیغام می دهد که فایل بوت نیست و همینطور می ماند نمی دانم چه کار کنم لطف می کنید اگر راهنمایی ام کنید. خیلی خیلی ممنون می شوم