⏱️ المدير التنفيذي: تشريح sched/mod.rs (المجدول)
كيف يتمكن الحاسوب من تشغيل أغنية، وتحميل ملف، وتصفح الإنترنت في نفس اللحظة رغم أن لديه معالجاً واحداً فقط؟ السر هنا في المجدول (Scheduler)؛ الديكتاتور العادل الذي يوزع أجزاءً من الثانية على البرامج دون أن تشعر!
1. المصفوفة المقدسة (Task List)
النواة تحتفظ بمصفوفة عالمية مسجل فيها كل البرامج التي تعمل حالياً:
rust
static mut TASKS: [Option<Task>; MAX_TASKS] = [None, None, ...];
static mut CURRENT_TASK: usize = 0; // من الذي يعمل الآن؟2. خوارزمية التبديل العادل (Round-Robin)
عندما يطلق المؤقت الزمني نبضة (tick) كل ملي ثانية، يستيقظ المجدول فوراً وينفذ هذه الخوارزمية:
- يبحث عن البرنامج الحالي، ويحفظ جميع مسجلاته (كي لا ينسى أين وصل).
- يبحث في المصفوفة عن البرنامج التالي الذي يملك حالة
TaskState::Ready(جاهز للعمل). - يطلب من المعالج تحميل مسجلات البرنامج الجديد، وتغيير جدول ذاكرته (
CR3) ليصبح هو الحاكم الجديد للمعالج!
rust
// دالة الـ Context Switch (جزؤها الأكبر بالأسمبلي لتبديل المسجلات عتادياً)
unsafe fn switch_context(old_ctx: *mut CpuContext, new_ctx: *const CpuContext);3. ولادة البرامج (spawn_from_elf)
عندما تطلب تشغيل vfs_server، يقوم المجدول بصناعة "هيكل" للبرنامج:
rust
pub unsafe fn spawn_from_elf(elf_data: &[u8]) -> Result<u64, &'static str> {
// 1. يحلل الـ ELF لمعرفة موقع الكود
// 2. يصنع CR3 (جدول ذاكرة) معزول للبرنامج عبر VMM
// 3. يخصص مساحة للمكدس (Stack)
// 4. ينشئ كائن Task، يضعه في المصفوفة كـ Ready، ويعيد الـ PID الخاص به!
}4. منح الصلاحيات (السر الأمني)
البرامج المعزولة لا يمكنها التحدث، إلا إذا قرر "المدير التنفيذي" إيصالها ببعضها:
rust
pub unsafe fn kernel_grant_port_pair(slot_a: usize, slot_b: usize) {
// هذه الدالة تبحث عن "منفذ IPC" فارغ في A وتربطه بـ B، والعكس.
// وهي دالة لا يمكن استدعاؤها إلا من داخل النواة Ring 0!
}