Nand2Tetris — الجزء الثاني: من الآلة الافتراضية إلى نظام التشغيل › المشروع 12: نظام التشغيل 6 / 6 السابق

المشروع 12: نظام التشغيل

المشروع 12: نظام التشغيل

خلفية

نظام التشغيل (OS) مجموعة من الخدمات البرمجية، صُمّمت لسدّ الفجوات بين عتاد الحاسوب وبرمجيات التطبيقات. فمثلًا، إذا استخدمت لغة عالية المستوى لكتابة برنامج يطلب من المستخدم إدخال بعض البيانات باستخدام لوحة المفاتيح، فإن الشيفرة التي يولّدها المصرِّف ستتضمّن (من بين أمور أخرى) نداءات إلى روتينات نظام التشغيل التي تتولّى معالجة مُدخلات لوحة المفاتيح. وبالتالي، يمكن النظر إلى نظام التشغيل أيضًا بوصفه امتدادًا للغة البرمجة عالية المستوى. وهذه نظرة مبسّطة إلى حدّ ما لأنظمة التشغيل، لكنها تكفي لهدفنا.

الهدف

نفّذ نظام التشغيل Jack OS المحدّد في الفصل 12. وخلال بناء نظام التشغيل هذا، ستنفّذ مجموعة معيارية من بعض الخوارزميات الجميلة في علوم الحاسوب التطبيقية. وبذلك، ستتعرّف أيضًا عمليًا على بعض الموضوعات الرائعة في علوم الحاسوب.

العقد

اكتب تنفيذًا لنظام التشغيل Jack OS، واختبره باستخدام البرامج وسيناريوهات الاختبار الموضحة أدناه.

الموارد

يتضمّن الفصل 12 واجهة برمجة تطبيقات نظام التشغيل Jack OS، التي يتعيّن تنفيذها في هذا المشروع. والأداة الرئيسية المطلوبة هي Jack، لغة البرمجة عالية المستوى التي ستبني بها نظام التشغيل (تمامًا كما بُني Unix بلغة C). وستحتاج أيضًا إلى مصرِّف Jack المرفق، لتجميع تنفيذ نظام التشغيل خاصّك وكذلك برامج الاختبار المرفقة، وإلى مُحاكٍ الآلة الافتراضية (VM Emulator) المرفق، لتشغيل الشيفرة المترجمة واختبارها.

الاختبار

يُنفّذ نظام التشغيل بصفته مجموعة من 8 أصناف Jack. ويمكن تنفيذ كل صنف واختباره اختبارًا وحدويًا في معزل عن الآخرين، وبأي ترتيب مرغوب. ولتطوير كل صنف OSClass.jack وتجميعه واختباره في معزل عن غيره، اتّبع هذا الإجراء:

  • ضع ملف OSClass.jack الذي تطوّره في نفس المجلد الذي يتضمّن برنامج الاختبار المرفق والمصمّم لاختباره؛

  • جمّع المجلد باستخدام مصرِّف Jack المرفق. وسيؤدي ذلك إلى تجميع ملف OSClass.jack خاصّك وكذلك ملفات أصناف الاختبار المرفقة. وخلال هذه العملية، سيُنشأ ملف OSClass.vm جديد؛

  • حمّل المجلد إلى مُحاكٍ الآلة الافتراضية المرفق؛

  • نفّذ الشيفرة وتحقّق مما إذا كانت خدمات نظام التشغيل تعمل بصورة صحيحة، وفقًا للإرشادات المُبيّنة أدناه.

تذكّر أن مُحاكٍ الآلة الافتراضية المرفق يتضمّن تنفيذًا مدمجًا لنظام التشغيل Jack OS بأكمله. ومعهذا، فإن منطق الإجراء الموضّح أعلاه هو كالآتي. فعادةً، حين يصادف مُحاكٍ الآلة الافتراضية المرفق نداءً لدالّة في نظام التشغيل، فإنه يتولّى النداء باستدعاء التنفيذ المدمج لتلك الدالّة. ولكن، إذا احتوى المجلد المترجَم على ملف .vm يتضمّن تنفيذ VM للدالّة، فسيُنفّذ هذا التنفيذ، مقصّرًا التنفيذ المدمج. وتتبعًا لهذه الممارسة، على غرار روح الهندسة العكسية في GNU Unix وLinux، يمكنك بناء واختبار وحدات نظام تشغيل مختلفة في معزل عن بعضها، كأنّ جميع وحدات نظام التشغيل الأخرى منفّذة بصورة صحيحة وتعمل جنبًا إلى جنب مع الوحدة قيد التطوير. وهذا أمر مهم، إذ إنّ صنف نظام التشغيل الذي تطوّره حاليًا قد يتضمّن نداءات إلى خدمات أصناف نظام تشغيل أخرى.

