العمليات والخيوط (المسارات)
تغطي هذه الوحدة مفاهيم العمليات في أنظمة التشغيل، حالاتها، جدولتها، والاتصال بينها. كما تتناول الخيوط (Threads)، البرمجة متعددة الأنوية، ونماذج تعدد الخيوط.
Processes and Threads
This module covers process concepts in operating systems, their states, scheduling, and inter-process communication. It also explores threads, multicore programming, and multithreading models.
أهداف التعلم
- تحديد المكونات المنفصلة للعملية وتوضيح كيفية تمثيلها وجدولتها في نظام التشغيل.
- وصف كيفية إنشاء العمليات وإنهائها في نظام التشغيل.
- مقارنة التباين في الاتصال بين العمليات (IPC) باستخدام الذاكرة المشتركة وتمرير الرسائل.
- تحديد المكونات الأساسية للخيط (Thread) ومقارنة الخيوط بالعمليات.
- وصف فوائد وتحديات تصميم التطبيقات متعددة الخيوط.
- Identify the separate components of a process and illustrate how they are represented and scheduled in an operating system.
- Describe how processes are created and terminated in an operating system.
- Compare and contrast inter-process communication using shared memory and message passing.
- Identify the basic components of a thread, and contrast threads and processes.
- Describe the benefits and challenges of designing multithreaded applications.
1 مفهوم العملية وتخطيط الذاكرة
1 Process Concept and Memory Layout
العملية هي برنامج قيد التنفيذ، وتتكون من أربعة أقسام رئيسية في الذاكرة: النص، البيانات، الكومة، والمكدس.
A process is a program in execution, consisting of four main memory sections: Text, Data, Heap, and Stack.
البرنامج بحد ذاته ليس عملية؛ العملية هي كيان نشط.
تنقسم ذاكرة العملية إلى: قسم النص (Text) الذي يحتوي على الكود القابل للتنفيذ، قسم البيانات (Data) للمتغيرات العامة، الكومة (Heap) للذاكرة المخصصة ديناميكياً أثناء التشغيل، والمكدس (Stack) لتخزين البيانات المؤقتة عند استدعاء الدوال (مثل المعاملات، عناوين العودة، والمتغيرات المحلية).
A program by itself is not a process; a process is an active entity.
The memory layout includes: Text section (executable code), Data section (global variables), Heap section (dynamically allocated memory during runtime), and Stack section (temporary data storage when invoking functions, like parameters and local variables).
ينمو المكدس والكومة باتجاه بعضهما البعض في مساحة العنوان، مما يتطلب من نظام التشغيل إدارة الذاكرة بعناية لمنع تداخلهما (Stack Overflow أو Heap Overflow).
التنفيذ يجب أن يكون متسلسلاً ولا يوجد تنفيذ متوازٍ للتعليمات داخل عملية واحدة (بدون خيوط إضافية).
The stack and heap grow towards each other in the address space, requiring the OS to manage memory carefully to prevent overlap (Stack/Heap overflow).
Process execution must progress in a sequential fashion; no parallel execution of instructions occurs within a single, single-threaded process.
لماذا يتم فصل الكومة (Heap) عن المكدس (Stack) في تخطيط الذاكرة للعملية؟ Why are the Heap and Stack separated in the process memory layout?
لأن المكدس يدار تلقائياً بواسطة المعالج لاستدعاء الدوال (LIFO)، بينما الكومة تدار يدوياً أو بواسطة جامع القمامة للبيانات الديناميكية التي يختلف عمرها عن نطاق الدالة. فصلهما ونموهما باتجاهين متعاكسين يحسن استخدام المساحة المتاحة.
Because the stack is automatically managed for function calls (LIFO), while the heap is for dynamic data whose lifetime extends beyond a single function. Separating them and having them grow towards each other optimizes the use of the unallocated address space.
2 حالات العملية وكتلة التحكم (PCB)
2 Process States and PCB
تتغير حالة العملية أثناء تنفيذها (جديدة، جاهزة، قيد التشغيل، منتظرة، منتهية)، ويتم تتبع كل معلوماتها في كتلة التحكم في العملية (PCB).
A process changes state as it executes (New, Ready, Running, Waiting, Terminated), and all its information is tracked in the Process Control Block (PCB).
الحالات الخمس هي: New (قيد الإنشاء)، Running (التعليمات قيد التنفيذ)، Waiting (تنتظر حدثاً مثل إدخال/إخراج)، Ready (تنتظر تخصيص المعالج)، و Terminated (انتهى التنفيذ).
يمثل نظام التشغيل كل عملية باستخدام PCB الذي يحتوي على: حالة العملية، عداد البرنامج (PC)، سجلات وحدة المعالجة المركزية، معلومات الجدولة، إدارة الذاكرة، المحاسبة، ومعلومات حالة الإدخال/الإخراج.
The five states are: New (being created), Running (instructions executing), Waiting (waiting for an event like I/O), Ready (waiting for CPU assignment), and Terminated (finished).
The OS represents each process using a PCB containing: process state, program counter (PC), CPU registers, scheduling info, memory-management info, accounting info, and I/O status info.
الـ PCB هو هيكل البيانات الأساسي الذي يسمح لنظام التشغيل بإيقاف عملية واستئنافها لاحقاً دون فقدان حالتها.
حجم وتعقيد الـ PCB يؤثر مباشرة على أداء تبديل السياق (Context Switch).
The PCB is the core data structure that allows the OS to suspend and later resume a process without losing its state.
The size and complexity of the PCB directly impact the performance overhead of a Context Switch.
هل يمكن لعملية أن تنتقل مباشرة من حالة 'الانتظار' (Waiting) إلى حالة 'التشغيل' (Running)؟ Can a process transition directly from the 'Waiting' state to the 'Running' state?
لا، يجب أن تنتقل أولاً إلى حالة 'الجاهزية' (Ready) وتوضع في طابور الجاهزية حتى يختارها المجدول (Scheduler) لتصبح قيد التشغيل.
No, it must first transition to the 'Ready' state and be placed in the ready queue until the scheduler dispatches it to the CPU.
3 الجدولة وتبديل السياق
3 Scheduling and Context Switch
يختار المجدول العمليات من طابور الجاهزية لتنفيذها. تبديل السياق هو عملية حفظ حالة العملية القديمة وتحميل حالة العملية الجديدة، وهو عبء إضافي (Overhead).
The scheduler selects processes from the ready queue to execute. A context switch saves the state of the old process and loads the new one, acting as pure overhead.
الهدف من الجدولة هو تعظيم استخدام وحدة المعالجة المركزية (CPU).
يحتفظ النظام بطوابير: طابور الجاهزية (Ready Queue) للعمليات الموجودة في الذاكرة وتنتظر التنفيذ، وطوابير الانتظار (Wait Queues) للعمليات التي تنتظر حدثاً (مثل I/O).
عند التبديل بين العمليات، يقوم النظام بـ تبديل السياق (Context Switch)، حيث يحفظ حالة العملية الحالية في الـ PCB الخاص بها ويحمل حالة العملية التالية.
هذا الوقت يعتبر عبئاً صافياً (Pure Overhead) لأن النظام لا يقوم بأي عمل مفيد خلاله.
The goal of scheduling is to maximize CPU use.
The OS maintains queues: Ready queue (processes in memory ready to execute) and Wait queues (processes waiting for an event).
When switching processes, a Context Switch occurs: the system saves the state of the old process into its PCB and loads the saved state for the new process.
Context-switch time is pure overhead; the system does no useful work while switching.
يعتمد وقت تبديل السياق بشكل كبير على دعم الأجهزة (Hardware).
بعض المعماريات توفر مجموعات متعددة من السجلات (Registers) لكل نواة، مما يسمح بتحميل سياقات متعددة في وقت واحد، وبالتالي تقليل وقت التبديل إلى مجرد تغيير مؤشر السجل.
Context-switch time is highly dependent on hardware support.
Some hardware provides multiple sets of registers per CPU, allowing multiple contexts to be loaded at once, reducing the switch time to merely changing a pointer.
لماذا يعتبر تبديل السياق 'عبئاً صافياً' (Pure Overhead)؟ Why is a context switch considered 'pure overhead'?
لأن وحدة المعالجة المركزية خلال هذا الوقت تقوم فقط بمهام إدارية لنظام التشغيل (حفظ وتحميل السجلات) ولا تقوم بتنفيذ أي تعليمات خاصة ببرامج المستخدم.
Because during this time, the CPU is only performing OS administrative tasks (saving/loading registers) and is not executing any user program instructions.
4 العمليات على العمليات (الإنشاء والإنهاء)
4 Operations on Processes
تنشئ العملية الأب عمليات أبناء. يمكن للأب أن ينتظر إنهاء الابن أو يعمل بالتزامن معه. تنتهي العملية عندما تطلب من النظام حذفها.
A parent process creates child processes. The parent can wait for the child or execute concurrently. A process terminates when it asks the OS to delete it.
إنشاء العملية: العملية المنشِئة تسمى الأب (Parent) والجديدة تسمى الابن (Child). هناك احتمالان للتنفيذ: الأب يستمر بالتزامن مع الابن، أو الأب ينتظر حتى ينتهي الابن. بالنسبة لمساحة العنوان: إما أن يكون الابن نسخة مطابقة للأب، أو يتم تحميل برنامج جديد فيه.
إنهاء العملية: تنتهي العملية عند تنفيذ آخر تعليمة. يمكن للأب إنهاء الابن إذا تجاوز الابن موارده، أو لم تعد المهمة مطلوبة، أو إذا كان الأب يخرج ونظام التشغيل لا يسمح للأبناء بالاستمرار (Cascading Termination).
Process Creation: The creating process is the parent, the new one is the child. Execution possibilities: parent executes concurrently with children, or parent waits until children terminate. Address-space possibilities: child is a duplicate of the parent, or child has a new program loaded into it.
Process Termination: A process terminates when it finishes its final statement. A parent may terminate a child if the child exceeds resource usage, the task is no longer required, or the parent is exiting and the OS doesn't allow orphans.
في أنظمة UNIX، يتم الإنشاء باستخدام استدعاء النظام `fork()` الذي ينشئ نسخة مطابقة، يليه غالباً `exec()` لتحميل برنامج جديد في مساحة الابن.
إذا انتهى الأب دون انتظار الابن، قد يصبح الابن عملية 'يتيمة' (Orphan) أو 'زومبي' (Zombie) حسب كيفية إدارة نظام التشغيل لذلك.
In UNIX systems, creation is done via the `fork()` system call (creating a duplicate), often followed by `exec()` to replace the child's memory space with a new program.
If a parent terminates without waiting, children might become orphans or zombies, depending on OS handling.
ما هي الحالات التي يضطر فيها الأب لإنهاء عملية الابن قسرياً؟ In what situations would a parent forcibly terminate a child process?
إذا استهلك الابن موارد أكثر من المسموح، أو إذا لم تعد نتيجة مهمة الابن مطلوبة، أو إذا كان الأب نفسه على وشك الانتهاء والنظام لا يدعم العمليات اليتيمة.
If the child exceeds allocated resources, the task assigned to the child is no longer needed, or the parent is exiting and the OS does not allow child processes to continue.
5 الاتصال بين العمليات (IPC)
5 Interprocess Communication (IPC)
تتواصل العمليات المتعاونة إما عبر مشاركة منطقة من الذاكرة (Shared Memory) أو عبر إرسال واستقبال الرسائل (Message Passing).
Cooperating processes communicate either by sharing a region of memory (Shared Memory) or by sending and receiving messages (Message Passing).
العمليات قد تكون مستقلة أو متعاونة. أسباب التعاون تشمل: مشاركة المعلومات، تسريع الحسابات، والنمطية (Modularity).
يوجد نموذجان رئيسيان لـ IPC:
- الذاكرة المشتركة (Shared Memory): منطقة ذاكرة تتشاركها العمليات. الاتصال سريع ويتم التحكم فيه بواسطة العمليات نفسها، لكنه يتطلب آليات مزامنة (Synchronization) لمنع التعارض.
- تمرير الرسائل (Message Passing): يتم الاتصال دون متغيرات مشتركة باستخدام عمليتي `send()` و `receive()`. يمكن أن يكون الاتصال مباشراً (تسمية العملية صراحة) أو غير مباشر (عبر صناديق البريد/المنافذ).
Processes can be independent or cooperating. Reasons for cooperation: information sharing, computation speedup, modularity.
Two main IPC models exist:
- Shared Memory: An area of memory shared among processes. Communication is fast and controlled by user processes, but requires synchronization mechanisms.
- Message Passing: Communication without shared variables using `send(message)` and `receive(message)`. Communication can be direct (naming processes explicitly) or indirect (using mailboxes/ports).
في الذاكرة المشتركة، مشكلة 'المخزن المؤقت المحدود' (Bounded-Buffer) شائعة، حيث يجب ألا يكتب المنتج في مخزن ممتلئ ولا يقرأ المستهلك من مخزن فارغ.
في تمرير الرسائل، يجب على نظام التشغيل إدارة الروابط (Links) التي قد تكون متزامنة (Blocking) أو غير متزامنة (Non-blocking)، وتحديد سعة التخزين المؤقت للرابط.
In Shared Memory, the Bounded-Buffer problem is classic: producers must not write to a full buffer, and consumers must not read from an empty one.
In Message Passing, the OS must manage communication links, which can be synchronous (blocking) or asynchronous (non-blocking), and handle link buffering capacity.
/* Producer Process - Shared Memory */
item next_produced;
while (true) {
/* produce an item in next produced */
while (((in + 1) % BUFFER_SIZE) == out)
; /* do nothing - buffer is full */
buffer[in] = next_produced;
in = (in + 1) % BUFFER_SIZE;
}
/* Consumer Process - Shared Memory */
item next_consumed;
while (true) {
while (in == out)
; /* do nothing - buffer is empty */
next_consumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
/* consume the item in next consumed */
}
| Shared Memory | Message Passing | |
|---|---|---|
| السرعةSpeed | سريعة جداً (لا تتطلب استدعاءات نظام مستمرة)Very fast (no continuous system calls) | أبطأ (تتطلب استدعاءات نظام لكل رسالة)Slower (requires system calls for each message) |
| المزامنة (Synchronization)Synchronization | يجب على المبرمج إدارتها يدوياًProgrammer must manage it manually | تدار غالباً بواسطة نظام التشغيلOften managed by the OS |
| الاستخدام الأمثلBest Use Case | نقل كميات كبيرة من البيانات في نفس الجهازTransferring large amounts of data on the same machine | نقل كميات صغيرة أو عبر الشبكة (الأنظمة الموزعة)Transferring small amounts or over a network (distributed systems) |
أيهما أسرع في نقل كميات كبيرة من البيانات: الذاكرة المشتركة أم تمرير الرسائل؟ ولماذا؟ Which is faster for transferring large amounts of data: Shared Memory or Message Passing? Why?
الذاكرة المشتركة أسرع، لأن البيانات لا يتم نسخها بين مساحات الذاكرة ولا تتطلب تدخل نظام التشغيل (System Calls) لكل رسالة، بل يتم الوصول إليها مباشرة.
Shared Memory is faster because data is not copied between memory spaces and it avoids the overhead of system calls for every message exchange.
6 الخيوط والبرمجة متعددة الأنوية
6 Threads and Multicore Programming
الخيط (Thread) هو وحدة أساسية لاستخدام المعالج. التطبيقات متعددة الخيوط أكثر استجابة وتوفر الموارد، وتستفيد من المعالجات متعددة الأنوية.
A thread is a basic unit of CPU utilization. Multithreaded applications are more responsive, share resources efficiently, and leverage multicore processors.
تتشارك الخيوط داخل نفس العملية في قسم الكود، البيانات، والملفات، لكن لكل خيط سجلاته الخاصة ومكدسه (Stack) وعداد البرنامج (PC).
فوائد الخيوط: الاستجابة (استمرار التنفيذ إذا توقف جزء)، مشاركة الموارد (أسهل من IPC)، الاقتصاد (إنشاء الخيوط وتبديلها أرخص من العمليات)، وقابلية التوسع (استغلال الأنوية المتعددة).
تحديات الأنوية المتعددة: تقسيم الأنشطة، التوازن، تقسيم البيانات، الاعتمادية على البيانات، والاختبار وتصحيح الأخطاء.
Threads within the same process share the code section, data section, and OS resources (files), but each has its own registers, stack, and PC.
Benefits: Responsiveness (execution continues if part is blocked), Resource Sharing (easier than IPC), Economy (cheaper creation and context switching than processes), and Scalability (utilizing multicore architectures).
Multicore challenges: Dividing activities, balance, data splitting, data dependency, and testing/debugging.
هناك فرق بين التزامن (Concurrency) والتوازي (Parallelism).
التزامن يعني أن أكثر من مهمة تحرز تقدماً (ممكن على نواة واحدة عبر الجدولة)، بينما التوازي يعني تنفيذ أكثر من مهمة في نفس اللحظة (يتطلب أنوية متعددة).
التوازي نوعان: توازي البيانات (نفس العملية على أجزاء مختلفة من البيانات) وتوازي المهام (خيوط مختلفة تنفذ عمليات مختلفة).
Concurrency supports more than one task making progress (possible on a single core via scheduling), while Parallelism implies a system can perform more than one task simultaneously (requires multiple cores).
Types of parallelism: Data parallelism (distributes subsets of same data across cores) and Task parallelism (distributing different threads/operations across cores).
لماذا يعتبر تبديل السياق بين الخيوط (Thread Context Switch) أسرع من تبديل السياق بين العمليات (Process Context Switch)؟ Why is a thread context switch faster than a process context switch?
لأن الخيوط في نفس العملية تتشارك في مساحة الذاكرة (النص والبيانات)، لذا لا يحتاج نظام التشغيل إلى تبديل جداول الذاكرة (Page Tables)؛ يحتاج فقط لحفظ وتحميل السجلات والمكدس.
Because threads within the same process share the memory space (text and data), the OS does not need to switch memory management structures (like page tables); it only needs to save/load registers and the stack pointer.
7 نماذج تعدد الخيوط
7 Multithreading Models
تربط نماذج تعدد الخيوط بين خيوط المستخدم (User Threads) وخيوط النواة (Kernel Threads) بثلاث طرق: متعدد-إلى-واحد، واحد-إلى-واحد، ومتعدد-إلى-متعدد.
Multithreading models map user threads to kernel threads in three ways: Many-to-One, One-to-One, and Many-to-Many.
تُدار خيوط المستخدم بواسطة مكتبات في مساحة المستخدم (مثل POSIX Pthreads, Java threads)، بينما تُدعم خيوط النواة مباشرة من نظام التشغيل.
- Many-to-One: عدة خيوط مستخدم ترتبط بخيط نواة واحد. إذا توقف خيط واحد (Block)، تتوقف جميعها. لا تستفيد من الأنوية المتعددة.
- One-to-One: كل خيط مستخدم يرتبط بخيط نواة. يوفر تزامناً أعلى، لكن إنشاء خيط مستخدم يتطلب إنشاء خيط نواة (عبء إضافي). مستخدم في Windows و Linux.
- Many-to-Many: عدة خيوط مستخدم ترتبط بعدة خيوط نواة. مرن جداً لكنه معقد وغير شائع حالياً.
User threads are managed by user-level libraries (e.g., POSIX Pthreads, Java threads), while Kernel threads are supported directly by the OS.
- Many-to-One: Many user threads mapped to a single kernel thread. One thread blocking causes all to block. Cannot run in parallel on multicore.
- One-to-One: Each user thread maps to a kernel thread. More concurrency, but creating a user thread creates a kernel thread (overhead). Used in Windows and Linux.
- Many-to-Many: Many user threads mapped to many kernel threads. Flexible but complex, not very common today.
قضايا الخيوط (Threading Issues) تشمل دلالات استدعاءات `fork()` و `exec()` (هل ننسخ كل الخيوط أم خيط واحد؟)، معالجة الإشارات (Signal Handling)، إلغاء الخيوط (متزامن أم مؤجل)، التخزين المحلي للخيط (Thread-local storage)، وتنشيط المجدول (Scheduler Activations).
Threading issues include the semantics of `fork()` and `exec()` (duplicate all threads or just one?), signal handling (synchronous vs asynchronous), thread cancellation (asynchronous vs deferred), thread-local storage, and scheduler activations.
| Many-to-One | One-to-One | |
|---|---|---|
| التوازي على أنوية متعددةParallelism on Multicore | غير ممكن (خيط واحد في النواة في نفس الوقت)Not possible (only one thread in kernel at a time) | ممكن وفعالPossible and efficient |
| تأثير التوقف (Blocking)Blocking Impact | توقف خيط واحد يوقف العملية بأكملهاOne thread blocking blocks the entire process | توقف خيط لا يؤثر على الخيوط الأخرىOne thread blocking does not affect others |
| العبء (Overhead)Overhead | منخفض (لا يتم إنشاء خيوط نواة لكل خيط مستخدم)Low (no kernel thread created for each user thread) | مرتفع (إنشاء خيط نواة لكل خيط مستخدم)High (creating a kernel thread for each user thread) |
لماذا تخلت معظم أنظمة التشغيل الحديثة (مثل Linux و Windows) عن نموذج Many-to-Many لصالح نموذج One-to-One؟ Why have most modern OSs (like Linux and Windows) abandoned the Many-to-Many model in favor of the One-to-One model?
لأن نموذج One-to-One أصبح أقل تكلفة مع تطور الأجهزة، وهو أسهل في البرمجة وإدارة الأخطاء، ويستفيد بشكل كامل من المعالجات متعددة الأنوية دون تعقيدات المزامنة الإضافية المطلوبة في نموذج Many-to-Many.
Because hardware has improved making kernel thread creation less of a bottleneck, One-to-One is simpler to implement, avoids complex multiplexing logic, and fully utilizes multicore processors seamlessly.