sched(7)

الاسم
sched - نظرة عامة على جدولة وحدة المعالجة المركزية

الوصف
منذ لينكس 2.6.23، المُجدول المبدئي هو CFS، "المُجدول العادل تمامًا". حل مُجدول CFS محل المُجدول السابق "O(1)".

  ملخص واجهة برمجة التطبيقات
يوفر لينكس استدعاءات النظام التالية للتحكم في سلوك جدولة وحدة المعالجة المركزية، وسياسة، وأولوية العمليات (أو، بشكل أدق، الخيوط).

nice(2)
    تعيين قيمة nice جديدة للخيط المستدعي، وإرجاع قيمة nice الجديدة.

getpriority(2)
    إرجاع قيمة nice لخيط، مجموعة عمليات، أو مجموعة الخيوط المملوكة لمستخدم محدد.

setpriority(2)
    تعيين قيمة nice لخيط، مجموعة عمليات، أو مجموعة الخيوط المملوكة لمستخدم محدد.

sched_setscheduler(2)
    تعيين سياسة الجدولة ومعاملات خيط محدد.

sched_getscheduler(2)
    إرجاع سياسة الجدولة لخيط محدد.

sched_setparam(2)
    تعيين معاملات الجدولة لخيط محدد.

sched_getparam(2)
    جلب معاملات الجدولة لخيط محدد.

sched_get_priority_max(2)
    إرجاع الحد الأقصى للأولوية المتاحة في سياسة جدولة محددة.

sched_get_priority_min(2)
    إرجاع الحد الأدنى للأولوية المتاحة في سياسة جدولة محددة.

sched_rr_get_interval(2)
    جلب الكم المستخدم للخيوط المُجدولة تحت سياسة الجدولة "الدائرية".

sched_yield(2)
    جعل المستدعي يتخلى عن وحدة المعالجة المركزية، بحيث يُنفذ خيط آخر.

sched_setaffinity(2)
    (خاص بلينكس) تعيين تقارب وحدة المعالجة المركزية لخيط محدد.

sched_getaffinity(2)
    (خاص بلينكس) الحصول على تقارب وحدة المعالجة المركزية لخيط محدد.

sched_setattr(2)
    تعيين سياسة الجدولة ومعاملات خيط محدد. يوفر استدعاء النظام هذا (خاص بلينكس) مجموعة شاملة من وظائف sched_setscheduler(2) و sched_setparam(2).

sched_getattr(2)
    جلب سياسة الجدولة ومعاملات خيط محدد. يوفر استدعاء النظام هذا (خاص بلينكس) مجموعة شاملة من وظائف sched_getscheduler(2) و sched_getparam(2).

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

بالنسبة للخيوط المُجدولة تحت إحدى سياسات الجدولة العادية (SCHED_OTHER، SCHED_IDLE، SCHED_BATCH)، لا يُستخدم sched_priority في قرارات الجدولة (يجب تحديده كـ 0).

العمليات المُجدولة تحت إحدى سياسات الوقت الحقيقي (SCHED_FIFO، SCHED_RR) لها قيمة sched_priority في النطاق من 1 (منخفض) إلى 99 (مرتفع). (كما تشير الأرقام، خيوط الوقت الحقيقي لها دائمًا أولوية أعلى من الخيوط العادية.) لاحظ جيدًا: يتطلب POSIX.1 من التطبيق دعم 32 مستوى أولوية متميزة فقط كحد أدنى لسياسات الوقت الحقيقي، وتوفر بعض الأنظمة هذا الحد الأدنى فقط. يجب على البرامج المحمولة استخدام sched_get_priority_min(2) و sched_get_priority_max(2) لإيجاد نطاق الأولويات المدعومة لسياسة معينة.

مفاهيميًا، يحتفظ المُجدول بقائمة من الخيوط القابلة للتشغيل لكل قيمة sched_priority محتملة. لتحديد أي خيط يعمل بعد ذلك، يبحث المُجدول عن القائمة غير الفارغة ذات الأولوية الثابتة الأعلى ويختار الخيط في رأس هذه القائمة.

تحدد سياسة الجدولة للخيط أين سيُدرج في قائمة الخيوط ذات الأولوية الثابتة المتساوية وكيف سيتحرك داخل هذه القائمة.

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

  SCHED_FIFO: جدولة الوارد أولاً صادر أولاً
يمكن استخدام SCHED_FIFO فقط مع أولويات ثابتة أعلى من 0، مما يعني أنه عندما يصبح خيط SCHED_FIFO قابلاً للتشغيل، فسيستبق فورًا أي خيط SCHED_OTHER أو SCHED_BATCH أو SCHED_IDLE قيد التشغيل حاليًا. SCHED_FIFO هي خوارزمية جدولة بسيطة بدون تقطيع زمني. بالنسبة للخيوط المجدولة تحت سياسة SCHED_FIFO، تنطبق القواعد التالية:

