مدخل إلى أنظمة التشغيل الفصل الثامن: تعدد المهام (Multitasking) في الحواسيب


Ola Abbas

يتضمن المعالج نوى متعددة في العديد من الحواسيب الحالية وهذا يعني أنه يستطيع تشغيل عدة عمليات في نفس الوقت، وكل نواةٍ لديها القدرة على القيام بتعدد المهام (multitasking) أي يمكنها التبديل من عملية لعمليةٍ أخرى بسرعة، وبذلك تخلق وهمًا بوجود عدة عمليات مُشغَّلة في الوقت ذاته. يسمى جزء نظام التشغيل الذي يطبّق تعدد المهام بالنواة (kernel) وهي الجزء الأعمق في نظام التشغيل وتكون محاطةً بالصدفة (shell) سواء كان نظام تشغيل يشبه الجوزة (nut) أو البذرة (seed)، فالنواة (kernel) هي المستوى الأدنى من البرمجيات (software) في نظام التشغيل وتكون هذه النواة محاطةً بطبقات أخرى متعددة، وإحدى هذه الطبقات واجهةٌ (interface) تسمى صدفة (shell) حيث تلاحظ أن الاختصاصيين في علوم الحاسوب يحبون الاستعارات (metaphors).

عمل النواة الأساسي هو معالجة المقاطعات، والمقاطعة هي الحدث الذي يوقِف دورة التعليمة (instruction cycle) القياسية ويسبب قفز تدفق التنفيذ (flow of execution) إلى جزءٍ خاص من الشيفرة يدعى معالج المقاطعة (interrupt handler). للمقاطعة نوعان هما: مقاطعة عتادية (hardware interrupt) ومقاطعة برمجية (software interrupt)، حيث تحدث المقاطعة العتادية (hardware interrupt) عندما يرسل جهازٌ ما إشارات إلى المعالج مثل تسبُّب واجهة الشبكة (network interface) بحدوث مقاطعة عند وصول حزمة بيانات (packet of data) أو مثل المقاطعة التي يسببها القرص الصلب (disk drive) عند اكتمال عملية نقل البيانات، وتحوي معظم الأنظمة مؤقتات (timers) تسبِّب مقاطعات عند الفواصل الزمنية المنتظمة (regular intervals) أو بعد انتهاء الوقت المستغرَق (elapsed time). تحدث المقاطعة البرمجية (software interrupt) بسبب برنامجٍ قيد التشغيل مثل عدم اكتمال تعليمةٍ لسببٍ ما، فتُنبّه هذه التعليمة مقاطعةً وبالتالي يعالج نظام التشغيل الشرط الخاص بالعملية المُقاطَعة، حيث تُعالَج أخطاء الأعداد العشرية (floating-point errors) مثل خطأ القسمة على صفر (division by zero) باستخدام المقاطعات.

ينشئ برنامج استدعاء نظام (system call) عندما يريد هذا البرنامج الوصول إلى جهاز عتادي، ويشبه استدعاءُ النظام استدعاءَ دالةٍ ولكن بدلًا من القفز إلى بداية الدالة ينفّذ استدعاءُ النظام تعليمةً خاصة، وتنبّهُ هذه التعليمة مقاطعةً مسببةً قفز تدفق التنفيذ إلى النواة، ثم تقرأ النواة معامِلات استدعاء النظام وتجري العمليات المطلوبة ثم تستأنف العملية المُقاطَعة.

حالة العتاد (Hardware state)

تتطلب معالجة المقاطعات تعاونًا بين العتاد والبرمجيات، حيث من الممكن وجود تعليمات متعددة قيد التشغيل ضمن المعالج (CPU) وبيانات مُخزَّنة في المسجلات بالإضافة إلى حالة عتادٍ (hardware state) أخرى عند حدوث مقاطعة. يكون العتاد عادةً مسؤولًا عن وصول المعالج إلى حالة الاستقرار (consistent state) فيجب أن تكتمل كل تعليمة أو أن تتصرف كأنها لم تبدأ من الأساس أي لا وجود لتعليمةٍ نصفها مكتملٌ على سبيل المثال، والعتاد مسؤولٌ أيضًا عن حفظ عدّاد البرنامج (program counter) ويختصر إلى PC الذي تستخدمه النواة (kernel) لتعرف من أين ستستأنف تنفيذ التعليمات، ثم يستلم معالج المقاطعة (interrupt handler) مسؤولية حفظ بقية حالة العتاد قبل أن يقوم بأي شيء آخر يعدّل حالة العتاد هذه ثم يستعيد حالة العتاد المحفوظة سابقًا قبل استئناف العملية المُقاطعَة، حيث يمكن اختصار سلسلة الأحداث السابقة كما يلي:

  1. يحفظ العتاد عدّاد البرنامج في مسجّلٍ خاص عند حدوث المقاطعة ثم يقفز العتاد إلى معالج المقاطعة المناسب.
  2. ثم يخزّن معالجُ المقاطعة عدادَ البرامج وحالة المسجل (status register) في الذاكرة إلى جانب محتويات مسجلات البيانات التي من المُخطَّط استخدامها.
  3. ثم يُشغّل معالج المقاطعة الشيفرة المطلوبة لمعالجة هذه المقاطعة.
  4. يستعيد معالج المقاطعة محتويات المسجلات التي خزّنها سابقًا ثم أخيرًا يستعيد عداد البرنامج للعملية المقاطعة وهذا يؤدّي إلى العودة إلى التعليمة المُقاطَعة.