أصناف نظام التشغيل وبرامج الاختبار

ثمة ثمانية أصناف لنظام التشغيل: Memory وArray وMath وString وScreen وKeyboard وSys. ولكل صنف نظام تشغيل Xxx، نرفق ملف صنف هيكلي Xxx.jack يتضمّن جميع تواقيع الروتينات الفرعية المطلوبة، وصنف اختبار مقابل اسمه Main.jack، وسكربتات اختبار ذات صلة.

وحدة نظام التشغيل برامج الاختبار
Memory.jack Main.jack MemoryTest.tst MemoryTest.cmp
Array.jack Main.jack ArrayTest.tst ArrayTest.cmp
Math.jack Main.jack MathTest.tst MathTest.cmp
التعليقات
لاختبار تنفيذك لهذا الصنف من أصناف نظام التشغيل، جمّع المجلد، ونفّذ سكربت الاختبار على مُحاكٍ الآلة الافتراضية المرفق، وتأكّد من أن المقارنة مع ملف المقارنة تنتهي بنجاح.
الإرشادات نفسها.
الإرشادات نفسها.

لا تتضمّن برامج الاختبار المرفقة أعلاه اختبارًا كاملاً لدالّتي Memory.alloc وMemory.deAlloc. فالاختبار الكامل لهاتين دالّتي إدارة الذاكرة يتطلّب فحص تفاصيل التنفيذ الداخلية غير المرئية في الاختبار على مستوى المستخدم. ويمكن فعل ذلك عبر التنقيح خطوة بخطوة في مُحاكٍ الآلة الافتراضية المرفق.

لا تتضمّن برامج الاختبار المتبقية أي سكربتات اختبار. ويجب تجميعها وتنفيذها على مُحاكٍ الآلة الافتراضية المرفق على النحو التالي:

وحدة نظام التشغيل برامج الاختبار سكربتات الاختبار
String.jack يختبر هذا الصنف من نظام التشغيل عبر برنامج اختبار يتضمّن بعض التفاعل بين المستخدم والبرنامج. فبالنسبة لكل دالّة في صنف نظام التشغيل Keyboard (keyPressed وreadChar وreadLine وreadInt)، يطلب البرنامج من المستخدم الضغط على بعض مفاتيح لوحة المفاتيح. فإذا كانت دوالّ نظام التشغيل منفّذة بصورة صحيحة وتمّ الضغط على المفاتيح المطلوبة، يطبع البرنامج النصّ "ok" وينتقل لاختبار الدالّة التالية. وإلا، كرّر البرنامج الطلب للدالّة نفسها. وإذا انتهت جميع الطلبات بنجاح، طبع البرنامج النصّ "Test ended successfully"، وحينها قد تبدو الشاشة كالآتي:
Output.jack يمكن اختبار دالّتين فقط في هذا الصنف: Sys.init وSys.wait. ويختبر برنامج الاختبار المرفق دالّة Sys.wait بطلب الضغط على أي مفتاح من المستخدم، والانتظار ثانيتين (باستخدام Sys.wait)، ثم طبع رسالة أخرى على الشاشة. والزمت الذي يمضي من لحظة رفع اليد عن المفتاح حتى طبع الرسالة التالية يجب أن يكون ثانيتين. أما دالّة Sys.init فلا تُختبر صراحةً. لكن تذكّر أنها تنفّذ جميع تهيئات نظام التشغيل الضرورية ثم تستدعي دالّة Main.main لكل برنامج اختبار. وبالتالي، يمكن افتراض أن لا شيء سيعمل بصورة صحيحة إلا إذا كانت Sys.init منفّذة بصورة صحيحة. وطريقة بسيطة لاختبار Sys.init في معزل عن غيرها هي تشغيل لعبة Pong المرفقة باستخدام ملف Sys.vm خاصّك.
Screen.jack
Keyboard.jack
Sys.jack

الاختبار الكامل، و...

بعد اختبار كل صنف من أصناف نظام التشغيل بنجاح في معزل عن غيره، اختبر تنفيذ نظام التشغيل بالكامل باستخدام لعبة Pong، التي يتوفّر شيفرها المصدري في مجلد projects/11/Pong خاصّك. ضع جميع ملفات .jack لنظام التشغيل خاصّك في هذا المجلد، وجمّعه، ونفّذ اللعبة في مُحاكٍ الآلة الافتراضية المرفق. فإن عملت اللعبة، فتهانينا: أنت الآن المالك الفخور لنظام تشغيل كتبته بكاملك. وبالمناسبة، أكملت للتوّ بناء نظام حاسوب عامّ الغرض كامل. اذهب واحتفل!