Lab1 Fall2023
Lab1 Fall2023
مقدمه
سیستمعامل xv6یک سیستمعامل آموزشی است که در سال 2006توسط محققان دانشگاه MITبه وجود آمده
است .این سیستمعامل به زبان Cو با استفاده از هسته Unix Version 6نوشته شده و بر روی معماری Intel
x86قابل اجرا میباشد .سیستمعامل xv6علیرغم سادگی و حجم کم ،نکات اساسی و مهم در طراحی
سیستمعامل را دارا است و برای مقاصد آموزشی بسیار مفید میباشد .تا پیش از این ،در درس سیستمعامل
دانشگاه تهران از هسته سیستمعامل لینوکس استفاده میشد که پیچیدگیهای زیادی دارد .در ترم پیشرو،
دانشجویان آزمایشگاه سیستمعامل بایستی پروژههای مربوطه را برروی سیستمعامل xv6اجرا و پیادهسازی
نمایند .در این پروژه ،ضمن آشنایی به معماری و برخی نکات پیادهسازی سیستمعامل ،آن را اجرا و
اشکالزدایی خواهیم کرد و همچنین برنامهای در سطح کاربر خواهیم نوشت که برروی این سیستمعامل قابل
اجرا باشد.
اجرا و اشکالزدایی
در این بخش به اجرای سیستم عامل xv6خواهیم پرداخت .علیرغم اینکه این سیستمعامل قابل اجرای مستقیم بر
روی سخت افزار است ،به دلیل آسیبپذیری باال و رعایت مسائل ایمنی از این کار اجتناب نموده و سیستم عامل
را به کمک برابرساز Qemu 2روی سیستمعامل لینوکس اجرا میکنیم .برای این منظور الزم است که کدهای
مربوط به سیستمعامل را از لینک ارائه شده cloneو یا دانلود کنیم .در ادامه با اجرای دستور makeدر پوشه
دانلود ،سیستمعامل کامپایل میشود .در نهایت با اجرای دستور make qemuسیستمعامل بر روی برابرساز
اجرا میشود (توجه شود که فرض شده Qemuاز قبل بر روی سیستمعامل شما نصب بوده است .در غیر این
صورت ابتدا آن را نصب نمایید).
Process 1
Emulator 2
2
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
● توجه شود که عالوه بر نمایش درست بر روی کنسول ،باید دستورات نوشته شده با کلیدهای ترکیبی
فوق ،قابلیت اجرای درست را نیز داشته باشند.
3
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
رقم 0و در غیر این صورت رقم 1در جایگاه iام حاصل باینری قرار میگیرد .همچنین اگر طول یکی از
رشتهها از رشته دیگر بلندتر بود ،حروف مازاد آن رشته در مقایسههایشان به عنوان حرف بزرگتر به حساب
میآیند .بزرگتر بودن حروف نسبت به یکدیگر هم به این صورت تعریف میشود که یک حرف در حروف
الفبای انگلیسی بعد از حرف دیگر آمده باشد .به عنوان مثال حرف fاز حرف bبزرگتر است.
در نهایت ،خروجی محاسبه را در یک فایل تکست با نام strdiff_result.txtذخیره کنید .اگر فایل تکست از
قبل موجود بود ،جواب بر روی آن بازنویسی شود.
از دستورات open، read، writeو closeاستفاده کنید که برای باز کردن ،خواندن ،نوشتن و بستن فایلها
استفاده میشود .برای پیادهسازی این برنامه سطح کاربر ،عالوه بر نوشتن کد ،باید در فایل Makefileنیز
تغییرات الزم را بوجود آورید تا این برنامه مثل دستورات دیگر از قبیل lsاجرا شود.
4
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
Sector 6
Boot Sector 7
Boot Loader 8
Basic Input/Output System 9
General Purpose Register 10
Segment Register 11
Status Registers 12
Control Registers 13
5
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
وضعیت ثباتها را میتوان به کمک gdbو دستور info registersمشاهده نمود .وضعیت برخی از ثباتهای
دیگر نیاز به دسترسی ممتاز 14دارد .به این منظور میتوان از qemuاستفاده نمود .کافی است با زدن Ctrl +
Aو سپس Cبه ترمینال qemuرفته و دستور info registersرا وارد نمود .با تکرار همان دکمهها میتوان
به xv6بازگشت.
.15پردازندههای x86دارای مدهای مختلفی هستند .هنگام بوت ،این پردازندهها در مد حقیقی قرار داده
15
میشوند .مدی که سیستمعامل اماسداس )MS DOS( 16در آن اجرا میشد .چرا؟ یک نقص اصلی این
مد را بیان نمایید؟
.16آدرسدهی به حافظه در این مد شامل دو بخش قطعه و افست بوده که اولی ضمنی و دومی به طور
18 17
هر آدرس در کد برنامه یک آدرس منطقی 22است .این آدرس توسط سختافزار مدیریت حافظه در نهایت به یک
آدرس فیزیکی در حافظه نگاشت داده میشود .این نگاشت دو بخش دارد )۱ :ترجمه قطعه 23و )۲ترجمه
صفحه .24مفهوم ثباتهای قطعه در این مد تا حد زیادی با نقش آنها در مد حقیقی متفاوت است .این ثباتها با
تعامل با جدولی تحت عنوان جدول توصیفگر سراسری )GDT( 25ترجمه قطعه را انجام میدهند .به این ترتیب
ترجمه آدرس در مد محافظتشده بسیار متفاوت خواهد بود .در بسیاری از سیستمعاملها از جمله xv6و
لینوکس ترجمه قطعه یک نگاشت همانی است .یعنی GDTبه نحوی مقداردهی میگردد (خطوط ۹۱۸۲تا
)۹۱۸۵که میتوان از گزینشگر 26صرفنظر نموده و افست را به عنوان آدرس منطقی در نظر گرفت و این
افست را دقیقا ً به عنوان آدرس خطی 27نیز در نظر گرفت .به عبارت دیگر میتوان فرض نمود که آدرسها
دوبخشی نبوده و صرفا ً یک عدد هستند .یک آدرس برنامه (مثالً آدرس یک اشارهگر یا آدرس قطعهای از کد
برنامه) یک آدرس منطقی (و همینطور در اینجا یک آدرس خطی) است .به عنوان مثال در خط ۹۲۲۴آدرس
6
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
اشارهگر elfکه به 0x10000مقداردهی شده است یک آدرس منطقی است .به همین ترتیب آدرس تابع
() bootmainکه در زمان کامپایل تعیین میگردد نیز یک آدرس منطقی است .در ادامه بنابر دالیل تاریخی به
آدرسهایی که در برنامه استفاده میشوند ،آدرس مجازی 28اطالق خواهد شد .نگاشت دوم یا ترجمه صفحه در
کد بوت فعال نمیشود .لذا در اینجا نیز نگاشت همانی وجود داشته و به این ترتیب آدرس مجازی برابر آدرس
فیزیکی خواهد بود .نگاشت آدرسها (و عدم استفاده مستقیم از آدرس فیزیکی) اهداف مهمی را دنبال میکند که
در فصل مدیریت حافظه مطرح خواهد شد .از مهمترین این اهداف ،حفاظت محتوای حافظه برنامههای
کاربردی مختلف از یکدیگر است .بدین ترتیب در لحظه تغییر مد ،وضعیت حافظه (فیزیکی) سیستم به صورت
شکل زیر است.
.17کد bootmain.cهسته را با شروع از سکتور بعد از سکتور بوت خوانده و در آدرس 0x100000
قرار میدهد 29.علت انتخاب این آدرس چیست؟
حالت حافظه پس از این فرایند به صورت شکل زیر است.
به این ترتیب در انتهای بوت ،کد هسته سیستمعامل به طور کامل در حافظه قرار گرفته است .در گام انتهایی،
بوتلودر اجرا را به هسته واگذار مینماید .باید کد ورود به هسته اجرا گردد .این کد اسمبلی در فایل entry.S
قرار داشته و نماد (بیانگر مکانی از کد) entryاز آن فراخوانی میگردد .آدرس این نماد در هسته بوده و حدود
0x100000است.
.18کد معادل entry.Sدر هسته لینوکس را بیابید.
7
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
نیمه چپ شکل ،فضای آدرس مجازی را نشان میدهد .جدول آدرسهای نیمه چپ را به نیمه راست نگاشت
میدهد .در اینجا دو صفحه چهار مگابایتی به یک بخش چهار مگابایتی از حافظه فیزیکی نگاشت شدهاند .یعنی
برنامه میتواند با استفاده از دو آدرس به یک محتوا دسترسی یابد .این یکی دیگر از قابلیتهای صفحهبندی
است .در ادامه اجرا قرار است هسته تنها از بخش باالیی فضای آدرس مجازی استفاده نماید 33.به عبارت دیگر،
نگاشت پایینی حذف خواهد شد .علت اصلی این است که باید حافظه مورد دسترسی توسط هسته از دسترسی
برنامههای کاربردی یا به عبارت دقیقتر برنامههای سطح کاربر 34حفظ گردد .این یک شرط الزم برای ارائه
سرویس امن به برنامههای سطح کاربر است .هر کد در حال اجرا دارای یک سطح دسترسی جاری)CPL( 35
Paging 30
31به طور دقیقتر این جداول سلسلهمراتبی بوده و آدرس اولین الیه جدول در cr3قرار داده میشود.
Page 32
33در xv6از آدرس 0x80000000به بعد مربوط به سطح هسته و آدرسهای 0x0تا این آدرس مربوط به سطح کاربر هستند.
User Level Programs 34
Current Privilege Level 35
8
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
است .سطح دسترسی در پردازندههای xv6از صفر تا سه متغیر بوده که صفر و سه به ترتیب ممتازترین و
پایینترین سطح دسترسی هستند .در سیستمعامل xv6اگر CPL=0باشد در هسته و اگر CPL=3باشد در سطح
37
کاربر هستیم .36تشخیص سطح دسترسی کد کنونی مستلزم خواندن مقدار ثبات csاست.
دسترسی به آدرسهای هسته با CPL=3نباید امکانپذیر باشد .به منظور حفاظت از حافظه هسته ،در مدخل
جدول نگاشتهای صفحهبندی ،بیتهایی وجود دارد که حافظه هسته را از حافظه برنامه سطح کاربر تفکیک
مینماید (پرچم ( PTE_Uخط )۸۰۳بیانگر حق دسترسی سطح کاربر به حافظه مجازی است) .صفحههای
بخش باالیی به هسته تخصیص داده شده و بیت مربوطه نیز این مسئله را تثبیت خواهد نمود .سپس توسط
سازوکاری از دسترسی به مدخلهایی که مربوط به هسته هستند ،زمانی که برنامه سطح کاربر این دسترسی را
صورت میدهد ،جلوگیری خواهد شد .در اینجا اساس تفکر این است که هسته عنصر قابل اعتماد سیستم بوده و
برنامههای سطح کاربر ،پتانسیل مخرب بودن را دارند.
.20به این ترتیب ،در انتهای ،entry.Sامکان اجرای کد Cهسته فراهم میشود تا در انتها تابع ()main
صدا زده (خط )۱۰۶۵شود .این تابع عملیات آمادهسازی اجزای هسته را بر عهده دارد .در مورد هر
تابع به طور مختصر توضیح دهید .تابع معادل در هسته لینوکس را بیابید.
در کد entry.Sهدف این بود که حداقل امکانات الزم جهت اجرای کد اصلی هسته فراهم گردد .به همین علت،
تنها بخشی از هسته نگاشت داده شد .لذا در تابع () mainتابع () kvmallocفراخوانی میگردد (خط )۱۲۲۰تا
آدرسهای مجازی هسته به طور کامل نگاشت داده شوند .در این نگاشت جدید ،اندازه هر تکه پیوسته۴ ،
کیلوبایت است .آدرسی که باید در cr3بارگذاری گردد ،در متغیر kpgdirذخیره شده است (خط .)۱۸۴۲
.21مختصری راجع به محتوای فضای آدرس مجازی هسته توضیح دهید.
.22عالوه بر صفحهبندی در حد ابتدایی از قطعهبندی به منظور حفاظت هسته استفاده خواهد شد .این
عملیات توسط () seginitانجام میگردد .همانطور که ذکر شد ،ترجمه قطعه تأثیری بر ترجمه آدرس
منطقی نمیگذارد .زیرا تمامی قطعهها اعم از کد و داده روی یکدیگر میافتند .با این حال برای کد و
دادههای سطح کاربر پرچم SEG_USERتنظیم شده است .چرا؟ (راهنمایی :علت مربوط به ماهیت
دستورالعملها و نه آدرس است).
9
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
procتخصیص داده میشود (خط .)۲۵۲۵این تابع بخشهایی را که برنامه برای اجرا در سطح ممتاز (هسته)
نیاز دارد ،مقداردهی میکند .یکی از عملیات مهمی که در این تابع صورت میگیرد ،مقداردهی
38
p->context->eipبه آدرس تابع () forkretاست .این عمل منجر به این میشود که هنگام اجرای برنامه
ابتدا () forkretاجرا گردد .آمادهسازی بخشهای باقیمانده سیستم در این تابع انجام میشود.
.24چرا به خواب رفتن در کد مدیریتکننده سیستم مشکلساز است؟ (راهنمایی :به زمانبندی در ادامه
توجه نمایید).
در ادامه تابع ،)(userinitتابع () setupkvmفراخوانی شده و فضای آدرس مجازی هسته را برای برنامه
سطح کاربر مقداردهی میکند.
.25تفاوت این فضای آدرس هسته با فضای آدرس هسته که توسط () kvmallocدر خط ۱۲۲۰صورت
گرفت چیست؟ چرا وضعیت به این شکل است؟
تابع () inituvmفضای آدرس مجازی سطح کاربر را برای این برنامه مقداردهی مینماید .به طوری که در
آدرس صفر تا ۴کیلوبایت ،کد مربوط به initcode.Sقرار گیرد.
.26تفاوت این فضای آدرس کاربر با فضای آدرس کاربر در کد مدیریت سیستم چیست؟
یک برنامه سطح کاربر میتواند برای دسترسی به سرویسهای ممتاز سیستم به مد ممتاز ( )CPL=3منتقل شود.
به این ترتیب میتواند حتی به حافظه هسته نیز دسترسی داشته باشد .به منظور تغییر مد امن ،سازوکارهایی
مانند فراخوانی سیستمی 39وجود دارد .تفاوت در این سبک دسترسی این است که هسته آن را با یک سازوکار
امن مدیریت مینماید .اجرای کد از فضای آدرس مجازی سطح کاربر به فضای آدرس مجازی هسته منتقل
میشود .لذا باید وضعیت اجرای برنامه سطح کاربر در فضای آدرس مجازی سطح کاربر در مکانی ذخیره
41
گردد .این مکان قاب تله 40نام داشته و در ساختار procذخیره میشود.
با توجه به این که اجرا در مد هسته است و جهت اجرای برنامه سطح کاربر باید به مد سطح کاربر منتقل شد،
حالت سیستم به گونهای شبیهسازی میشود که گویی برنامه سطح کاربر در حال اجرا بوده و تلهای رخ داده
است .لذا فیلد مربوطه در procباید مقداردهی شود .با توجه به این که قرار است کد به سطح کاربر بازگردد،
بیتهای مربوط به سطح دسترسی جاری ثباتهای قطعه p->tf->csو p->tf->dsبه DPL_USERمقداردهی
شدهاند p->tf->eip .برابر صفر شده است (خط .)۲۵۳۹این بدان معنی است که زمانی که کد به سطح کاربر
بازگشت ،از آدرس مجازی صفر شروع به اجرا میکند .به عبارت دیگر اجرا از ابتدای کد initcode.Sانجام
خواهد شد .در انتها p->stateبه RUNNABLEمقداردهی میشود (خط .)۲۵۵۰این یعنی برنامه سطح کاربر
قادر به اجرا است .حالتهای ممکن دیگر یک برنامه در فصل زمانبندی بررسی خواهد شد.
در انتهای تابع () mainتابع () mpmainفراخوانی شده (خط )۱۲۳۶و به دنبال آن تابع ()scheduler
فراخوانی میشود (خط .)۱۲۵۷به طور ساده ،وظیفه زمانبند تعیین شیوه اجرای برنامهها بر روی پردازنده
میباشد .زمانبند با بررسی لیست برنامهها یک برنامه را که p->stateآن RUNNABLEاست بر اساس
معیاری انتخاب نموده و آن را به عنوان کد جاری بر روی پردازنده اجرا میکند .این البته مستلزم تغییراتی در
وضعیت جاری سیستم جهت قرارگیری حالت برنامه جدید (مثالً تغییر cr3برای اشاره به جدول نگاشت برنامه
جدید) روی پردازنده است .این تغییرات در فصل زمانبندی تشریح میشود .با توجه به این که تنها برنامه قابل
اجرا برنامه initcode.Sاست ،پس از مهیا شدن حالت پردازنده و حافظه در اثر زمانبندی ،این برنامه اجرا
شده و به کمک یک فراخوانی سیستمی برنامه init.cرا اجرا نموده که آن برنامه نیز در نهایت یک برنامه
ترمینال (خط )۸۵۲۹را ایجاد میکند .به این ترتیب امکان ارتباط با سیستمعامل را فراهم میآورد.
.27کدام بخش از آمادهسازی سیستم ،بین تمامی هستههای پردازنده مشترک و کدام بخش اختصاصی است؟
(از هر کدام یک مورد را با ذکر دلیل توضیح دهید ).زمانبند روی کدام هسته اجرا میشود؟
10
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
اشکال زدایی
کد هر برنامهای ممکن است دارای اشکال باشد .اشکالزدایی ممکن است ایستا ،پویا و یا به صورت ترکیبی
صورت پذیرد .کشف اشکال در روشهای ایستا ،بدون اجرا و تنها بر اساس اطالعات کد برنامه صورت
میگیرد .به عنوان مثال کامپایلر Clangدارای تحلیلگرهای ایستا برای اشکالزدایی اشکالهای خاص است.
اشکالزدایی پویا که معموالً دقیقتر است ،اقدام به کشف اشکال در حین اجرای برنامه مینماید .ابزار
Valgrindیک اشکالزدای پویا برای تشخیص نشتی حافظه 42است .از یک منظر leak-checkدر ابزار
میتوان اشکالزداهای پویا را به دو دسته تقسیم نمود )۱ :اشکالزداهایی که بر یک نوع اشکال خاص مانند
نشتی تمرکز دارند و )۲اشکالزداهایی که مستقل از نوع اشکال بوده و تنها اجرا را ردگیری 43نموده و
اطالعاتی از حالت سیستم (شامل سختافزار و نرمافزار) در حین اجرا یا پس از اجرا جهت درک بهتر رفتار
برنامه برمیگردانند .در این بخش ابزار اشکالزدای گنو ،)GDB( 44که یک اشکالزدای پویا از نوع دوم است
معرفی خواهد شد.
GDBیک اشکالزدای متداول در سیستمهای یونیکسی بوده که در بسیاری از شرایط ،نقش قابلتوجهی در
تسریع روند اشکالزدایی ایفا میکند .اشکالزدایی برنامههای تکریسهای ،45چندریسهای 46و حتی هستههای
سیستمعامل توسط این ابزار ممکن است .جهت اشکال زدایی xv6با ،GDBدر گام نخست باید سیستمعامل به
صورتی بوت شود که قابلیت اتصال اشکالزدا به آن وجود داشته باشد .مراحل اتصال عبارت است از:
.1در یک ترمینال دستور make qemu-gdbاجرا گردد.
.2سپس در ترمینالی دیگر ،فایل کد اجرایی به عنوان ورودی به GDBداده شود.
چنانچه پیشتر ذکر شد کد اجرایی شامل یک نیمه هسته و یک نیمه سطح کاربر بوده که نیمه هسته ،ثابت و نیمه
سطح کاربر ،بسته به برنامه در حال اجرا بر روی پردازنده دائما ً در حال تغییر است .به این ترتیب ،به عنوان
مثال ،هنگام اجرای برنامه ،catکدهای اجرایی سیستم شامل کد هسته و کد برنامه catخواهند بود .جهت
اشکالزدایی بخش سطح کاربر ،کافی است دستور gdb _catو جهت اشکالزدایی بخش هسته دستور gdb
kernelفراخوانی شود .دقت شود در هر دو حالت ،هر دو کد سطح هسته و کاربر اجرا میشوند .اما
اشکالزدا فقط روی یک کد اجرایی (سطح کاربر یا هسته) کنترل داشته و تنها قادر به انجام عملیات بر روی آن
قسمت خواهد بود.
.3نهایتا ً با وارد کردن دستور target remote tcp::26000در ،GDBاتصال به سیستمعامل صورت
خواهد گرفت.
روند اجرای GDB
GDBمیتواند در هر گام از اجرا ،با ارائه حالت سیستم ،به برنامهنویس کمک کند تا حالت خطا را از حالت
مورد انتظار تشخیص دهد .هنگام اجرای کد در GDBممکن است چندین حالت رخ دهد:
.1اجرا با موفقیت جریان داشته باشد یا خاتمه یابد.
.2اجرا به علت اشکال ،ناتمام مانده و برنامه متوقف شود.
.3اجرا متوقف نشده ولی حالت سیستم در برخی نقاط درونی یا در خروجیهای برنامه نادرست باشد.
11
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
هدف ،یافتن حاالت خطای سیستم در دو وضعیت ۲و ۳است .به عبارتی ابتدا باید در نقطه مورد نظر ،توقف
صورت گرفته و سپس به کمک دستورهایی حالت سیستم را استخراج نمود .برای توقف اجرا در نقاط مختلف
اجرا در GDBسازوکارهای مختلفی وجود دارد:
.1در اجرای ناتمام ،اجرای برنامه به طور خودکار متوقف میشود.
.2با فشردن کلید ترکیبی Ctrl + Cبه اشکالزدا بازگشت.
این عملیات در میان اجرا ،آن را متوقف نموده و کنترل را به خط فرمان اشکالزدا منتقل میکند .مثالً حلقه
بینهایت رخ داده باشد ،میتوان با این کلید ترکیبی ،در نقطهای از حلقه متوقف شد.
.3روی نقطهای از برنامه Breakpointقرار داد .بدین ترتیب هر رسیدن اجرا به این نقطه منجر به
توقف اجرا گردد.
روشهای مختلفی برای تعیین نقطه استقرار Breakpointوجود داشته که در این لینک قابل مشاهده است.
از جمله:
انتخاب نام و شماره خط فایل
$ break cat.c:12
انتخاب نام تابع
$ b cat
انتخاب آدرس حافظه
$ b *0x98
این نقاط میتوانند در سطح کاربر یا هسته سیستمعامل باشند .همچنین میتوانند شرطی تعریف شوند.
.4روی خانه خاصی از حافظه Watchpointقرار داد تا دسترسی یا تغییر مقدار آن خانه ،منجر به
توقف اجرا گردد.
Watchpointها انواع مختلفی داشته و با دستورهای خاص خود مشخص میگردند.
دستور زیر:
$ watch *0x1234567
یک Watchpointروی آدرس 0x1234567در حافظه میگذارد .بدین ترتیب نوشتن در این آدرس،
منجر به توقف اجرا خواهد شد.
ً
میتوان از نام متغیر هم استفاده نمود .مثال watch v، Watchرا روی (آدرس) متغیر vقرار میدهد.
باید دقت نمود ،اگر Watchروی متغیر محلی قرار داده شود ،با خروج از حوزه دسترسی به آن متغیر،
Watchحذف شده و به برنامهنویس اطالع داده میشود .اگر هم آدرسی از فضای پشته47و 48داده شود،
ممکن است در حین اجرا متغیرها یا دادههای نامرتبط دیگری در آن آدرس نوشته شود .یعنی این آدرس در
زمانهای مختلف مربوط به دادههای مختلف بوده و در عمل Watchکارایی مورد نظر را نداشته باشد.
یک مزیت مهم ،Watchتشخیص وضعیت مسابقه 49است که در فصول بعدی درس با آن آشنا خواهید شد.
در این شرایط میتوان تشخیص داد که کدام ریسه 50یا پردازه مقدار نامناسب را در آدرس حافظه نوشته که
منجر به خطا شده است.
همانطور که مشاهده میشود ،خیلی از حاالت با استفاده از چهار سازوکار مذکور به سهولت قابل استخراج
نیستند .مثالً حالتی که یک زنجیره خاص فراخوانی توابع وجود داشته باشد یا این که مثالً حالتی خاص در
دادهساختارها رخ داده و یک لیست پیوندی ،چهارمین عنصرش را حذف نماید.
)۱برای مشاهده Breakpointها از چه دستوری استفاده میشود؟
)۲برای حذف یک Breakpointاز چه دستوری و چگونه استفاده میشود؟
Stack 47
48یعنی فضای آدرسی که دادههایی از جمله مقادیر متغیرهای محلی و آدرسهای برگشت مربوط به توابع فراخوانی شده در آن قرار دارد.
Race Condition 49
Thread 50
12
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
مربوط به نقطه توقف ،قابل رؤیت است .برای اطالعات بیشتر در رابطه با این رابط کاربری میتوانید به این
صفحه مراجعه کنید.
)۷خروجی دستورهای layout srcو layout asmدر TUIچیست؟
)۸برای جابجایی میان توابع زنجیره فراخوانی جاری (نقطه توقف) از چه دستورهایی استفاده میشود؟
دستورهای stepiو nextiمعادلهای سطح اسمبلی stepو nextبوده و به جای یک دستور سی ،در
ریزدانگی یک دستورالعمل ماشین عمل میکنند .در شرایطی که کد مورد اشکالزدایی از ابتدا در زبان اسمبلی
نوشته شده باشد ،چارهای جز استفاده از این دستورها وجود نخواهد داشت.
نکات پایانی
با توجه به کاستیهایی که در اشکالزداها وجود دارد ،همچنان برخی از تکنیکها در کدزنی میتواند بسیار
راهگشا باشد .سادهترین راه برای اشکالزدایی این است که تغییرها را اندک انجام داده و گامبهگام از صحت
C 51
Text user interface 52
13
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
اجرای کد ،اطمینان حاصل شود .به عنوان مثال اگر آرایهای ۱۰۰عنصری تخصیص داده شده و در نقطهای
فراتر از مرز انتهایی آن نوشتن صورت گیرد ،حافظهای غیر از حافظه مربوط به آرایه دستکاری میگردد.
چندین حالت ممکن است رخ دهد .از جمله اینکه:
.1اقدام به نوشتن در حافظهای فقط خواندنی مانند کد برنامه ،صورت پذیرد .در چنین شرایطی خطا رخ
داده و نقطه توقف به راحتی در GDBقابل رؤیت خواهد بود.
.2در حافظه نوشتنی نامرتبط نوشته شده و مشکلی پیش نیاید.
.3در حافظه نوشتنی نامرتبط نوشته شود و اجرای برنامه به طرز عجیبی متوقف گردد .به طوری که
GDBنقطه نامربوطی را نشان دهد .یعنی تأثیر آن بالفاصله و به طور مستقیم رخ ندهد .در چنین
شرایطی استفاده ابتدایی از اشکالزدا راحتی راهگشا نخواهد بود .چک کردن اندازه آرایه و احتمال
دسترسی به خارج آن در سطح کد ،میتوانست راحتتر باشد .البته در برخی موارد به سادگی و یا با
تکنیکهایی مانند استفاده از ،Watchضبط اجرا و حرکت رو به عقب از حالت نادرست ،میتوان
اشکال را یافت .53اما تکنیک قبلی بهتر بود.
بنابراین ،استفاده از GDBدر کنار دیگر ابزارها و تکنیکها در پروژههای این درس توصیه میگردد .با توجه
به آشنایی اولیهای که با GDBفراهم شده است ،میتوان مزایای آن را برشمرد:
● اشکالزدایی کدهای بزرگ و کدهایی که با پیادهسازی آنها آشنایی وجود ندارد .ممکن است نیاز باشد
یک کد بزرگ را به برنامه اضافه کنید .در این شرایط اشکالزدایی اجرای Crashکرده در GDB
درک اولیهای از نقطه خرابی ارائه میدهد.
● بررسی مقادیر حالت برنامه ،بدون نیاز به قرار دادن دستورهای چاپ مقادیر در کد و کامپایل مجدد آن.
● بررسی مقادیر حالت سختافزار و برنامه که در سطح کد قابل رؤیت نیستند .به عنوان مثال مقدار یک
اشارهگر به تابع ،مقصد یک تابع کتابخانهای ،اطمینان از قرارگیری آدرس متغیر محلی در بازه حافظه
پشته ،این که اجرا در کدام فایل کد منبع قرار دارد ،اطالع از وضعیت فضای آدرس حین اجرا ،مثالً
این که هر کتابخانه در چه آدرسی بوده و در کدام کتابخانه در حال اجرا هستیم و ....
● تشخیص اشکالهای پیچیده مانند این که کدام ریسه ،یک متغیر را دستکاری نموده یا چرا یک متغیر
مقدار نادرستی داشته یا مقداردهی اولیه نشده است .این اشکالهای با کمک Watchو ضبط و اجرای
مجدد رو به جلو/عقب به راحتی قابل تشخیص هستند.
GDB 53در برنامههای عادی قادر به ضبط و اجرای رو به عقب برنامه است .همچنین ابزار RRکه توسط شرکت موزیال برای اشکالزدایی
فایرفاکس ارائه شده است امکان انجام همین عملیات را به صورت قطعی دارد .این قطعیت ،در اشکالزدایی کدهای همروند و وضعیت مسابقه
بسیار کمککننده است.
14
پاییز ۱۴۰۲ آزمایشگاه سیستمعامل پروژه ۱
نکات مهم
• برای تحویل پروژه ابتدا یک مخزن خصوصی در سایت GitHubایجاد نموده و سپس پروژه خود را در آن
Pushکنید .سپس اکانت UT-OS-TAرا با دسترسی Maintainerبه مخزن خود اضافه نمایید .کافی است
در محل بارگذاری در سایت درس ،آدرس مخزن ،شناسه آخرین Commitو گزارش پروژه را بارگذاری
نمایید.
• به سؤاالتی که در صورت پروژه از شما خواسته شده است پاسخ دهید و آنها را در گزارشکار خود
بیاورید.
ً
• همه اعضای گروه باید به پروژه آپلود شده توسط گروه خود مسلط باشند و لزوما نمره افراد یک گروه با
یکدیگر برابر نیست.
• در صورت مشاهده هرگونه مشابهت بین کدها یا گزارش دو گروه ،نمره 0به هر دو گروه تعلق میگیرد.
• سؤاالت را در کوتاهترین اندازه ممکن پاسخ دهید.
15