•   يبقى خيط SCHED_FIFO الجاري المسبوق بواسطة خيط آخر ذي أولوية أعلى في رأس القائمة لأوليته ويستأنف التنفيذ بمجرد حظر جميع الخيوط ذات الأولوية الأعلى مرة أخرى.

•   عندما يصبح خيط SCHED_FIFO المحظور قابلاً للتشغيل، يُدرج في نهاية القائمة لأوليته.

•   إذا غيّر استدعاء لـ sched_setscheduler(2) أو sched_setparam(2) أو sched_setattr(2) أو pthread_setschedparam(3) أو pthread_setschedprio(3) أولوية خيط SCHED_FIFO الجاري أو القابل للتشغيل المُعرّف بواسطة pid، فإن التأثير على موضع الخيط في القائمة يعتمد على اتجاه التغيير في أولوية الخيط:

    (أ) إذا رُفعت أولوية الخيط، يوضع في نهاية القائمة لأوليته الجديدة. ونتيجة لذلك، قد يستبق خيطًا قيد التشغيل حاليًا بنفس الأولوية.

    (ب) إذا لم تتغير أولوية الخيط، يبقى موضعه في قائمة التشغيل دون تغيير.

    (ج) إذا خُفضت أولوية الخيط، يوضع في مقدمة القائمة لأوليته الجديدة.

    وفقًا لـ POSIX.1-2008، يجب أن تؤدي التغييرات في أولوية الخيط (أو سياسته) باستخدام أي آلية غير pthread_setschedprio(3) إلى وضع الخيط في نهاية القائمة لأوليته.

•   يوضع الخيط الذي يستدعي sched_yield(2) في نهاية القائمة.

لن تنقل أي أحداث أخرى خيطًا مجدولاً تحت سياسة SCHED_FIFO في قائمة انتظار الخيوط القابلة للتشغيل ذات الأولوية الثابتة المتساوية.

يعمل خيط SCHED_FIFO حتى يُحظر بواسطة طلب إدخال/إخراج، أو يُسبق بواسطة خيط ذي أولوية أعلى، أو يستدعي sched_yield(2).

  SCHED_RR: جدولة دائرية
SCHED_RR هي تحسين بسيط لـ SCHED_FIFO. كل ما وُصف أعلاه لـ SCHED_FIFO ينطبق أيضًا على SCHED_RR، باستثناء أن كل خيط يُسمح له بالتشغيل فقط لكم زمني أقصى. إذا كان خيط SCHED_RR قيد التشغيل لفترة زمنية تساوي أو تزيد عن الكم الزمني، فسيوضع في نهاية القائمة لأوليته. يكمل خيط SCHED_RR المسبوق بواسطة خيط ذي أولوية أعلى ثم استأنف التنفيذ كخيط جارٍ الجزء غير المنقضي من كمه الزمني الدائري. يمكن استرداد طول الكم الزمني باستخدام sched_rr_get_interval(2).

  SCHED_DEADLINE: جدولة الموعد النهائي لنموذج المهمة المتفرقة
منذ لينكس 3.14، يوفر لينكس سياسة جدولة الموعد النهائي (SCHED_DEADLINE). تُنفذ هذه السياسة حاليًا باستخدام GEDF (الأولوية العالمية للموعد النهائي الأقرب) بالتزامن مع CBS (خادم النطاق الترددي الثابت). لتعيين هذه السياسة والسمات المرتبطة بها وجلبها، يجب استخدام استدعاءات النظام الخاصة بلينكس sched_setattr(2) و sched_getattr(2).

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

يوضح الرسم البياني التالي هذه المصطلحات:

    arrival/wakeup                    absolute deadline
         |    start time                    |
         |        |                         |
         v        v                         v
    -----x--------xooooooooooooooooo--------x--------x---
                  |<- comp. time ->|
         |<------- relative deadline ------>|
         |<-------------- period ------------------->|

عند تعيين سياسة SCHED_DEADLINE لخيط باستخدام sched_setattr(2)، يمكن تحديد ثلاث معاملات: Runtime (وقت التشغيل)، و Deadline (الموعد النهائي)، و Period (الفترة). لا تتوافق هذه المعاملات بالضرورة مع المصطلحات المذكورة أعلاه: الممارسة المعتادة هي تعيين Runtime إلى شيء أكبر من متوسط وقت الحساب (أو وقت التنفيذ في أسوأ الحالات للمهام في الوقت الفعلي الصارم)، و Deadline إلى الموعد النهائي النسبي، و Period إلى فترة المهمة. وبالتالي، بالنسبة لجدولة SCHED_DEADLINE، لدينا:

    arrival/wakeup                    absolute deadline
         |    start time                    |
         |        |                         |
         v        v                         v
    -----x--------xooooooooooooooooo--------x--------x---
                  |<-- Runtime ------->|
         |<----------- Deadline ----------->|
         |<-------------- Period ------------------->|

