محاكاة Linus Torvalds: قم بإنشاء نظام التشغيل الخاص بك من 0 (V)

في هذه الدفعة الخامسة ، سنرى جدولًا مشابهًا تمامًا لـ GDT سواء من الناحية النظرية أو في الاستخدام ، نشير إلى IDT. IDT تعني المقاطعات وصف الجدول y هو جدول يُستخدم للتعامل مع المقاطعات التي تحدث. على سبيل المثال ، يقوم شخص ما بإجراء قسمة على 0 ، تسمى الوظيفة المسؤولة عن المعالجة. هذه الوظائف هي ISR (إجراءات خدمة المقاطعة). لذلك دعونا ننشئ IDT ونضيف بعض ISR.

أولاً ، سنعلن عن الهياكل المقابلة لـ IDT:

struct Entry{
uint16_t base_low;
uint16_t sel;
uint8_t always0;
uint8_t flags;
uint16_t base_high;
} __attribute__((packed));
struct Ptr{
uint16_t limit;
uint32_t base;
} __attribute__((packed));

كما يمكن رؤيته إذا قارنته بـ GDT ، فإن بنية Ptr متطابقة والإدخال مشابه تمامًا. لذلك فإن وظائف وضع إدخال (SetGate) وتثبيت (تثبيت) متشابهة جدًا.

void ND::IDT::SetGate(uint8_t num,uint32_t base,uint16_t sel, uint8_t flags)
{
idt[num].base_low=(base & 0xFFFF);
idt[num].base_high=(base >> 16) & 0xFFFF;
idt[num].sel=sel;
idt[num].always0=0;
idt[num].flags=flags;
}

تثبيت:

idtptr.limit=(sizeof(struct ND::IDT::Entry)*256)-1;
idtptr.base=(uint32_t)&idt;
ND::Memory::Set(&idt,0,sizeof(struct ND::IDT::Entry)*256);
ND::IDT::Flush();

إذا نظرنا ، فسنرى أن وظيفة التثبيت تستخدم وظيفة ND :: Memory :: Set التي أعلنا عنها في المنشور الآخر. يمكننا أيضًا أن نقدر كيف أننا لا نجري أي مكالمات إلى SetGate حتى الآن ونسمي ND :: IDT :: Flush ، لهذه الوظيفة ، نستخدم عبارة asm المتغيرة مرة أخرى:

asm volatile("lidtl (idtptr)");

إذا سارت الأمور على ما يرام وقمنا بترتيب جمالي ، يجب أن يبدو كما يلي:

NextDivel-IDT

حسنًا ، سنبدأ الآن في ملء IDT بالمقاطعات. هنا سأقوم بإنشاء واحد فقط ولكن بالنسبة للباقي سيكون هو نفسه. سأقوم بالقسمة على كسر صفر. كما تعلم في الرياضيات ، لا يمكن تقسيم الرقم على 0. إذا حدث هذا في المعالج ، يتم إنشاء استثناء لأنه لا يمكن أن يستمر. في IDT المقاطعة الأولى في القائمة (0) تتوافق مع هذا الحدث.

نضيف هذا بين إعداد الذاكرة والتدفق داخل وظيفة التثبيت الخاصة بـ IDT:

ND::IDT::SetGate(0,(unsigned)ND::ISR::ISR1,0x08,0x8E);

ستكون وظيفة رد الاتصال ND :: ISR :: ISR1 وهي بسيطة للغاية على الرغم من أنه يجب علينا استخدام ASM:

void ND::ISR::ISR1()
{
asm volatile(
"cli \n"
"pushl 0 \n"
"pushl 0 \n"
"jmp ND_ISR_Common \n"
);
}

ND_ISR_Common سنعرّفها كدالة في لغة C. لحفظ الملفات وتحسين إمكانية القراءة ، يمكننا استخدام خارجي «C» {}:

