لعبة OS ، 32 بت أخيرا ينفذ قذيفة تفاعلية بسيطة 
قائمة المهام:
هناك قرصان صلبان في المجموع ، يتم تثبيت النظام نفسه على القرص الرئيسي ، ويتم اعتماد وضع التمهيد لـ MBR ، ويتم استخدام عملية تشغيل mbr-> boot-> kernnel.
يقع MBR في قطاع واحد بدءًا LBA 0号扇区
يقع Boot Loader في 4 قطاعات بدءًا من LBA 2号扇区من القرص
يقع Kernel ضمن 200 قطاع بدءًا من LBA 9号扇区
يتم تنفيذ نظام الملفات على قرص الرقيق. قد لا يكون هذا معقولًا جدًا. إذا كان نظام الملفات يعتمد على منطق النظام التجاري ، فيجب تنفيذه الآن ، ثم يتم تثبيت نظام التشغيل في القسم المقابل.
ترحيل الذاكرة ، صفحة واحدة هي 4 كيلو بايت
تتبنى إدارة الذاكرة إدارة صورة نقطية ، وتتميز بالحجم عند تخصيص الذاكرة. إذا كان أكبر من 1024 بايت ، فسيتم تخصيصه مباشرة حسب الصفحة.
إذا كان أقل من 1024 بايت ، على أساس تخصيص الساحة حسب الصفحة ، استخدم blockchain الخمول في الساحة للتخصيص والتحكم.
للراحة ، على الرغم من تمكين آلية الترحيل ، لا يتم تنفيذ وظيفة التبديل لصفحات الذاكرة والأقراص.