تتوافق معاملات جدولة الموعد النهائي الثلاثة مع حقول sched_runtime و sched_deadline و sched_period في بنية sched_attr؛ انظر sched_setattr(2). تعبر هذه الحقول عن القيم بالنانو ثانية. إذا حُدد sched_period كـ 0، فسيُجعل مساويًا لـ sched_deadline.

تتطلب النواة أن:

    sched_runtime <= sched_deadline <= sched_period

بالإضافة إلى ذلك، في ظل التطبيق الحالي، يجب أن تكون جميع قيم المعاملات على الأقل 1024 (أي ما يزيد قليلاً عن ميكروثانية واحدة، وهي دقة التطبيق)، وأقل من 2^63. إذا فشل أي من هذه الفحوصات، يفشل sched_setattr(2) مع الخطأ EINVAL.

يضمن CBS عدم التداخل بين المهام، عن طريق خنق الخيوط التي تحاول تجاوز وقت التشغيل المحدد لها.

لضمان ضمانات جدولة المواعيد النهائية، يجب على النواة منع المواقف التي تكون فيها مجموعة خيوط SCHED_DEADLINE غير قابلة للتطبيق (قابلة للجدولة) ضمن القيود المعطاة. وبالتالي، تقوم النواة بإجراء اختبار قبول عند تعيين أو تغيير سياسة وسمات SCHED_DEADLINE. يحسب اختبار القبول هذا ما إذا كان التغيير قابلاً للتطبيق؛ إذا لم يكن كذلك، يفشل sched_setattr(2) مع الخطأ EBUSY.

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

من أجل الوفاء بالضمانات التي تُمنح عند قبول خيط في سياسة SCHED_DEADLINE، تكون خيوط SCHED_DEADLINE هي الخيوط ذات الأولوية الأعلى (القابلة للتحكم من قبل المستخدم) في النظام؛ إذا كان أي خيط SCHED_DEADLINE قابلاً للتشغيل، فإنه يسبق أي خيط مجدول تحت إحدى السياسات الأخرى.

يفشل استدعاء fork(2) بواسطة خيط مجدول تحت سياسة SCHED_DEADLINE مع الخطأ EAGAIN، ما لم يكن للخيط علامة إعادة التعيين عند fork مضبوطة (انظر أدناه).

خيط SCHED_DEADLINE الذي يستدعي sched_yield(2) يتخلى عن المهمة الحالية وينتظر بدء فترة جديدة.

  SCHED_OTHER: جدولة مشاركة الوقت الافتراضية في لينكس
يمكن استخدام SCHED_OTHER فقط بأولوية ثابتة 0 (أي أن الخيوط تحت سياسات الوقت الحقيقي لها دائماً أولوية على عمليات SCHED_OTHER). SCHED_OTHER هو المجدول القياسي لمشاركة الوقت في لينكس والمخصص لجميع الخيوط التي لا تتطلب آليات الوقت الحقيقي الخاصة.

اُختير الخيط للتشغيل من قائمة الأولوية الثابتة 0 بناءً على أولوية ديناميكية تُحدد فقط داخل هذه القائمة. تعتمد الأولوية الديناميكية على قيمة nice (انظر أدناه) وتُزاد لكل كمية زمنية يكون الخيط جاهزاً للتشغيل فيها، ولكن يُمنع من التشغيل بواسطة المجدول. يضمن هذا تقدماً عادلاً بين جميع خيوط SCHED_OTHER.

في شفرة مصدر نواة لينكس، تُسمى سياسة SCHED_OTHER فعلياً SCHED_NORMAL.

  قيمة nice
قيمة nice هي سمة يمكن استخدامها للتأثير على مجدول وحدة المعالجة المركزية لتفضيل أو عدم تفضيل عملية في قرارات الجدولة. تؤثر على جدولة عمليات SCHED_OTHER و SCHED_BATCH (انظر أدناه). يمكن تعديل قيمة nice باستخدام nice(2) أو setpriority(2) أو sched_setattr(2).

وفقاً لـ POSIX.1، قيمة nice هي سمة لكل عملية؛ أي أن الخيوط في عملية يجب أن تشارك قيمة nice. ومع ذلك، في لينكس، قيمة nice هي سمة لكل خيط: قد يكون للخيوط المختلفة في نفس العملية قيم nice مختلفة.

يختلف نطاق قيمة nice عبر أنظمة UNIX. في لينكس الحديث، النطاق هو -20 (أولوية عالية) إلى +19 (أولوية منخفضة). في بعض الأنظمة الأخرى، النطاق هو -20..20. كانت نوى لينكس المبكرة جداً (قبل لينكس 2.0) تحتوي على النطاق -infinity..15.

تختلف درجة تأثير قيمة nice على الجدولة النسبية لعمليات SCHED_OTHER أيضًا عبر أنظمة UNIX وعبر إصدارات نواة لينكس.

