معمل نظام التشغيل - الأسبوع 6
4 دقائق قراءة
شرائح الدرس
1 / 11
إدارة الـ Processes والملفات المُعيَّنة على الذاكرة (Memory-Mapped Files) في C#
جدول المحتويات
الملفات المُعيَّنة على الذاكرة
ما هي الملفات المُعيَّنة على الذاكرة؟
تُنشئ الملفات المُعيَّنة على الذاكرة (Memory-Mapped Files) تعيينًا (Mapping) مباشرًا بين ملف موجود على القرص ومنطقة في الذاكرة (RAM). يتيح لك هذا:
- الوصول إلى بيانات الملف كما لو كانت ذاكرة عادية
- مشاركة البيانات بين عدة processes بكفاءة
- التعامل مع الملفات الكبيرة عن طريق تحميل الأجزاء المطلوبة فقط
- تنفيذ عمليات الوصول العشوائي (Random Access) بسرعة
كيف تعمل
sequenceDiagram
participant App as Application
participant OS as Operating System
participant MMF as Memory-Mapped File
participant Disk as Disk Storage
App->>OS: Request Memory-Mapped File
OS->>Disk: Map file to memory region
Disk-->>OS: File mapped
OS-->>App: Return MMF handle
App->>MMF: Write data to memory
MMF->>OS: Update memory region
OS->>Disk: Sync to disk (lazy/on-demand)
App->>MMF: Read data from memory
MMF-->>App: Return data instantlyالمزايا الرئيسية
- وصول سريع: الوصول المباشر إلى الذاكرة أسرع بكثير من إدخال/إخراج الملفات (File I/O) التقليدي
- وصول عشوائي: الانتقال إلى أي موضع في الملف فوريًا
- الاتصال بين الـ Processes (IPC): يمكن لعدة processes مشاركة نفس المنطقة المُعيَّنة على الذاكرة
- كفاءة مع الملفات الكبيرة: تحميل الأجزاء التي تحتاجها فقط إلى الذاكرة
معمارية الملفات المُعيَّنة على الذاكرة
graph LR
subgraph Process1[Process 1]
A1[Memory View Accessor]
end
subgraph Process2[Process 2]
A2[Memory View Accessor]
end
subgraph OS[Operating System]
B[Memory-Mapped File Object]
end
subgraph Storage[Physical Storage]
C[File on Disk]
end
A1 <-->|Read/Write| B
A2 <-->|Read/Write| B
B <-->|Maps to| Cأمثلة برمجية
المثال 1: ملف مُعيَّن على الذاكرة (MMF.cs)
يوضح هذا المثال كيفية إنشاء ملف مُعيَّن على الذاكرة واستخدامه لكتابة البيانات وقراءتها.
using System.IO.MemoryMappedFiles;
using System.Text;
namespace Process_MMF;
public class MMF
{
public static void Main(string[] args)
{
// Define the file path and size
string filePath = "largefile.txt";
long fileSize = 1024 * // = 1 KB
1024 * // = 1 MB
100; // = 100 MB
// Create or open the memory-mapped file
using (
var mmf = MemoryMappedFile.CreateFromFile(
filePath,
FileMode.OpenOrCreate,
null,
fileSize
))
{
// Create a memory-mapped view accessor to read and write data
using (var accessor = mmf.CreateViewAccessor())
{
// Write data to the memory-mapped file
string dataToWrite = "Hello, Memory-Mapped Files!";
byte[] dataBytes = Encoding.UTF8.GetBytes(dataToWrite);
// Write starting at byte position 30
accessor.WriteArray(30, dataBytes, 0, dataBytes.Length);
// Read 2 bytes starting at position 34
byte[] readData = new byte[2];
accessor.ReadArray(34, readData, 0, 2);
string readDataString = Encoding.UTF8.GetString(readData);
Console.WriteLine("Data read from memory-mapped file: " + readDataString);
Console.ReadKey();
}
}
}
}شرح الكود
حساب حجم الملف:
long fileSize = 1024 * 1024 * 100; // 100 MB- ينشئ ملفًا بحجم 100 ميجابايت
- 1024 بايت = 1 كيلوبايت
- 1024 كيلوبايت = 1 ميجابايت
- الإجمالي 100 ميجابايت
إنشاء الملف المُعيَّن على الذاكرة:
var mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.OpenOrCreate, null, fileSize)filePath: اسم الملف المراد تعيينهFileMode.OpenOrCreate: ينشئ الملف إن لم يكن موجودًا، ويفتحه إن كان موجودًاnull: اسم التعيين الافتراضي (تعيين بلا اسم)fileSize: حجم المنطقة المُعيَّنة على الذاكرة
View Accessor:
var accessor = mmf.CreateViewAccessor()- ينشئ مُتحكِّم وصول (Accessor) للقراءة من الذاكرة المُعيَّنة والكتابة إليها
- يوفر وصولًا عشوائيًا لأي موضع بايت
كتابة البيانات:
accessor.WriteArray(30, dataBytes, 0, dataBytes.Length);- يكتب البيانات بدءًا من الموضع رقم 30 في الملف
- المُعطَيات: (الموضع، البيانات، الإزاحة، العدد)
قراءة البيانات:
accessor.ReadArray(34, readData, 0, 2);- يقرأ بايتين بدءًا من الموضع رقم 34
- الموضع 34 سيقرأ "o," من كلمة "Hello" (H=30، e=31، l=32، l=33، o=34)
تصور توضيحي لتخطيط الذاكرة
graph LR
subgraph MemoryMappedFile[Memory-Mapped File - largefile.txt]
A[Position 0-29: Empty] --> B[Position 30: 'H']
B --> C[Position 31: 'e']
C --> D[Position 32: 'l']
D --> E[Position 33: 'l']
E --> F[Position 34: 'o']
F --> G[Position 35: ',']
G --> H[Position 36-56: Rest of string]
H --> I[Position 57-end: Empty]
end
style F fill:#ffcccc
style G fill:#ffccccملخص
غطَّى هذا المعمل:
- الملفات المُعيَّنة على الذاكرة: الوصول الفعّال إلى الملفات والاتصال بين الـ processes عبر تعيين الذاكرة
أهم النقاط
- توفر الملفات المُعيَّنة على الذاكرة وصولًا سريعًا وعشوائيًا إلى الملفات الكبيرة
- التوافق عبر المنصات يتطلب معالجة خاصة بكل نظام تشغيل عند تنفيذ الـ processes
- يعمل صنف MemoryMappedFile في .NET بسلاسة عبر جميع المنصات
تمارين تطبيقية
- عدِّل كود MMF للكتابة والقراءة في مواضع مختلفة
- أنشئ برنامجين منفصلين يتواصلان عبر ملف مُعيَّن على الذاكرة مشترك
- نفِّذ مُشغِّل processes يعمل عبر منصات متعددة ويكتشف نظام التشغيل تلقائيًا
- جرِّب أحجام ملفات مختلفة وقِس الفروق في الأداء