إذا استخدِمت هذه الآلية بصورة صحيحة فلا يمكن أن تعلم العملية المقاطَعة بحدوث المقاطعة أبدًا إلّا إذا اكتشفت تغيّرًا في الوقت الفاصل بين التعليمات.

تبديل السياق (Context switching)

يمكن أن تكون معالجات المقاطعة سريعةً لأنها غير ملزمةٍ بحفظ كامل حالة العتاد وإنما تحفظ المسجلات التي من المخطط استخدامها فقط، ولكن لا تستأنف النواةُ العمليةَ المقاطعة دائمًا عند حدوث مقاطعةٍ ما وبالتالي يكون للنواة حرية التبديل إلى عملية أخرى، وتدعى هذه الآلية بتبديل السياق (context switch). لا تعلم النواة أيّ مسجلات ستستخدمها العملية لذلك يجب أن تحفظ كل المسجلات، ويجب على النواة تصفير البيانات المخزنة في وحدة إدارة الذاكرة (memory management unit) عند التبديل إلى عملية جديدة، حيث يمكن أن يستغرق تحميل بيانات العملية الجديدة إلى الذاكرة المخبئية بعض الوقت بعد تبديل السياق إليها لذلك يكون تبديل السياق بطيئًا نسبيًا فقد يستغرق آلاف الدورات أو عدة ميكرو ثانية. يُسمَح لكل عملية في نظام متعدد المهام أن تُشغَّل لفترة زمنية قصيرة تدعى بشريحة زمنية (time slice) أو حصّة (quantum)، وتضبط النواة مؤقت العتاد (hardware timer) خلال عملية تبديل السياق، وهذا يسبب حدوث مقاطعة عند نهاية الشريحة الزمنية، وبالتالي تستطيع النواة عند حدوث مقاطعةٍ التبديلَ إلى عملية أخرى أو السماح للعملية المقاطَعة أن تستأنف عملها، وجزء نظام التشغيل الذي يقرّر اختيار أحد هذين الخيارين هو المجدول (scheduler).

دورة حياة العملية (The process life cycle)

يخصص نظام التشغيل للعملية عند إنشائها بنية بيانات تتضمن معلومات عن هذه العملية وتدعى بينة البيانات هذه بكتلة تحكم العملية (process control block) وتختصر إلى PCB التي تتتبّع حالة العملية (process state)، ويكون للعملية أربع حالات هي:

  • التنفيذ (Running): عند تنفيذ العملية ضمن النواة (core).
  • الاستعداد (Ready): عندما تكون العملية جاهزة للتنفيذ ولكنها لا تُنفَّذ ويجب عليها الانتظار لأن عدد العمليات القابلة للتنفيذ أكبر من عدد الأنوية (cores).
  • الإيقاف (Blocked): إذا كان غير ممكن أن تُنفَّذ العملية لأنها تنتظر حدثًا مستقبليًا مثل اتصال شبكة أو قراءة من القرص الصلب.
  • الاكتمال (Done): إذا اكتمل تنفيذ العملية ولكنها تملك معلومات حالة المغادرة (exit status information) التي لم تُقرَأ بعد.