مع ظهور مجدول CFS في لينكس 2.6.23، اعتمد لينكس خوارزمية تجعل الاختلافات النسبية في قيم nice ذات تأثير أقوى بكثير. في التطبيق الحالي، تؤدي كل وحدة اختلاف في قيم nice لعمليتين إلى عامل 1.25 في درجة تفضيل المجدول للعملية ذات الأولوية الأعلى. يتسبب هذا في أن قيم nice المنخفضة جداً (+19) توفر بالفعل القليل من وحدة المعالجة المركزية لعملية كلما كان هناك أي حمل آخر ذو أولوية أعلى على النظام، ويجعل قيم nice العالية (-20) توفر معظم وحدة المعالجة المركزية للتطبيقات التي تحتاجها (مثل بعض تطبيقات الصوت).

في لينكس، يمكن استخدام حد المورد RLIMIT_NICE لتحديد حد يمكن رفع قيمة nice لعملية غير مميزة إليه؛ انظر setrlimit(2) للتفاصيل.

لمزيد من التفاصيل حول قيمة nice، انظر الأقسام الفرعية حول ميزة autogroup وجدولة المجموعة، أدناه.

  SCHED_BATCH: جدولة عمليات الدفعات
(منذ لينكس 2.6.16.) يمكن استخدام SCHED_BATCH فقط بأولوية ثابتة 0. تشبه هذه السياسة SCHED_OTHER من حيث أنها تجدول الخيط وفقاً لأولوياته الديناميكية (المبنية على قيمة nice). الفرق هو أن هذه السياسة تجعل المجدول يفترض دائماً أن الخيط مكثف لوحدة المعالجة المركزية. وبالتالي، يطبق المجدول عقوبة جدولة صغيرة فيما يتعلق بسلوك الاستيقاظ، بحيث يكون هذا الخيط غير مفضل بشكل طفيف في قرارات الجدولة.

هذه السياسة مفيدة لأحمال العمل غير التفاعلية، ولكنها لا تريد خفض قيمة nice الخاصة بها، ولأحمال العمل التي تريد سياسة جدولة حتمية دون أن تسبب التفاعلية استباقات إضافية (بين مهام حمل العمل).

  SCHED_IDLE: جدولة وظائف ذات أولوية منخفضة جداً
(منذ لينكس 2.6.23.) يمكن استخدام SCHED_IDLE فقط بأولوية ثابتة 0؛ قيمة nice للعملية ليس لها تأثير على هذه السياسة.

هذه السياسة مخصصة لتشغيل الوظائف بأولوية منخفضة للغاية (أقل حتى من قيمة nice +19 مع سياسات SCHED_OTHER أو SCHED_BATCH).

  إعادة تعيين سياسة الجدولة للعمليات الفرعية
لكل خيط علم جدولة إعادة التعيين عند الاستنساخ. عند تعيين هذا العلم، لا ترث العمليات الفرعية المنشأة بواسطة fork(2) سياسات الجدولة المميزة. يمكن تعيين علم إعادة التعيين عند الاستنساخ بإحدى الطريقتين:

•   إجراء عملية OR للعلم SCHED_RESET_ON_FORK مع وسيط policy عند استدعاء sched_setscheduler(2) (منذ لينكس 2.6.32)؛ أو

•   تحديد العلم SCHED_FLAG_RESET_ON_FORK في attr.sched_flags عند استدعاء sched_setattr(2).

لاحظ أن الثوابت المستخدمة مع هاتين الواجهتين البرمجيتين لها أسماء مختلفة. يمكن استرداد حالة علم إعادة التعيين عند الاستنساخ بالمثل باستخدام sched_getscheduler(2) و sched_getattr(2).

ميزة إعادة التعيين عند الاستنساخ مخصصة لتطبيقات تشغيل الوسائط، ويمكن استخدامها لمنع التطبيقات من تجاوز حد المورد RLIMIT_RTTIME (انظر getrlimit(2)) عن طريق إنشاء عمليات فرعية متعددة.

بشكل أكثر دقة، إذا عُين علم إعادة التعيين عند الاستنساخ، تنطبق القواعد التالية على العمليات الفرعية المنشأة لاحقًا:

•   إذا كان للخيط المستدعي سياسة جدولة SCHED_FIFO أو SCHED_RR، يُعاد تعيين السياسة إلى SCHED_OTHER في العمليات الفرعية.

•   إذا كانت للعملية المستدعية قيمة nice سالبة، يُعاد تعيين قيمة nice إلى الصفر في العمليات الفرعية.

بعد تمكين علم إعادة التعيين عند الاستنساخ، يمكن إعادة تعيينه فقط إذا كان للخيط القدرة CAP_SYS_NICE. يُعطل هذا العلم في العمليات الفرعية المنشأة بواسطة fork(2).

  الامتيازات وحدود الموارد
