تطوير نظام تشغيل أحادي يونيكس يشبه - سجل نظام 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