extern "C"
void ND_ISR_Common()
{
asm volatile(
"pusha \n"
"push %ds \n"
"push %es \n"
"push %fs \n"
"push %gs \n"
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movl %esp, %eax \n"
"push %eax \n"
"movl $ND_ISR_Handler, %eax \n"
"call *%eax \n"
"popl %eax \n"
"popl %ds \n"
"popl %es \n"
"popl %fs \n"
"popl %gs \n"
"popa \n"
"addl 8, %esp \n"
"iret \n"
);
}

قد يكون من الصعب فهم هذا الرمز في ASM ولكن هذا لأننا سنعلن عن بنية في C للوصول إلى البيانات التي تم إنشاؤها بواسطة المقاطعة. من الواضح ، إذا كنت لا تريد ذلك ، يمكنك فقط استدعاء Kernel Panic في ND :: ISR :: ISR1 أو شيء من هذا القبيل. الهيكل له شكل مثل:

struct regs{
uint32_t ds;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t int_no, err_code;
uint32_t eip, cs, eflags, useresp, ss;
};

وأخيرًا ، قمنا بعمل وظيفة ND_ISR_Handler (أيضًا باستخدام رابط C) والتي نعرض فيها حالة من الذعر في النواة ووصفًا صغيرًا للخطأ وفقًا للخطأ الموجود في قائمة الأخطاء.

extern "C"
void ND_ISR_Handler(struct regs *r)
{
if(r->int_no < 32) { ND::Panic::Show(exception_messages[r->int_no]);
for(;;);
}
}

جيد وبهذا نحن قادرون بالفعل على التعامل مع هذا الانقطاع. مع بقية المقاطعات ، قد يحدث نفس الشيء فيما عدا أن هناك بعضًا يُرجع المعلمات وسنستخدم بنية reg للحصول عليها. ومع ذلك ، قد تتساءل كيف نعرف ما إذا كان يعمل حقًا. لاختبار ما إذا كان يعمل ، سنقوم بإدخال سطر بسيط بعد ND :: IDT :: Install ():

int sum=10/0;

إذا قمنا بتجميعه ، فسوف يعطينا تحذيرًا وإذا حاولنا تنفيذه ، فسنحصل على شاشة لطيفة:

NextDivel-ISR
وبهذا ينتهي هذا المنشور ، أعتقد أنه واحد من أكثر المنشورات شمولاً ولكنه فعال للغاية.


محتوى المقال يلتزم بمبادئنا أخلاقيات التحرير. للإبلاغ عن خطأ انقر فوق هنا.

5 تعليقات ، اترك لك

اترك تعليقك

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها ب *

*

*

  1. المسؤول عن البيانات: ميغيل أنخيل جاتون
  2. الغرض من البيانات: التحكم في الرسائل الاقتحامية ، وإدارة التعليقات.
  3. الشرعية: موافقتك
  4. توصيل البيانات: لن يتم إرسال البيانات إلى أطراف ثالثة إلا بموجب التزام قانوني.
  5. تخزين البيانات: قاعدة البيانات التي تستضيفها شركة Occentus Networks (الاتحاد الأوروبي)
  6. الحقوق: يمكنك في أي وقت تقييد معلوماتك واستعادتها وحذفها.

  1.   ميسودابلر قال

    لقد تحولت إلى LFS ، إنه أكثر استمرارية.

  2.   إليوتيمي 3000 قال

    مقدس ... على أي حال ، الدروس جيدة.

  3.   sc قال

    جيد جدًا ، لقد كنت أتابعها منذ البداية. هل يمكنك إرفاق الرموز بكل مقطورة؟

    1.    شارع أدريان أرويو قال

      لديك كل التعليمات البرمجية المصدر المتوفرة على GitHub: http://github.com/AdrianArroyoCalle/next-divel من هناك يمكنك تنزيل ملف ZIP أو TAR.GZ أو مجرد استخدام git.

  4.   الدقة في درجات االإختلاف قال

    هاهاها جيد جدا! يوافق! 🙂