قبل لينكس 2.6.12، فقط الخيوط المميزة (CAP_SYS_NICE) يمكنها تعيين أولوية ثابتة غير صفرية (أي تعيين سياسة جدولة زمن حقيقي). التغيير الوحيد الذي يمكن لخيط غير مميز القيام به هو تعيين سياسة SCHED_OTHER، ويمكن القيام بذلك فقط إذا تطابق معرف المستخدم الفعال للمستدعي مع معرف المستخدم الحقيقي أو الفعال للخيط الهدف (أي الخيط المحدد بواسطة pid) الذي يُغير سياسته.

يجب أن يكون الخيط مميزًا (CAP_SYS_NICE) لتعيين أو تعديل سياسة SCHED_DEADLINE.

منذ لينكس 2.6.12، يحدد حد المورد RLIMIT_RTPRIO سقفًا للأولوية الثابتة للخيط غير المميز لسياسات SCHED_RR و SCHED_FIFO. قواعد تغيير سياسة الجدولة والأولوية هي كما يلي:

•   إذا كان للخيط غير المميز حد لين RLIMIT_RTPRIO غير صفري، فيمكنه تغيير سياسة الجدولة والأولوية الخاصة به، مع مراعاة القيد بأنه لا يمكن تعيين الأولوية إلى قيمة أعلى من الحد الأقصى لأولويتها الحالية وحدها اللين RLIMIT_RTPRIO.

•   إذا كان الحد اللين RLIMIT_RTPRIO هو 0، فإن التغييرات المسموح بها الوحيدة هي خفض الأولوية، أو التبديل إلى سياسة غير زمن حقيقي.

•   مع مراعاة نفس القواعد، يمكن لخيط غير مميز آخر أيضًا إجراء هذه التغييرات، طالما أن معرف المستخدم الفعال للخيط الذي يقوم بالتغيير يطابق معرف المستخدم الحقيقي أو الفعال للخيط الهدف.

•   تنطبق قواعد خاصة على سياسة SCHED_IDLE. قبل لينكس 2.6.39، لا يمكن لخيط غير مميز يعمل تحت هذه السياسة تغيير سياسته، بغض النظر عن قيمة حد المورد RLIMIT_RTPRIO الخاص به. منذ لينكس 2.6.39، يمكن لخيط غير مميز التبديل إلى إما سياسة SCHED_BATCH أو SCHED_OTHER طالما أن قيمة nice الخاصة به تقع ضمن النطاق المسموح به بواسطة حد المورد RLIMIT_NICE الخاص به (انظر getrlimit(2)).

تتجاهل الخيوط المميزة (CAP_SYS_NICE) حد RLIMIT_RTPRIO؛ كما هو الحال مع النوى القديمة، يمكنها إجراء تغييرات عشوائية على سياسة الجدولة والأولوية. انظر getrlimit(2) لمزيد من المعلومات حول RLIMIT_RTPRIO.

  تحديد استخدام وحدة المعالجة المركزية للعمليات الزمن الحقيقي وذات الموعد النهائي
يمكن لحلقة لا نهائية غير محظورة في خيط مجدول تحت سياسة SCHED_FIFO أو SCHED_RR أو SCHED_DEADLINE أن تمنع جميع الخيوط الأخرى من الوصول إلى وحدة المعالجة المركزية إلى الأبد. قبل لينكس 2.6.25، كانت الطريقة الوحيدة لمنع عملية زمن حقيقي جامحة من تجميد النظام هي تشغيل (في وحدة التحكم) شل مجدول بأولوية ثابتة أعلى من التطبيق المختبر. يسمح هذا بقتل طارئ لتطبيقات الزمن الحقيقي المختبرة التي لا تحظر أو تنتهي كما هو متوقع.

منذ لينكس 2.6.25، هناك تقنيات أخرى للتعامل مع عمليات الزمن الحقيقي وذات الموعد النهائي الجامحة. إحداها هي استخدام حد المورد RLIMIT_RTTIME لتعيين سقف لوقت وحدة المعالجة المركزية الذي قد تستهلكه عملية زمن حقيقي. انظر getrlimit(2) للتفاصيل.

منذ لينكس 2.6.25، يوفر لينكس أيضًا ملفين /proc يمكن استخدامهما لحجز قدر معين من وقت وحدة المعالجة المركزية لاستخدامه بواسطة عمليات غير زمن حقيقي. يسمح حجز وقت وحدة المعالجة المركزية بهذه الطريقة بتخصيص بعض وقت وحدة المعالجة المركزية لـ (على سبيل المثال) شل جذر يمكن استخدامه لقتل عملية جامحة. يحدد كلا الملفين قيم الوقت بالميكروثانية:

/proc/sys/kernel/sched_rt_period_us
    يحدد هذا الملف فترة جدولة تعادل 100% من عرض النطاق الترددي لوحدة المعالجة المركزية. يمكن أن تتراوح القيمة في هذا الملف من 1 إلى INT_MAX، مما يعطي نطاق تشغيل من 1 ميكروثانية إلى حوالي 35 دقيقة. القيمة المبدئية في هذا الملف هي 1,000,000 (1 ثانية).