PCB هو حجم صفحة واحدة
يتمثل الجوهر الأساسي لجدولة مؤشرات الترابط في تبديل ثنائي الفينيل متعدد الكلور عن طريق التحكم في تبديل مؤشر ESP عن طريق مقاطعة الساعة. تنعكس الأولوية في طول شريحة وقت التشغيل لكل مؤشر ترابط.
يعتمد تنفيذ العملية على مؤشرات الترابط ، ويعتمد اختيار TSS على Linux ، باستخدام TSS الفردي إلى مكدسي مستوى النسخ الاحتياطي 0 ومستوى 0 مؤشرات المكدس. الفرق الأكبر من سلسلة الرسائل هو أن العملية لديها عنوان جدول صفحة في PCB ، وهو الفرق الأكبر بين العملية وخيط. هذه العملية لها حقًا مساحة ذاكرة افتراضية مستقلة.
لا توجد خوارزمية فعالة في الجدولة ، فقط استخدم جدولة حلقة قائمة الانتظار
تنفيذ موضوع الخمول
تطبيق موضوع الخمول بسيط للغاية. عندما تحصل على الجدول الزمني لأول مرة ، يمكنك حظره وإعطائه من وحدة المعالجة المركزية. عندما يقوم المجدول بتنفيذ الإرسال مرة أخرى ، إذا لم يتم العثور على مؤشر ترابط أو عملية جاهزة في قائمة الانتظار جاهزة ، فسيتم إيقاظ سلسلة الخمول. في هذا الوقت ، يقوم مؤشر ترابط الخمول بتعليق وحدة المعالجة المركزية من خلال hlt . عند استخدام الشريحة الزمنية ولم تعثر وحدة المعالجة المركزية على عملية أو مؤشر ترابط جاهزة ، تابع استبدال مؤشر ترابط الخمول بوحدة المعالجة المركزية. في هذا الوقت ، سيستمر الخمول في حظر نفسه ثم البدء في تكرار عملية الجدولة أعلاه.
// 空载任务
static void idle ( void * arg ) {
while ( 1 ) {
thread_block ( TASK_BLOCKED );
asm volatile ( "sti; hlt" : : : "memory" );
}
}شوكة العملية
نسخ شوكة العملية أولاً من PCB للعملية الحالية ، ثم قم بإنشاء جدول صفحة جديد من خلال صورة نقطية تجمع افتراضية للعملية الحالية. مراسلات العنوان الافتراضي هي نفسها كما في العملية الأصلية. أخيرًا ، يتم تزوير موقع المقاطعة ويتم إضافة عملية الطفل إلى قائمة انتظار الجدولة وانتظر تنفيذ الجدولة. في موقع المقاطعة المزور ، يتم تعديل EAX في PCB لعملية الطفل إلى 0 ، مما يعني أن قيمة إرجاع الشوكة هي 0 في العملية الجديدة ، بينما يظل EAX في PCB في العملية الأصل دون تغيير ، تمثل PID لعملية الطفل. تعود عملية الوالدين من خلال نهاية استدعاء النظام ، بينما تعود عملية الطفل مباشرة من خلال وظيفة خروج المقاطعة.
عملية exec
يقوم تنفيذ EXEC أولاً بتحميل ملف ELF من القرص إلى الذاكرة ، ثم يغير اسم العملية في PCB من العملية الحالية ، ويضع المعلمات المطلوبة من قبل العملية التي سيتم تنفيذها في السجل المتفق عليها ، ويعدل EIP إلى نقطة دخول ELF ، وتزوير موقع المقاطعة ، وتنفيذ العملية الجديدة على الفور عن طريق استدعاء وظيفة Exit exit مباشرة.
من بينها ، يتم تنفيذ نقطة دخول ELF من خلال تنفيذ CRT بسيط للغاية ، والذي يعطي إدخال _start ويدفع سجلات المعلمة المتفق عليها إلى المكدس 3 على مستوى ، ويستدعي الوظيفة الرئيسية للأمر الخارجي لتحقيق معلمة تمرير.
[bits 32]
extern main
extern exit
; 这是一个简易版的CRT
; 如果链接时候ld不指定-e main的话,那ld默认会使用_start来充当入口
; 这里的_start的简陋实现,充当了exec调用的进程从伪造的中断中返回时的入口地址
; 通过这个_start, 压入了在execv中存放用户进程参数的两个寄存器。然后call 用户进程main来实现了向用户进程传递参数
section .text
global _start
_start:
;下面这两个要和 execv 中 load 之后指定的寄存器一致
push ebx ;压入 argv
push ecx ;压入 argc
call main
; 压入main的返回值
push eax
call exit ; 不再返回,直接调度别的进程了,这个进程直接被回收了العملية انتظر
بعد شوكة وتنفيذ أمر محلي ، حتى لا تظهر ، يجب أن تنتهي عملية الوالدين في عملية Wait Child المحلية.
يتمثل التنفيذ هنا في إدخال مكالمة SYS_WAIT System ، وتجتاز قائمة انتظار العملية بأكملها ، والعثور على العملية التي تكون عملية الوالدين هي حالتها المعلقة الخاصة بها ، ثم الحصول على قيمة الإرجاع في PCB ، وقم بإعادة تدوير جداول PCB ودليل الصفحة ، وإزالتها من قائمة انتظار الجدولة. إذا لم يتم العثور على عملية الطفل المعلقة بعد اجتياز ، فقم بحظر نفسها وانتظر عملية الطفل للاستيقاظ.
خروج العملية
أثناء التنفيذ ، يتم لف الأوامر الخارجية بالفعل بواسطة CRT بسيط تم إنشاؤه بمفرده. سيحصل الأمر الرئيسي على الأمر الخارجي CRT Call البسيط على قيمة الإرجاع الخاصة به في النهاية ، ويمررها للخروج ، ثم استدعاء الخروج
يقوم التنفيذ هنا بشكل أساسي بثلاثة أشياء:
العملية بأكملها لتحميل الأوامر الخارجية وتنفيذها
أولاً ، يحتاج الأمر الخارجي إلى توفير وظيفة int main(int argc, char **argv) . عند الارتباط ، تحتاج إلى إحضار start.o CRT بسيط محلي الصنع ، وأخيراً كتابة الأوامر الخارجية التي تم تجميعها إلى نظام الملفات.
عندما يتم تنفيذ أمر خارجي ، تقوم العملية الحالية بشحن عملية ، و EXECV في العملية الجديدة ، وتنفيذ العملية الحالية ، وتنفيذ عنوان لقبول قيمة الإرجاع لعملية الطفل ، ثم تمنع وينتظر العملية الجديدة للعودة. تقوم العملية الجديدة بتحميل الأوامر الخارجية من نظام الملفات إلى الذاكرة في exevc ، وتغير المحتوى ذي الصلة في ثنائي الفينيل متعدد الكلور إلى معلومات الأوامر الخارجية ، ويعدل EIP في مكدس المقاطعة PCB إلى إدخال _Start الخاص بـ CRT (في هذا الوقت ، تم استبدال العملية الجديدة ودخولها إلى المدى المزيف intr_exit إلى المقاطع المزيفة ودخولها إلى المقاطع المزيفة ودخولها إلى المقاطع المزيفة و الأمر الخارجي. عندما ينتهي التنفيذ الرئيسي للأمر الخارجي ، يستدعي CRT الخروج من خلال قيمة الإرجاع الرئيسية ، وضع قيمة الإرجاع الرئيسية في sys_exit في الموضع المقابل للعملية PCB ، وقم بإعادة تدوير جميع الموارد باستثناء PCB وجدول دليل الصفحة ، ثم إيقاظ العملية الأصل وحظر عملية الطفل. بعد أن يتم إيقاظ العملية الأصل ، يحصل sys_wait من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من ثنائي الفينيل متعدد الكلور من PCB من ثنائي الفينيل متعدد الكلور من PCB ، وتنظيف الجدول الدليل للصفحة لعملية الطفل. في هذه المرحلة ، تم تنفيذ عملية الطفل وإعادة تدويرها بالكامل.
يقلد تطبيق نظام الملفات إنود الأنظمة الشبيهة بـ UNIX
يحد القسم من عدد inodes 4096. تعمل وحدة المعالجة المركزية على القرص الصلب وفقًا لحجم الكتلة (الكتلة) ، ويتم تعيين كتلة واحدة على قطاع ، مع 512 بايت.
يدعم Inode 12 كتلة مباشرة وجدول واحد غير مباشر من المستوى الأول. كتلة واحدة هي 512 بايت في قطاع ، لذلك يدعم ملف واحد ما يصل إلى 140 * 512 بايت.
بنية inode

تخطيط نظام الملفات

المراسلات بين واصف الملف و inode

يعتمد تنفيذ خط الأنابيب على بنية الملف في نظام الملفات. جوهرها هو استبدال inode الذي يجب أن تتوافق بنية الملف في الأصل مع مساحة المخزن المؤقت الحلقة في مساحة kernel.
// 因为管道也是当作文件来对待,因此file结构体在针对真实文件和管道是有不同的意义
struct file {
// 文件操作的偏移指针, 当是管道是表示管道打开的次数
uint32_t fd_pos ;
// 文件的操作标志,当是管道是一个固定值0xFFFF
uint32_t fd_flag ;
// 对应的inode指针,当是管道时指向管道的环形缓冲区
struct inode * fd_inode ;
}; نظرًا لمشاركة مساحة kernel ، يمكن تحقيق التواصل بين عمليات مختلفة من خلال خطوط الأنابيب القراءة والكتابة. يتم تغليف قراءة وكتابة خط الأنابيب في sys_write و sys_read ، لذلك لا يوجد فرق بين تشغيل خط الأنابيب وتشغيل الملفات العادية.
يتمثل جوهر إعادة التوجيه في تغيير عنوان جدول الوصف العالمي المقابل في جدول واصفات ملف PCB ، ثم يتم توجيه تشغيل واصف الملف المقابل إلى الملف الجديد.
تنفيذ شخصية خط الأنابيب | في الصدفة يتم تحقيقها عن طريق إعادة توجيه المدخلات القياسية والإخراج القياسي إلى خط الأنابيب.
int32_t sys_read ( int32_t fd , void * buf , uint32_t count ) {
if ( fd == stdin_no ) {
if ( is_pipe ( fd )) {
// 从已经重定向好管道中读
ret = pipe_read ( fd , buf , count );
} else {
// 从键盘获取输入
}
} else if ( is_pipe ( fd )) {
// 读管道
ret = pipe_read ( fd , buf , count );
} else {
// 读取普通文件
}
return ret ;
}
int32_t sys_write ( int32_t fd , const void * buf , uint32_t count ) {
if ( fd == stdout_no ) {
if ( is_pipe ( fd )) {
// 向已经重定向好管道中写入
return pipe_write ( fd , buf , count );
} else {
// 向控制台输出内容
}
} else if ( is_pipe ( fd )) {
// 写管道
return pipe_write ( fd , buf , count );
} else {
// 向普通文件写入
}
}