تطوير نظام تشغيل أحادي يونيكس يشبه - سجل نظام Kernel (3)

في المقالة السابقة ، الثانية في صف واحد ، قمنا بتطوير الوظائف اللازمة للعمل مع سلاسل من مكتبة C. في هذا الدرس ، نقوم بتنفيذ إخراج تصحيح كامل على الشاشة - سجل نظام kernel.

جدول المحتويات


  1. بناء نظام (جعل ، مجلس التعاون الخليجي ، الغاز). التمهيد الأولي (متعدد التمهيد). إطلاق (qemu). مكتبة C (strcpy ، memcpy ، strext).
  2. مكتبة C (sprintf ، strcpy ، strcmp ، strtok ، va_list ...). بناء المكتبة في وضع kernel ووضع تطبيق المستخدم.
  3. سجل نظام النواة. ذاكرة الفيديو الإخراج إلى المحطة (kprintf ، kpanic ، kassert).
  4. الذاكرة الديناميكية ، الكومة (kmalloc ، kfree).
  5. تنظيم الذاكرة والتعامل مع المقاطعة (GDT ، IDT ، PIC ، syscall). الاستثناءات.
  6. الذاكرة الظاهرية (دليل الصفحة وجدول الصفحة).
  7. العملية. المجدول. تعدد المهام. مكالمات النظام (القتل ، الخروج ، ملاحظة).
  8. نظام ملفات kernel (initrd) ، قزم ، وداخله. مكالمات النظام (exec).
  9. برامج تشغيل الأجهزة الشخصية. مكالمات النظام (ioctl ، fopen ، fread ، fwrite). مكتبة C (fopen ، fclose ، fprintf ، fscanf).
  10. شل كبرنامج كامل للنواة.
  11. وضع حماية المستخدم (ring3). قسم حالة المهمة (tss).

سجل نظام Kernel


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

extern u_char asm_read_port(u_char port); extern void asm_write_port(u_int port, u_char data); 

وبالمثل ، هناك أمران للتحكم في مقاطعات المعالج المقنع.

 extern void asm_lock(); extern void asm_unlock(); 

حسنًا ، لتوفير الطاقة بعد الأخطاء القاتلة ، فأنت بحاجة إلى أمر إيقاف المعالج.

 extern void asm_hlt(); 

كما تتذكر ، تبدأ ذاكرة الفيديو في 0xB8000 ، لكنني أقترح كتابة الرسائل أولاً إلى المخزن المؤقت بتنسيق نص عادي. ثم انسخ هذا المخزن المؤقت في ذاكرة الفيديو ، مع مراعاة سمات الألوان. للقيام بذلك ، قمت بتنفيذ العديد من الأدوات المساعدة للعمل مع هذه المخازن المؤقتة. سيكون المخزن المؤقت واحد syslog kernel ، والباقي من أجل المحطات الافتراضية. سيتم تنفيذ التمرير على الشاشة أيضًا على المخزن المؤقت. ولن تؤدي وظيفة video_flush إلا إلى نسخ المخزن المؤقت إلى ذاكرة الفيديو ، مع توسيعه بسمات.

 extern void video_init(); extern void video_disable_cursor(); extern void* video_scroll(char const* video_buff, char* pos); extern char* video_clear(char const* video_buff); extern void video_flush(char const* video_buff); 

الآن هو الوقت المناسب لتقديم الميزات الأكثر استخدامًا. سيتم استخدام الأخيرتين لتصحيح kernel عندما يتم تصحيح الكسل بواسطة المصحح. صدقوني ، لم أستخدم مصححًا أبدًا عندما كتبت هذا النواة.

 extern void kpanic(char* message, ...); extern void kassert(const char* file, u_int line, bool expr); extern void kunreachable(const char* file, u_int line); 

حسنا ، في الواقع ، وظائف للعمل مع سجل نظام kernel. للتحكم في ما يتم عرضه على الشاشة ، أدخلت وظيفة kmode في سجل النظام أو وحدة تحكم المستخدم. لقراءة سجل النظام في المخزن المؤقت ، ستكون هناك حاجة إلى وظيفة klog ، لأن عمليات المستخدم لن يكون لها حق الوصول إلى kernel إلا من خلال مكالمات النظام.

 extern void kclear(); extern void kprintf(const char* format, ...); extern void kvprintf(const char* format, va_list list); extern void kmode(bool is_early); extern void klog(char* buf, u_int n); 

أعطي الوظائف الأكثر إثارة للاهتمام هنا:

 /* * Api - Scroll video buffer up * Returns new position */ extern void* video_scroll(char const* video_buff, char* pos) { char* ptr = (void*)video_buff; /* scroll up */ for (int i = 1; i < VIDEO_SCREEN_HEIGHT; ++i) { for (int j = 0; j < VIDEO_SCREEN_WIDTH; ++j) { ptr[(i - 1) * VIDEO_SCREEN_WIDTH + j] = ptr[i * VIDEO_SCREEN_WIDTH + j]; } } /* empty last line */ for (int j = 0; j < VIDEO_SCREEN_WIDTH; ++j) { ptr[(VIDEO_SCREEN_HEIGHT - 1) * VIDEO_SCREEN_WIDTH + j] = ' '; } /* move position up */ pos -= VIDEO_SCREEN_WIDTH; return pos; } 

 /* * Api - Print kernel message */ extern void kvprintf(const char* format, va_list list) { char buff[VIDEO_SCREEN_WIDTH]; int len = vsprintf(buff, format, list); for (int i = 0; i < len; ++i) { if (buff[i] != '\n') { kputc(buff[i]); } else { int line_pos = (syslog_pos - syslog) % VIDEO_SCREEN_WIDTH; for (int j = 0; j < VIDEO_SCREEN_WIDTH - line_pos; ++j) { kputc(' '); } } } kflush(); } 

 /* * Put character to syslog */ static void kputc(char ch) { if ((size_t)syslog_pos - (size_t)syslog + 1 < VIDEO_SCREEN_SIZE) { *syslog_pos++ = ch; } else { syslog_pos = video_scroll(syslog, syslog_pos); kputc(ch); } } 

انظر البرنامج التعليمي المفصل في الفيديو التعليمي.

مراجع


→ فيديو تعليمي لهذا المقال
→ شفرة المصدر (تحتاج إلى فرع الدرس 3)

مراجع


  1. جيمس مولوي. لفة نظام التشغيل الخاص بك UNIX استنساخ.
  2. زوبكوف. مجمع ل DOS ، ويندوز ، يونيكس
  3. كلاشينكوف. المجمع سهل!
  4. تانينباوم. أنظمة التشغيل. التنفيذ والتطوير.
  5. روبرت لوف. نواة لينكس وصف عملية التطوير.

Source: https://habr.com/ru/post/ar466765/


All Articles