/proc/sys/kernel/sched_rt_runtime_us
    تحدد القيمة في هذا الملف مقدار وقت "الفترة" الذي يمكن استخدامه بواسطة جميع العمليات المجدولة في الوقت الحقيقي وذات الموعد النهائي على النظام. يمكن أن تتراوح القيمة في هذا الملف من -1 إلى INT_MAX-1. يؤدي تحديد -1 إلى جعل وقت التشغيل مساويًا للفترة؛ أي أنه لا يُخصص وقت لوحدة المعالجة المركزية للعمليات غير الوقت الحقيقي (وهو السلوك قبل لينكس 2.6.25). القيمة المبدئية في هذا الملف هي 950,000 (0.95 ثانية)، مما يعني أن 5% من وقت وحدة المعالجة المركزية محجوزة للعمليات التي لا تعمل تحت سياسة جدولة الوقت الحقيقي أو الموعد النهائي.

  زمن الاستجابة
الخيط عالي الأولوية المحظور الذي ينتظر الإدخال/الإخراج له زمن استجابة معين قبل جدولته مرة أخرى. يمكن لكاتب برنامج تشغيل الجهاز تقليل زمن الاستجابة هذا بشكل كبير باستخدام معالج مقاطعة "مقاطعة بطيئة".

  متفرقات
ترث العمليات الفرعية سياسة الجدولة والمعاملات عبر fork(2). يُحفاظ على سياسة الجدولة والمعاملات عبر execve(2).

عادةً ما يكون قفل الذاكرة مطلوبًا للعمليات في الوقت الحقيقي لتجنب تأخيرات الترحيل؛ يمكن القيام بذلك باستخدام mlock(2) أو mlockall(2).

  ميزة المجموعة الآلية
منذ لينكس 2.6.38، يوفر النواة ميزة تُعرف بالتجميع الآلي لتحسين أداء سطح المكتب التفاعلي في مواجهة أعباء العمل كثيفة الاستخدام لوحدة المعالجة المركزية متعددة العمليات مثل بناء نواة لينكس بأعداد كبيرة من عمليات البناء المتوازية (أي علامة make(1) -j).

تعمل هذه الميزة بالتزامن مع مجدول CFS وتتطلب نواة مهيأة بـ CONFIG_SCHED_AUTOGROUP. على نظام قيد التشغيل، يمُكّن هذه الميزة أو تعطيلها عبر الملف /proc/sys/kernel/sched_autogroup_enabled؛ القيمة 0 تعطل الميزة، بينما القيمة 1 تمكّنها. القيمة المبدئية في هذا الملف هي 1، ما لم تُشغل النواة باستخدام المعامل noautogroup.

تُنشئ مجموعة آلية جديدة عند إنشاء جلسة جديدة عبر setsid(2)؛ يحدث هذا، على سبيل المثال، عند بدء نافذة طرفية جديدة. ترث العملية الجديدة المنشأة بواسطة fork(2) عضوية المجموعة الآلية لأصلها. وبالتالي، جميع العمليات في الجلسة هي أعضاء في نفس المجموعة الآلية. تُدمر المجموعة الآلية آليًا عند إنهاء آخر عملية في المجموعة.

عند تمكين التجميع الآلي، تُوضع جميع أعضاء المجموعة الآلية في نفس "مجموعة المهام" لمجدول النواة. عند تعطيله، يحدث إنشاء المجموعة كما هو مذكور أعلاه، وتكون عضوية المجموعة الآلية مرئية في /proc، ولكن لا تُستخدم المجموعات الآلية. يستخدم مجدول CFS خوارزمية تعمل على معادلة توزيع دورات وحدة المعالجة المركزية عبر مجموعات المهام. يمكن وصف فوائد ذلك لأداء سطح المكتب التفاعلي من خلال المثال التالي.

افترض وجود مجموعتين آليتين تتنافسان على نفس وحدة المعالجة المركزية (أي افترض إما نظام وحدة معالجة مركزية واحدة أو استخدام taskset(1) لحصر جميع العمليات على نفس وحدة المعالجة المركزية على نظام SMP). تحتوي المجموعة الأولى على عشر عمليات مقيدة بوحدة المعالجة المركزية من بناء نواة بدأ بـ make -j10. تحتوي الأخرى على عملية واحدة مقيدة بوحدة المعالجة المركزية: مشغل فيديو. تأثير التجميع الآلي هو أن المجموعتين ستتلقى كل منهما نصف دورات وحدة المعالجة المركزية. أي أن مشغل الفيديو سيحصل على 50% من دورات وحدة المعالجة المركزية، بدلاً من 9% فقط من الدورات، مما قد يؤدي إلى تدهور تشغيل الفيديو. الوضع على نظام SMP أكثر تعقيدًا، لكن التأثير العام هو نفسه: يوزع المجدول دورات وحدة المعالجة المركزية عبر مجموعات المهام بحيث لا تنتهي المجموعة الآلية التي تحتوي على عدد كبير من العمليات المقيدة بوحدة المعالجة المركزية إلى احتكار دورات وحدة المعالجة المركزية على حساب المهام الأخرى على النظام.