الأحداث التي تسبب انتقال العملية من حالة إلى أخرى هي:

  • تُنشَأ العملية عندما ينفّذ البرنامج المُشغَّل استدعاء نظام مثل fork، حيث تصبح العملية المنشَأة أو الجديدة في نهاية استدعاء النظام في حالة الاستعداد ثم قد يستأنف المجدول العملية الأصلية التي تسمى العملية الأب (parent) أو يبتدئ المجدول العملية الجديدة التي تسمى العملية الابن (child).
  • تتغير حالة العملية من حالة الاستعداد إلى حالة التنفيذ عندما يبتدئها المجدول أو يستأنفها.
  • تتغير حالة العملية من حالة التنفيذ إلى الاستعداد عندما تُقاطَع العملية ويختار المجدول ألا يستأنفها.
  • إذا نفّذت العملية استدعاء النظام الذي لا يكتمل على الفور وإنما يحتاج وقتًا مثل الطلب من القرص الصلب فتصبح العملية بحالة الإيقاف وعندها يختار المجدول عمليةً أخرى لتنفيذها.
  • إذا اكتملت عمليةٌ ما مثل عملية طلب من القرص الصلب فإنها تسبب مقاطعة، ويحدد معالج المقاطعة العملية المنتظرة لعملية الطلب هذه ويبدّل حالتها من حالة الإيقاف إلى الاستعداد ثم يختار المجدول أن يستأنفها أم لا.
  • إذا استدعت العملية الدالة exit فإن معالج المقاطعة يخزّن شيفرة المغادرة (exit code) في كتلة تحكم العملية (PCB) ثم يغير حالة العملية إلى حالة الاكتمال.

الجدولة (Scheduling)

من الممكن وجود مئات العمليات على الحاسوب ولكن معظمها في حالة إيقاف (blocked) ويكون عدد قليل منها في حالة استعداد أو تنفيذ، والمجدول هو الذي يقرر أية عمليةٍ تبدأ التنفيذ أو تستأنف عملها عند حدوث مقاطعة. هدف المجدول الرئيسي هو تقليل وقت الاستجابة (response time) قدر الإمكان على الحاسوب المحمول (laptop) أو على محطة العمل (workstation)، حيث يجب أن يستجيب الحاسوب بسرعة لإجراءات المستخدم. وقت الاستجابة مهمٌ أيضًا في المخدمات (servers) بالإضافة إلى أنه يجب على المجدول زيادة الإنتاجية (throughput) والتي هي عدد الطلبات المنجزة خلال واحدة الزمن، وفي الحقيقة لا يملك المجدول معلومات كثيرة عمّا تفعله العمليات لذلك تعتمد قراراته في اختيار العملية على عدة استنتاجات هي:

  • يمكن أن تكون العمليات محدودةً بموارد مختلفة، فالعملية التي تقوم بعمليات حسابية كثيرة محدودةٌ بالمعالج (CPU-bound) أي أن وقت تشغيل هذه العملية يعتمد على كمية الوقت الذي تأخذه من وقت المعالج، أما العملية التي تقرأ بيانات من الشبكة أو من القرص الصلب فتكون محدودةً بعمليات الإدخال والإخراج (I/O-bound) أي تكون هذه العملية أسرع إذا كان إدخال أو إخراج البيانات أسرع، ولكنها لن تنفّذ أسرع إذا كان وقت المعالج الخاص بها أكبر، ويمكن أن تكون العملية التي تتفاعل مع المستخدم في حالة الإيقاف حيث ستبقى منتظرةً إجراءات المستخدم معظم الوقت. يصنّف نظام التشغيل العمليات أحيانًا تبعًا لسلوكها السابق ويجدولها بناءً على ذلك، فمن المحتمل أن تنفّذ العملية التفاعلية (interactive process) مباشرةً عندما تنتهي من حالة الإيقاف لأن المستخدم ينتظر ردًا منها، بينما تكون العملية المحدودة بالمعالج (CPU-bound) والتي ما زالت تنفّذ منذ مدة طويلة أقلَّ حساسيةً لعامل الوقت.
  • إذا كان من المحتمل أن تُشغَّل العملية لفترة قصيرة ثم تطلب شيئًا يجعلها في حالة إيقاف، فيمكن أن تُشغَّل على الفور لسببين هما: (1) إذا استغرق الطلب بعض الوقت لإكماله فيجب أن يبدأ في أقرب وقت ممكن، و (2) من الأفضل أن تنتظر عملية ذات وقت تنفيذ طويل لفترةٍ قصيرة وليس العكس، بصورة مشابهة افترض أنك تصنع فطيرة تفاح، حيث يستغرق تحضير الطبقة الخارجية للفطيرة 5 دقائق ولكن يجب تركها لتبرد لمدة نصف ساعة ويستغرق تحضير حشوة الفطيرة 20 دقيقة، فإذا حضّرت الطبقة الخارجية أولًا فيمكنك تحضير الحشوة ريثما تبرد الطبقة الخارجية وبالتالي تنهي تحضير الفطيرة خلال 35 دقيقة، أما إذا حضّرت الحشوة أولًا فيستغرق تحضير الفطيرة 55 دقيقة.