يمكن عرض عضوية المجموعة الآلية (مجموعة المهام) لعملية ما عبر الملف /proc/pid/autogroup:

    $ cat /proc/1/autogroup
    /autogroup-1 nice 0

يمكن أيضًا استخدام هذا الملف لتعديل عرض النطاق الترددي لوحدة المعالجة المركزية المخصص لمجموعة آلية. يتم ذلك عن طريق كتابة رقم في نطاق "nice" إلى الملف لتعيين قيمة الأولوية nice للمجموعة الآلية. النطاق المسموح به هو من +19 (أولوية منخفضة) إلى -20 (أولوية عالية). (تتسبب كتابة قيم خارج هذا النطاق في فشل write(2) مع الخطأ EINVAL.)

إعداد nice للمجموعة الآلية له نفس معنى قيمة nice للعملية، ولكنه ينطبق على توزيع دورات وحدة المعالجة المركزية للمجموعة الآلية ككل، بناءً على قيم nice النسبية للمجموعات الآلية الأخرى. بالنسبة لعملية داخل مجموعة آلية، ستكون دورات وحدة المعالجة المركزية التي تتلقاها حاصل ضرب قيمة nice للمجموعة الآلية (مقارنة بالمجموعات الآلية الأخرى) وقيمة nice للعملية (مقارنة بالعمليات الأخرى في نفس المجموعة الآلية).

استخدام وحدة تحكم وحدة المعالجة المركزية cgroups(7) لوضع العمليات في مجموعات cgroups غير مجموعة cgroup الجذر لوحدة المعالجة المركزية يتجاوز تأثير التجميع الآلي.

ميزة المجموعة الآلية تجمع فقط العمليات المجدولة تحت سياسات غير الوقت الحقيقي (SCHED_OTHER و SCHED_BATCH و SCHED_IDLE). لا تجمع العمليات المجدولة تحت سياسات الوقت الحقيقي والموعد النهائي. تُجدول تلك العمليات وفقًا للقواعد الموصوفة سابقًا.

  قيمة nice وجدولة المجموعة
عند جدولة العمليات غير الوقت الحقيقي (أي تلك المجدولة تحت سياسات SCHED_OTHER و SCHED_BATCH و SCHED_IDLE)، يستخدم مجدول CFS تقنية تُعرف باسم "جدولة المجموعة"، إذا كُونت النواة مع الخيار CONFIG_FAIR_GROUP_SCHED (وهو أمر نموذجي).

تحت جدولة المجموعة، تُجدول الخيوط في "مجموعات مهام". مجموعات المهام لها علاقة هرمية، متجذرة تحت مجموعة المهام الأولية على النظام، المعروفة باسم "مجموعة المهام الجذر". تُشكل مجموعات المهام في الظروف التالية:

•   جميع الخيوط في مجموعة cgroup لوحدة المعالجة المركزية تشكل مجموعة مهام. أصل مجموعة المهام هذه هو مجموعة المهام لمجموعة cgroup الأصل المقابلة.

•   إذا مُكّن التجميع الآلي، فإن جميع الخيوط التي يتم وضعها (ضمنيًا) في مجموعة آلية (أي نفس الجلسة، كما أُنشئت بواسطة setsid(2)) تشكل مجموعة مهام. كل مجموعة آلية جديدة هي بالتالي مجموعة مهام منفصلة. مجموعة المهام الجذر هي أصل جميع هذه المجموعات الآلية.

•   إذا مُكّن التجميع الآلي، فإن مجموعة المهام الجذر تتكون من جميع العمليات في مجموعة cgroup الجذر لوحدة المعالجة المركزية التي لم تُوضع ضمنيًا في مجموعة آلية جديدة.

•   إذا عُطل التجميع الآلي، فإن مجموعة المهام الجذر تتكون من جميع العمليات في مجموعة cgroup الجذر لوحدة المعالجة المركزية.

•   إذا عُطل جدولة المجموعة (أي، كُونت النواة بدون CONFIG_FAIR_GROUP_SCHED)، فإن جميع العمليات في النظام توضع مبدئيا في مجموعة مهام واحدة.

تحت جدولة المجموعة، تؤثر قيمة الأولوية nice للخيط في قرارات الجدولة فقط بالنسبة للخيوط الأخرى في نفس مجموعة المهام. يترتب على ذلك بعض العواقب المفاجئة من حيث الدلالات التقليدية لقيمة nice على أنظمة UNIX. على وجه الخصوص، إذا مُكن التجميع الآلي (وهو المبدئي في توزيعات مختلفة)، فإن استخدام setpriority(2) أو nice(1) على عملية يكون له تأثير فقط للجدولة بالنسبة للعمليات الأخرى المنفذة في نفس الجلسة (عادةً: نفس نافذة الطرفية).

على العكس، بالنسبة لعمليتين هما (على سبيل المثال) العمليتان الوحيدتان المرتبطتان بوحدة المعالجة المركزية في جلسات مختلفة (مثل نوافذ طرفية مختلفة، كل منها مرتبطة بمهامها بمجموعات آلية مختلفة)، تعديل قيمة nice للعملية في إحدى الجلسات ليس له أي تأثير من حيث قرارات المجدول بالنسبة للعملية في الجلسة الأخرى. الحل البديل المفيد المحتمل هنا هو استخدام أمر مثل التالي لتعديل قيمة nice للمجموعة الآلية لـ جميع العمليات في جلسة طرفية:

    $ echo 10 > /proc/self/autogroup

  ميزات الوقت الحقيقي في نواة لينكس الرئيسية
منذ لينكس 2.6.18، أصبح لينكس مجهزًا تدريجيًا بقدرات الوقت الحقيقي، معظمها مشتق من مجموعة التصحيحات السابقة realtime-preempt. تُسمى هذه التصحيحات:

    patch-kernelversion-rtpatchversion

ويمكن تنزيلها من http://www.kernel.org/pub/linux/kernel/projects/rt/ أو استنساخها من شجرة git https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-stable-rt.git. تُصان الإصدارات الفردية طالما صينت نواة LTS المطابقة.

منذ لينكس 6.12، أصبح من الممكن تمكين استباق الوقت الحقيقي دون الحاجة إلى أي تصحيحات. يستمر وجود realtime-patch ويحتوي على دعم للبنى وبرامج التشغيل والميزات التي لم تدمج بعد والتي هي قيد التطوير.

منذ لينكس 6.13، أصبح الوقت الحقيقي خيارًا وليس نموذج استباق. مع هذا التغيير، تتوفر نماذج الاستباق التالية: CONFIG_PREEMPT_NONE وCONFIG_PREEMPT_VOLUNTARY وCONFIG_PREEMPT وCONFIG_PREEMPT_LAZY. يمكن تمكين قدرات الوقت الحقيقي باستخدام الخيار CONFIG_PREEMPT_RT ويمكن تعيين نموذج الاستباق إما إلى CONFIG_PREEMPT أو CONFIG_PREEMPT_LAZY. النموذج الأخير أقل حرصًا على استباق مهام SCHED_NORMAL في محاولة لتقليل استباق حامل القفل. لا يؤثر على مهام الوقت الحقيقي.

مع تمكين CONFIG_PREEMPT_RT، يتحول لينكس إلى نظام تشغيل وقت حقيقي عادي. تُستخدم سياسات الجدولة SCHED_FIFO وSCHED_RR وSCHED_DEADLINE بعد ذلك لتشغيل خيط بأولوية وقت حقيقي حقيقية وأدنى زمن استجابة جدولة في أسوأ الحالات.

ملاحظات
يمكن استخدام وحدة التحكم في وحدة المعالجة المركزية cgroups(7) لتحديد استهلاك وحدة المعالجة المركزية لمجموعات العمليات.

في الأصل، كان لينكس القياسي مخصصًا كنظام تشغيل للأغراض العامة قادر على التعامل مع عمليات الخلفية والتطبيقات التفاعلية وتطبيقات الوقت الحقيقي الأقل تطلبًا (التطبيقات التي تحتاج عادةً إلى الوفاء بالمواعيد النهائية الزمنية). على الرغم من أن لينكس 2.6 سمح باستباق النواة وأن المجدول O(1) المُقدم حديثًا يضمن أن الوقت اللازم للجدولة ثابت وحتمي بغض النظر عن عدد المهام النشطة، إلا أن الحوسبة الحقيقية في الوقت الحقيقي لم تكن ممكنة حتى لينكس 2.6.17.

انظر أيضًا
chcpu(1), chrt(1), lscpu(1), ps(1), taskset(1), top(1), getpriority(2), mlock(2), mlockall(2), munlock(2), munlockall(2), nice(2), sched_get_priority_max(2), sched_get_priority_min(2), sched_getaffinity(2), sched_getparam(2), sched_getscheduler(2), sched_rr_get_interval(2), sched_setaffinity(2), sched_setparam(2), sched_setscheduler(2), sched_yield(2), setpriority(2), pthread_getaffinity_np(3), pthread_getschedparam(3), pthread_setaffinity_np(3), sched_getcpu(3), capabilities(7), cpuset(7)

Programming for the real world - POSIX.4 بقلم Bill O. Gallmeister، O'Reilly & Associates, Inc., ISBN 1-56592-074-0.

وثائق نواة لينكس للمجدول (https://docs.kernel.org/scheduler).

يستحق الاطلاع: https://wiki.linuxfoundation.org/realtime/start

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.