تستخدم معظم المجدولات بعض نماذج الجدولة المعتمدة على الأولوية (priority-based scheduling)، حيث يكون لكل عملية أولوية تزيد أو تنقص خلال الوقت ويختار المجدول العملية القابلة للتنفيذ ذات الأولوية العليا، وهناك عدة عوامل لتحديد أولوية العملية هي:

  • تبدأ العملية عادةً برقم أولوية عالٍ نسبيًا لذلك تبدأ التنفيذ بسرعة.
  • إذا طلبت العملية شيئًا ما جعلها في حالة إيقاف قبل انتهاء شريحتها الزمنية ضمن المعالج فمن المحتمل أن تكون عملية تفاعلية مع المستخدم (interactive) أو عملية محدودة بعمليات الإدخال والإخراج (I/O-bound) لذلك يجب أن تصبح أولويتها أعلى.
  • إذا انتهت الشريحة الزمنية الخاصة بالعملية ضمن المعالج ولم ينتهِ تنفيذ هذه العملية فمن المحتمل أن تكون عملية ذات وقت تنفيذ طويل (long-running) ومحدودة بالمعالج (CPU-bound) لذلك يجب أن تصبح أولويتها أقل.
  • إذا توقفت مهمةٌ لمدة طويلة ثم أصبحت بحالة استعداد فيجب أن تحصل على زيادة في الأولوية لتتمكن من الاستجابة على الشيء الذي انتظرته.
  • إذا توقفت العملية A بسبب انتظارها للعملية B وهاتان العمليتان مرتبطتان عن طريق أنبوب (pipe) مثلًا فيجب أن تصبح أولوية العملية B أعلى.
  • يسمح استدعاء النظام nice للعملية بتقليل أولويتها (ولا تسمح بزيادتها) مما يسمح للمبرمجين بتمرير معلومات محددة إلى المجدول.

لا تؤثر خوازرميات الجدولة (scheduling algorithms) كثيرًا على أداء معظم أنظمة التشغيل التي تعمل بأحمال (workloads) عادية فسياسات الجدولة (scheduling policies) البسيطة جيدة كفاية لهذه الأنظمة.

الجدولة في الوقت الحقيقي (Real-time scheduling)

الجدولة مهمةٌ جدًا بالنسبة للبرامج التي تتفاعل مع العالم الحقيقي، فقد يضطر البرنامج الذي يقرأ بيانات من الحسّاسات (sensors) والذي يتحكم بالمحركات إلى إكمال المهام المتكررة بالحد الأدنى من التكرار وأن يتفاعل مع الأحداث الخارجية بالحد الأقصى من وقت الاستجابة. يُعبّر عن هذه المتطلبات بالمهام التي يجب إكمالها قبل المواعيد النهائية (deadlines). تدعى جدولة المهام من أجل الوفاء بالمواعيد النهائية بالجدولة في الوقت الحقيقي (real-time scheduling)، ويمكن تعديل أنظمة التشغيل التي تستخدم للأغراض العامة مثل Linux لتتعامل مع الجدولة في الوقت الحقيقي بالنسبة لبعض التطبيقات، وقد تشمل هذه التعديلات ما يلي:

  • توفير واجهات برمجة تطبيقات (APIs) أثرى للتحكم في أولويات المهام.
  • تعديل المجدول لضمان تشغيل العملية ذات الأولوية الأعلى خلال مدة زمنية محددة.
  • إعادة تنظيم معالجات المقاطعة لضمان أكبر وقت لاكتمال العمليات.
  • تعديل الأقفال (locks) وآليات المزامنة الأخرى (synchronization mechanisms) (سنتطرق إليها لاحقًا) للسماح لمهمة ذات أولوية عالية أن تسبق مهمة ذات أولوية أقل.
  • اختيار تطبيق تخصيص الذاكرة الديناميكي الذي يضمن أكبر وقت لاكتمال العمليات.

توفر أنظمة التشغيل في الوقت الحقيقي (real-time operating systems) إمكانيات متخصصة بالنسبة للتطبيقات الأكثر طلبًا وخاصة في المجالات التي تمثل فيها الاستجابة في الوقت الحقيقي مسألةَ حياة أو موت، وتكون هذه الأنظمة ذات تصميم أبسط بكثير من أنظمة التشغيل ذات الأغراض العامة.

ترجمة -وبتصرّف- للفصل Multitasking من كتاب Think OS A Brief Introduction to Operating Systems





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن