الملحق صفر - ما هو الحاسوب وكيف يعمل ؟
في هذا الملحق سنناقش معلومات أساسية عن الحواسيب،
ونأخذ نظرة عميقة إلى مفاهيم أنظمة التشغيل وبرمجيات النظم.
اقتباسات هذا الفصل:
- "إن الحواسيب لا تفكر، ولكنك تفكر أنها تفكر. (نحن نفكر، هي لا)"
-- برنامج 'fortune-mod'
- "إن السؤال هل تفكر الحواسيب يشبه السؤال هل تسبح الغواصات"
-- Edsger W. Dijkstra
- "الحاسبة ENIAC تحتوي 18000 صماماً مفرغاً وتزن 30 طناً، إلا أن
الحواسيب في المستقبل قد تحتوي فقط على 1000 صماماً وربما تزن طناً ونصف."
-- Popular Mechanics عدد آذار 1949
- "إن الحواسيب تسرّع ارتكاب الأخطاء أكثر من أي اختراع بشري آخر
ربما باستثناء الأسلحة والخمور."
-- Mitch Ratcliffe
- "يعمل العقل البشري ب 10% من قدرته والباقي يشغله نظام التشغيل."
-- برنامج 'fortune-mod'
محتويات هذا الفصل:
ما هو الحاسوب ؟
إذا قلنا بأن الحاسوب هو آلة تساعدنا على القيام بالعمليات
الحسابية فعلينا أن نعتبر العداد الخشبي حاسوباً. حسناً
هكذا كانت المحاولات الأولى ثم جاءت الآت ميكانيكية كالتي صنعها
العالم "باسكال" وهي تقوم على اسطوانات مسننة تدويرها يحرك
أرقام لتمثل الجمع والطرح والضرب والقسمة (على الأعداد الصحيحة).
هذه لم تكن حواسيب بالمعنى الحقيقي بل مجرد عدادات.
مع بداية الحرب العالمية ظهرت الحاجة لحساب مسار
القذائف والتعامل مع الشيفرات .فتم تجنيد البشر من ذوي المهارات
ليعملوا كآلات حاسبة بتزودة بجداول ولكن
هذا لم يكن ليلبي الحاجات فتم تمويل أبحاث لتصنيع
أجهزة تقوم بالعمليات الحسابية المختلفة التي تطلب منها
ولكن إكتمال أي من هذه المشاريع لم يكتمل قبل إنتهاء الحربين.
جاءت آلات تعتمد على مبدأ كهربائي-ميكانيكي مثل قطعة Relay
(تستخدم الآن في إضاءة وإطفاء مصابيح الغماز في الباص)
من الأمثلة عليها Mark1 الذي يستند إلى 3 آلاف Relay ويستطيع
القيام ب3 عمليات جمع في ثانية صنع في عام 1944
بعد الحرب تابعت شركات مثل IBM وجامعات هذه الأبحاث وحصلنا على
الجيل الأول من الحواسب. إنه جيل الصمامات المفرغة من الهواء
وهي قطع كهربائية سريعة التلف. كانت هذه الأجهزة بحجم طابق كامل
وتحتوي لوحة من المصابيح تضيء وتطفئ بحسب الناتج
ولوحة من الوصلات توصل معاً بتسلسل يمثل البرنامج المطلوب
منها ENIAC وهو جهاز يحتوي أقل بقليل من 18 ألف صمام
ويقوم بعدة آلاف عملية جمع في الثانية.
ENIAC Electronic Numerical Integrator And Computer 1943-1946
EDVAC Electronic Discrete Variable Automatic Computer 1946-
EDSAC Electronic Delay Storage Automatic Computer
UNIVAC UNIVersal Automatic Computer 1951
IBM 650 - IBM 709
ما يميّز هذه الأجهزة أنها ليست مجرد آلات حاسبة
بل هي أكثر من ذلك فهي عامة الأغراض ليست للتشفير أو فكه
ولا للحساب بل لأي منها حيث أنك لا تصل أسلاك الجمع بالرقم
ليضيء لك الجواب بل تقوم بتوصيلات تمثل تعليمات
يقوم الحاسوب بفهمها وإعطاءك الجواب دون
تدخل مباشر فيما يشبه البرمجة فيما بعد.
عند اكتشاف الترانزستر Transistor وجد له مكان في هذه الصناعة.
فهو أصغر ويعمل بجهد أقل ويصدر حرارة أقل أي أنه قليل التلف.
سمي هذا بالجيل الثاني وقد استمر من أواخر الخمسينات وحتى ستينات القرن 20
وظهرت فيه لغات المستوى العالي(القريبة للغة البشر منها للوصلات والأجهزة)
وهي أقل سرعة من لغة الآلة واللغات الدنيا.
من هذه اللغات العليا فورتران FORTRAN 56 وظهرت أساليب إدخال بيانات مثل البطاقة المثقبة
(كل بطاقة تمثل سطر من النص/الأوامر).
من الأمثلة على هذا الجيل جهاز IBM 1401
وعند اكتشاف الدارات المتكاملة وهي شريحة سليكون يحفر عليها
كل أنواع الإلكترونيات بما فيه الترانزستر في مكان صغير جداً
(يمكن حفر عدة آلاف ترانزستر في نصف سنتيمتر مربع)
،عندها ظهر الجيل الثالث جيل السبعينات هو الجيل الذي ظهرت فيه
المصطلحات "الحاسوب الميكروي microcomputer" و "نظام تشغيل" ،
وهو الوقت الذي ظهرت فيه لغة البرمجة سي اللغة التي
غيرت مجرى البرمجة من وجهة نظري فهي لغة من المستوى العالي
ولكنها توفر وصول إلى كافة تعليمات المعالج
وتعطي سرعة اللغات الدنيا.
الحاسوب المايكروي (أو الحاسوب الشخصي) هو حاسوب تجاري أقل سرعة لا يحتاج
طابق كامل ولا أجهزة تبريد خاصة وكل ما يحتاجه
مكتب في منزل وشخص عادي غير مختص ليشغله.
في هذا الجيل وفي العالم الآخر (غير التجاري أو الشخصي)
ظهر نظام التشغيل يونكس! في مختبرات بيل (ليس بيل غيتس)
هذا النظام كان يعمل على جهاز (يسمى خادم) تتفرع منه
أكثر من طرفية (شاشة ولوحة مفاتيح) يعمل
في كل منها مستخدم مستقل في نفس الوقت ظاهرياً
بإعطاء كل منهم شريحة زمنية ليعمل فيها
وسمي هذا التشارك الزمني Time Sharing،
العديد من المستخدمين يمكنهم الدخول إلى النظام دفعة واحدة
فيما يسمى تعدد المستخدمين Multi user
(الذي يعرفه برنامج fortune-mod "جهاز حاسوب واحد يشغل أكثر من إنسان!")
بل وحتى يمكن للمستخدم على أحد الطرفيات تشغيل أكثر من
برنامج في نفس الوقت فيما يسمى تعدد المهام Multi tasking.
في أجهزة اليوم أجهزة الجيل الرابع أصبح لا فرق
من ناحية الأداء والسرعة بين الحاسوب الشخصي والحاسوب العملاق،
بل الفرق في التطبيقات التي تعمل هنا وهناك.
ففي العالم التجاري كانت هناك واجهة الاستخدام الرسومية
GUI أي Graphical User Interface
وكانت السهولة هدفاً للبرامج User friendly
في الآخر كانت القوة والسرعة والأمان الموثوقية وعدم التعليق.
وتسمع كثيراً عن الجيل الخامس جيل الذكاء الصناعي والعقد/الشبكات العصبية ولكن
هذا ليس أكثر من إعلام فالذكاء الصناعي موجود منذ الجيل الثالث
وتقنية العقد العصبية هي خوارزمية مستعملة في لعبة طاولة الزهر(النرد) من غنو gnubg
الموجودة في الكثر من توزيعات غنو/لينكس.
فإذا كان هناك جيل خامس فهو سيكون نتيجة لاكتشاف جديد
مثل فرط الموصلية أو المعالجة الضوئية (وليس الكهربائية) أو
مزج التكنولوجيا الحيوية(العضوية) والإلكترونية السليكونية وهذا
لم يتحقق بعد.
لماذا نحتاج الحاسوب ؟
لاحظنا أنه في كل جيل كان الحاسوب يقوم بمهمات
أكبر فمن مجرد عمليات جمع إلى كل الذي يقوم به الآن
ولكن بشكل أساسي مهمة حاسوب اليوم هي أن يكون جهاز
للأغراض العامة فحتى الحواسيب المصنعة لأغراض خاصة
مثل أجهزة ألعاب الفيديو فهي تحتوي على جهاز حاسوب
عام الأغراض ولكن لا يشغل سوى برامج خاصة.
أما لماذا نريد الحاسوب فهو السؤال الذي
يجب أن تدرسه جيداً قبل تخصيص ميزانية لشرائه(في شركة/دائرة)
فهو مكلف ولا يوضع للزينة ولا لتشجيع السياحة ليس فقط
ثمنه بل ثمن الدعم وتكاليف الإصلاح والتطوير وثم البرمجيات ورواتب الموظفين والدورات
فهو كالسيارة لا يكفي أن تدفع ثمنها بل وثمن الوقود.
فبعد كل هذه التكاليف لماذا نشتري الحواسيب.
تقوم الحواسيب بالكثير من العمل في وقت أقل
مما يوفر الوقت والجهد والمال والعمالة أيضاً
وهذه الأخيرة تعني بطالة وهي ليست مشكلة في تلك البلدان
حيث هناك حاجة للموارد البشرية لتقوم بالتفكير
بدلاً من الأعمال التقليدية لأن الأعمال التقليدية (ترهل وعمالة مقنعة)
لا تساهم فعلياً في الدخل
القومي "الآلة تعمل. الإنسان يفكر." (أحد شعارات IBM).
فالمعاملة التي كان الزبون أو المواطن يحتاج
أن يدققها في مكان ويقدمها في مكان ويحصل على موافقة من مكان
آخر أصبحت ممكنة بنفس المكان عبر الشبكات
والبحث اليدوي بين ملفات ورقية كبيرة مؤرشفة في غرفة كبيرة
ثم أخذ تقرير منها ونقله إلى موظف آخر ليأخذ الحكم المناسب بناءً على التقرير يتم تلقائياً
بواسطة قواعد البيانات المحوسبة على نفس الجهاز
الأول بهذا نوفر الوقت والجهد ونكسب الدقة لأن الحاسوب
لا يعرف الوساطة ونوفر الأموال بتقليل الموظفين
الذين لا يقومون بشيء سوى الأعمال البيروقراطية ونكسب
المال من جهت المراجع فهو لا يعطل وقته
بل يعود بسرعة لعمله ومساهمته في الدخل القومي.
تلميح
حتى تفهم كيف يفيد الحاسوب في الدخل القومي عندما يخلصنا من موظفين
فهو لا يصنع بطالة بذلك بل يقلل من البطالة المقنعة
وهي أن يقوم عدة أشخاص بعمل يكفيه شخص واحد.
ثم إن الجهاز البيروقراطي في شركة أو دولة ليس هدفاً
بل خدمة للبقية.
نستنتج أن الهدف من وجود الحاسوب هو أتمتة الأعمال
أي القيام بها بطريقة تلقائية أوتوماتيكية بأقل تدخل بشري ممكن
وإذا حققنا هذا فنحن نستعمل الحاسوب بالشكل الصحيح وإلا فهو
ليس إلا جزء من ديكور المكتب.
تحذير
في الدول النامية الحاسوب هو إهدار لأموال الضرائب
وزيادة في الترهل والعمالة المقنعة وشماعة تلقى عليها الأخطاء البشرية.
فعندما تراجع شركة/بنك تريد أن تسحب نقود من السهل
أن يجيبك الموظف أن الجهاز معطل! أو أن اسمك غير مدخل
وأن ملفك في فرع الشركة بالعقبة.
أو تراجع دائرة بها جهاز شخصي حديث تصم أذنك "فيروز" من سماعاته
في الوقت الذي يتم البحث عن ملفك الورقي حيث
تنازع الموظف الآخر على انتباهه في لعبة الشدة solitaire
وفي الحسابات الاقتصادية للمقارنة بين حاسوبين نحسب
الأداء أو المنفعة مقسومة على السعر، فجهاز بشاشة ملونة مسطحة وسماعات
subwoufer تستخدم في نظام إدخال البيانات
لا تختلف عن طرفية غبية بشاشة سوداء ولوحة مفاتيح وأن الفرق في السعر
هو هدر . في المقابل جهاز بشاشة ملونة مع سماعات في قسم المبيعات
يسمح للزبون بمعرفة تفاصيل السلعة ويستعرضها بطريقة
مقنعة لا تعتبر هدر. برنامج تعليمي "محوسب" يظهر
فيه دب يقوم بقراءة درس بطريقة تلقيمية غير تفاعلية
(واحد + واحد = إثنان صحيح)
لا يختلف عن تسجيل درس رياضيات على شريط كاسيت صوتي! ولا يخدم
التحصيل عند الطالب، ولا يلفت إنتبهه. كذلك عند عرض الشرائح
تنزل فيه الأسئلة والشرح على خلفية حديقة جميلة
فإن الطالب سينظر للشاشة ويرفع يديه ليشكل ظل
عصفور أو كلب دون أن ينتبه لما يجري!
تلميح
عرض شرائح بشاشة زرقاء زاهية ومبهرجة لإنجازات الشركة
تنزل الكتابة بها على شكل مطر يرافقه صوت رصاص
وصورة نهر وأشجار ومصانع وفتيات مبتسمات لا يجعل شركتك
رابحة ولا يقنعي بشراء أسهم فيها، ولا يغيّر من حقيقة كونها تخسر.
ما هي البرامج ؟
"أجزاء النظام التي يمكنك أن تحطمها بالمطرقة (لا ننصح بذلك)
تسمى عتاد hardware، التعليمات المبرمجة التي لا يمكنك
تحطيمها بالمطرقة ولا تملك إلا أن تلعنها (لا ننصح بذلك)
تسمى برمجيات" (بتصرف عن أميّة التكولوجيا في التسعينات").
الحاسوب عام الأغراض يستطيع القيام بعمليات مختلفة
توضع له هذه العمليات في سلسلة من التعليمات/الأوامر التي
يفهمها عبر وسيط تخزين يقرأها الحاسوب ويحفظها في ذاكرته
الرئيسية ويبدأ بتفيذها واحدة واحدة دون تدخل الإنسان،
إلا عندما تطلب منه هذه التعليمات ذلك بأن ينظر ماذا ضغط المستخدم
وماذا تقول لوحة المفاتيح وأين تضغط الفأرة.
كما تعمل هذه التعليمات بصمت حتى يكون هناك تعليمات تطلب
منه كتابة شيء على الشاشة أو طباعة شيء أو إصدار صوت.
سلسلة التعليمات هذه تسمى برنامج
يمكن أن تكون هذه البرامج على شكل لغة عالية المستوى
أي قريبة من لغة البشر والتعابير الرياضية
ويسمى الملف الذي يحتوي هذه التعليمات النصية الكود المصدري source code
اكتب "ما هو الطول :"
اسأل عن ل
اكتب "ما هو العرض :"
اسأل عن ع
احسب م = ل × ع
اكتب "المساحة تساوي" م
أو لغة دنيا مثل لغة التجميع assembly
إليك الكود الذي يقوم فقط بضرب الطول في العرض
(دون عرض السؤال ودون السؤال ودون طباعة النتيجة)
; intel styled assembly code
; some code to display & enter the values
; ...
; some code to calculate area
mov eax,width
mov ebx,height
mult eax,ebx
mov area,eax
; some code to display the result
; ...
وهذه اللغة ليست سوى لغة الآلة مع التعبير عن تعليمات
لغة الآلة بالأحرف مكان الأرقام للتقليل من خطأ النقل فالتعليمة
int 0x80 تعني بلغة الآلة (إنتل 80x86
) الكود 0xcd80 أي 11001101-10000000.
ويتم تحويل البرنامج من الملف النصي المصدري
في اللغات العليا إلى لغة الألة لتنفيذها فالحاسوب لا يفهم سوى
لغة الآلة وهذه العملية إما أن تتم في كل مرة ينفذ بها البرنامج
عن طريقة برنامج آخر اسمه المفسر interupter.
أو مرة واحدة فقط وإنتاج ملف آخر يحتوي البرنامج بلغة
الآلة يسمى الملف الثنائي binary file أو الملف الجاهز precompiled file
هذه العملية تسمى تصنيف compiling والبرنامج الذي يقوم بها يسمى مصنف compiler
البعض يسميه مترجم (من لغة عليا إلى لغة الآلة) ولكني
لا أفضل ذلك لأنه يسبب خلط بينه وبين الأدوات اللغوية
مثل gettext فإذا قلنا ترجمنا برنامج كذا ربما تعني
أصبح يطبع الرسائل بالعربية.
تسأل الآن "كيف أبرمج لعبتي المفضلة؟" في الحقيقة
أنت لا تفعل كمستخدم أنت إما أن تشتريها من الشركة/المبرمج أو تحصل عليها
من الإنترنت ثم تركبها وتشغلها على جهازك. وهذه
ليست مهمة المستخدم فمهمته هي استعمال البرامج
الجاهزة. أما من تستهويه البرمجة فهي بحر واسع لنا منه غرفة
في هذا الكتاب(انظر أبواب البرمجة).
كيف يعمل الحاسوب ؟
الدارة الكهربائية إما موصولة(يمر بها تيار) أو مفصولة(لا يمر بها تيار)،
كالمصباح مضاء أو مطفأ. نرمز في الحاسوب لمرور التيار بالواحد
وعدمه بالصفر (لا علاقة لكمية التيار هنا فلا نقول
أن 1 هي 1 أمبير و لا واحد فولت
ولا نقول إذا كان 5 فولت 1 فإن 1000 فولت تمثل أكثر من واحد
بل تعمل الدارة في مدى محدد للفولتية ضمنه واحد ودونه صفر)
وهما حالاتن فريدتان صفر أو واحد
لا يوجد بينهما حالة ولا يوجد واحد كبير وآخر صغير
هذه الطريقة تسمى الطريقة الرقمية وعكسها
الموجات التناظرية حيث كلما زاد الجهد الكهربائي زاد مقدار ما تمثله
لهذا تقبل هذه الموجات التشويش بينما الموجات الرقمية
هي إما واحد أو صفر. لا يوجد واحد واضح وآخر غير واضح.
يمكن لهذا النظام أن يمثل أي عدد كما نفعل نحن
بالأرقام {0، 1، 2، 3، 4، 5، 6، 7، 8، 9} في نظامنا العشري ونشكل منها كل الأعداد وذلك باستعمال
أكثر من منزلة تكون قيمة الرقم فيها عشر أمثال مما لو كان في
المنزلة السابقة أي أن 3 في المنزلة الثانية 30 والثالثة 300.
في نظام الصفر والواحد الذي نسميه النظام الثنائي
يكون للعدد مثلي قيمته لو كان في المنزلة السابقة
مثلاً 1 تعني 1 و 10 تعني مثلي الواحد أي 2 وهكذا
000001b= 1d
000010b= 2d
000100b= 4d
001000b= 8d
010000b=16d
100000b=32d
وإذا كان هناك أكثر من رقم نجمع
ويمكنك عمل ذلك بسرعة وذلك بكتابة قيمة المنزلة فوق العدد
ثم جمع تلك التي كتب تحتها واحد
001011b= 001000b+000010b+000001b=8d+2d+1d=11d
32 16 8 4 2 1
0 0 1 0 1 1b= 1d+2d+8d = 11d
للتحويل بالعكس نقسم على أكبر رقم نتوقعه من قوى الإثنين : 11 ÷ 32 = 0 والباقي 11
نصع الناتج ثم نأخذ الباقي ونقسمه على نصف الرقم
11 ÷ 16 = 0 والباقي 11 نضع الناتج ونتابع
11 ÷ 8 = 1 والباقي 3 ثم
3 ÷ 4 = 0 والباقي 3 ثم
3 ÷ 2 = 1 والباقي 1 ثم
1 ÷ 1 = 1 الآن نضع النواتج بجانب بعضها فنحصل 001011.
جمع الأرقام الثائية لا يختلف عن العشرية كثيراً
صفر + صفر = صفر ، صفر + واحد = واحد ، واحد + واحد = صفر وباليد واحد.
هذا المثال يوضح ذلك
3d + 13d = ?
3d = 000011b
13d = 001101b
1111
000011b
001101b +
----------
010000b --> 16d
أما الطرح أو الأعداد السالبة فيتم التعامل معهما بوضع
علامة خاصة في آخر بت فإذا كانت قيمته 0 فهو موجب أو صفر
أما إذا كانت 1 فإن العدد هو سالب
المتممة الثانية للقيمة المخزنة. والمتممة الثانية
هي المتممة الأولى + 1 ؛ والمتممة الأولى (تسمى النفي/المعكوس الثنائي رمزها في لغة سي ~) هي قلب كل صفر إلى واحد
وكل واحد إلى صفر. هذا مثال يفترض 7 منازل للقيمة ومنزلة للإشارة.
00001101b=13d
11110011b= ??
~11110011b=00001100b
11110011b=-(00001100b+1)=-(00001101b)=-13d
تتسأل بالطبع لماذا اختاروا هذه الطريقة الغريبة ؟ السبب
بسيط لأن الرقم السالب بهذه الطريقة إذا جمع مع الموجب
سيعطي صفراً (ويزيد واحد باليد لا يحسب لأن هناك 8 منازل في مثالنا)
13d + (-13)d = 0
1 1111111
00001101b
11110011b +
------------
1 00000000b
تشبه هذه الطريقة عداد (المسننات مثل عداد الكيلومترات في السيارة) ،
عندما يكون على الصفر وتحركه خطوة للوراء يصبح
9999 أو خطوتين 9998 وهكذا عداد الصفر والواحد
عندما يكون 00000000b
وتعيده خطوة للوراء 11111111b
أو خطوتين 11111110b
وهما يمثلان -1 و -2.
الضرب والقسمة عمليتان تأخذان الكثير من الوقت
ولكن كحالة خاصة يمكن القيام بهما بسرعة
فالضرب والقسمة في 2 مرفوعة لأي قوة (صحيحة) هو إزحة
لليسار واليمين على الترتيب بعدد من المنازل تساوي القوة ناقص واحد وهي تشبه
الضرب في 10 والقسمة عليه في النظام العشري مثلاً:
11d x 8d = 11d x 23d
0001011b << 2d = 1011000b = 88d
هذا بالنسبة للأعداد الصحيحة أما النسبية فيتم التعامل
معها عبر تمثيل يسمى بالفاصلة العائمة float-point
وهي تشبه التمثيل الهندسي للأرقام مثلاً
سرعة الضوء 0.3x109 كم/س
و شحنة الإلكترون 0.16x10-18 كولوم
وهكذا ... لاحظ أن المنزلة الأولى بعد الفاصلة
لا تمثل عشراً بل تعتمد قيمتها على القوة التي نرفع لها العشرة
فيكون العدد مكوناً من القوة exponent وهي عدد صحيح والجزء النسبي mantissa.
العمليات التي يمكن القيام بها مثل عمليات
"و" و "أو" و "أو الحصرية"
تقسم إلى نوعين منطقية وثنائية
المنطقية نأخذ قيمة كل رقم هل هي صفر أم لا
أما الثنائية فنتعامل مع كل منزلة في الطرفين.
تستخدم ‘أو‘ (في سي |) لوضع واحد في
منزلة محددة سواء أكانت قيمته السابقة 1 أم 0 أما
أو الحصرية XOR (في لغة سي ^)فهي تعطي واحد إذا كان أحد الطرفين
واحد وليس كلاهما، تستخدم لقلب tuggle الواحدات إلى أصفار والعكس بتطبيقها
على صف من الواحدات (أو لتصفير المنازل بتطبيقها على نفسها).
أما ‘و‘ (في سي &)فهي تعطي واحد إذا كان كلا الطرفين واحد.
وتستخدم لعمل قناع حاجب mask. انظر هذا المثال:
110110b 110110b 110110b
001100b | 001100b & 001100b ^
-------- -------- --------
111110b 000100b 111010b
أقسام الحاسوب ؟
الوحدات الأساسية هي
- وحدات إدخال Input Units
- وحدات إخراج Output Units
- وحدة المعالجة المركزية CPU
- وحدة الحساب والمنطق ALU
- وحدة التحكم CU
- المسجلات Registers
- المستوى الأول من الذاكرة المخفية Level 1 Cache Memory
- المستوى الثاني من الذاكرة المخفية Level 2 Cache Memory
- الذاكرة الأساسية/وحدة التخزين الأولي
- ذواكر القراءة والكتابة RAM
- ذواكر القراءة فقط ROM
li>وحدة التخزين الثانوي
تلميح
RAM ليست الذاكرة الوحيدة التي يمكن الوصول لها عشوائياً ولكن هذا اسمها.
وحدات الإدخال هي التي تهدف للحصول على مدخلات من المستخدم مثل لوحة المفاتيح
والفأرة. في المقابل تكون وسائط الإخراج مثل الشاشة والطابعة
تهدف لإنتاج مخرجات يفهمها المستخدم.
ويكوّن المعالج وبعض الوحدات الأخرى
قلب الحاسوب أو بمعنى أدق دماغه ألا وهو وحدة المعالجة المركزية!
هذا المعالج بوحدتيه التحكم(التي تلتقط التعليمة التالية) والحساب (التي تقوم بالحسابات)
قد يستطيع القراءة من القرص الصلب أو من الذاكرة رام لكنه
لا تستطيع جمع رقمين موجودان على القرص الصلب أو في الذاكرة رام
الحسابات تتم في ذاكرة صغيرة جداً
تسمى المسجلات registers كل مسجل يتسع لكمية صغيرة
تسمى كلمة word وهي الوحدة التي يستطيع المعالح حسابها دفعة واحدة
(في X86 من 386 فما فوق تكون 32-بت )
الذاكرة الأساسية مثل رام هي المكان الذي يجب أن تكون
التعليمات(البرنامج) موجودة فيه لكي تنفذ.
المستوى الأول من الذاكرة المخفية (كاش) هي ذاكرة صغيرة تكون أقرب للمعالح من الأساسية
فبالتالي أسرع منها وتكون أغلى طبعاً تستخدم
لتسريع الوصول للذاكرة الأساسية.
بنفس الطريقة يكون المستوى الثاني هو منطقة أقرب/أسرع
من الذاكرة الثانوية تستخدم لتسريعها وقد أصبح المستوى الثاني جزءاً
من المعالجات CPUs الحديثة.
القرص الصلب والمدمج والمرن أمثلة على وحدة التخزين الثانوية.
أنظمة التشغيل - النواة
عندما يعمل الحاسوب يتم تشغيل برجية عتادية frameware
موجود في ذاكرة القراءة فقط ROM يسمى BIOS أي
نظام الإدخال والإخراج الأساسي - Basic Input/Output System
تلميح
ROM في الحقيقة ليست للقراءة فقط؛ إذ يوجد أنواع قابلة لإعادة البرمجة
(منها بالأشعة أو بأجهزة خاصة) ولكن الكتابة بها في الغالب مسؤولية الشركة الصانعة فقط.
هذا البرنامج يقوم بعملية فحص تسمى POST أي اختبار التشغيل الذاتي
Power On Self Test حيث يتم فحص صلاحية الذاكرة وتلمّس الأجهزة
لتحميل وتنفيذ برنامج الإقلاع Boot-Loader. ولكن أهمية BIOS في أنه يوفر
وظائف BIOS Calls التي تسهل كتابة البرامج.
كما قلنا لغة الآلة (والتجميع) توفر تعليمات داخلية
للتعامل مع العمليات الحسابية والمنطقية ومع الذاكرة رام ولا توفر أي طريقة للتعامل مع
بطاقة الصوت أو القرص الصلب أو بطاقة العرض (أو الملفات ولكنها ليست حالتنا) ،
هذه الأجهزة يتم التعامل معها من خلال منافذ ports (لا علاقة لها بالشبكات)
تسمى I/O Ports. هناك في لغة الآلة والتجميع (والسي) ما يمكنك من
كتابة رقم في منفذ ذو رقم معين أو قراءة رقم من منفذ ذو رقم معين.
كل جهاز له صيغة معينة للتعامل معه عبر المنافذ التي يستعملها
وحتى الجهاز الواحد قد يكون له أكثر من احتمال
(مثلاً بطاقات صوت Sound Blaster قد تأخذ المنفذ الأساسي 220 أو 230 .. إلى 270)
تلميح
إذا أخذ جهازان نفس المنفذ فهذا يسمى تضارب conflict
وكان يتم حله بتوصيل jumpers أما الآن فتتم في بطاقات من نوع ISA
من خلال تقنية PNP حيث يحدد المنفذ عبر البرمجيات إما BIOS أو نظام التشغيل.
وهذه المشكلة غير مجودة في بطاقات PCI الأحدث
وتقنية PNP بلا معنى فيها.
قد يأخذ الجهاز أكثر من منفذ واحد لمعرفة الحالة status
(جاهز، بانتظار الأمر ، بانظار معاملات ...)
وآخر لإرسال الأوامر وآخر لتحديد المعاملات.
كتابة برنامج بهذه الطريقة أمر صعب جداً تخيل معي "اكتب أمر معين
نتظر حتى تصبح الحالة ..." لهذا توفر BIOS Calls مكتبة يتم
استدعاؤها من خلال المقاطعة interrupt (هل لديكم تعريب أفضل؟)
وذلك بالتعليمة (في لغة التجميع) int ورقم يمثل ذلك الجزء من BIOS الذي تريد
مثلاً int 10h للخاص ببطاقة العرض
وهناك موقع ثابت في الذاكرة يحتوي على العناوين في الذاكرة المقابلة لكل مقاطعة
وهذه التعليمة تقرأ العنوان المقابل ل 10 (بالستعشري) وتستدع الوظيفة الموجودة في ذلك العنوان .
يتم تحديد ماذا تريد أن تفعل من خلال وضع قيم للمسجلات المناسبة
قبل التعليمة int مثل المسجل AH الذي يحدد ما هي الوظيفة التي تريد
استعمالها مثلاً كتابة حرف على الشاشة.
بعد تحميل برنامج الإقلاع الذي بدوره يتابع تحميل نظام التشغيل،
يقوم نظام التشغيل بعمل مستوى أعلى وأكثر رقي من وظائف BIOS Calls
فمثلاً يتعامل نظام BIOS مع القرص بأبعاده
الثلاث Sector/Head/Cylinder
(اقرأ محتويات رقم كذا-كذا-كذا واكتب في رقم كذا-كذا-كذا)
لكن نظام التشغيل يتعامل مع ملفات (الملف المسمى كذا ...)
وذلك بعمل مقاطعات خاصة بنظام التشغيل إضافتها للجدول
مثلاً في نظام دووس DOS المقاطعة الأساسية هي int 0x21
مثلاً لفتح ملف في دووس نسعمل الوظيفة 0x3D
myfile db "readme.txt"
mov dx, myfile
mov ax,0x3D00
int 0x21
ومن فوائد نظام التشغيل أن المقاطعات الخاصة به نفسها
على الأجهزة والمنصات المختلفة التي يعمل عليها نظام التشغيل
(بعض أنظمة التشغيل المشهورة لا تعمل سوى على نوع واحد من الأجهزة فلا يكون لها أي فائدة).
في المقابل النظام لينكس يستعمل المقاطعة رقم int 0x80
ورقم الوظيفة يوضع في eax وهو معرف في asm/unistd.h
على صورة __NR_systemcallname
ثم المعاملات في المسجلات ebx و ecx و edx و esi و edi و ebp.
وهي نفس وظائف POSIX الموحد في أكثر من نظام.
المثال التالي يكتب الجملة الشهيرة Hello, world!
في ملف الخرج القياسي، مأخوذ من Assembly-HOWTO
; hello.asm - hello world in NASM asm (from Assembly-HOWTO)
; type 'nasm -f elf hello.asm && ld -s -o hello hello.o'
; section are .text (ro code) .data (rw data) .bss (rw uninitialized data)
section .data
msg db "Hello, world!",0x0a
len equ $ - msg
section .text
global _start
_start:
; write(1,msg,len); // 1 is stdout filedesc
mov edx,len ; len of message
mov ecx,msg ; address of msg
mov ebx,1 ; 1=stdout filedesc(fd)
mov eax,4 ; 4=sys_write
int 0x80 ; call linux kernel
; exit(0);
mov ebx,0 ; 0=exit code
mov eax,1 ; 1=sys_exit
int 0x80 ; call linux kernel
يوفر نظام التشغيل وسيلة لتحميل برامج
وتنفيذها. هذه البرامج ليست مجرد
كود بلغة الآلة بل هي وفق هيئة خاصة تحتوي ترويسة إضافية
تحتوي كم يجب أن يحجز ذاكرة إضافية أو مكان لتمرير المعاملات
ومتغيرات البيئة وجدول بالملفات وأجزاء الذاكرة التي تخص
البرنامج ليتم تحريرها تلقائياً بعد إنهاء البرنامج.
بعض الأنظمة الأكثر نضوجاً تحمّل المكتبات الديناميكية والأكثر تطوراً
مثل لينكس توفر دعم لأكثر من هيئة تتصرف في كل
واحدة بطريقة مختلفة.
تلميح
تصميم BIOS قديم جداً (مثلاً لا صلة له بتعدد المهام) لهذا يمنع لينكس الوصول له
ويوفر بديل خاص به.
تلميح
يسمح gcc بالكتابة بلغة التجميع داخل سي
بفضل GAS (اسم الأداة as).
ولكن وفق أسلوب AT&T وليس إنتل.
الفرق أن المسجلات تسبق ب‘%‘ و الثوابت ب‘$‘ أما المتغيرات
فلا تسبق بشيء لقيمتها وتسبق ب ‘$‘ لعنوانها ،
الإزاحة تعطى على شكل رقم ثم قوسين ثم المؤشر.
الفرق الأكبر أن المصدر يذكر أولاً والهدف آخراً ("من" ثم "إلى") كما
في تعليمتي mov و add. يجوز إلحاق أحد الحروف b و w و l إلى نهاية
التعليمة لتحديد حجم المعامل ب 8 أو 16 أو 32-بت.
اسم ملفات GAS ينتهي ب S مثل hello.S ويتم تجميعه
بواسطة as و ربطه بواسطة ld كما يلي
as hello.S -o hello.o && ld -s -o hello hello.o
يمكنك تحويل ملفات سي إلى لغة التجميع (للتعليم والمتعة)
بواسطة gcc -S -fverbose-asm -O2 hello.c -o hello.S
في مستوى أعلى تأتي المكتبة في لغات البرمجة
عالية المستوى مثل سي فبدلاً من حفظ أرقام وجداول لديك أسماء سهلة الحفظ
مثل open. كما أن لغات البرمجة توفر واجهة موحدة
على الأنظمة المختلفة والأجهزة المختلفة مثل لغة سي ولكن بعض اللغات
مثل VB لا تعمل سوى على نظام واحد.
البرامج التي تستعمل مكتبات تحتاج إلى أن تربط
معها (أي أن نضيف كود المكتبة إلى كود البرنامج)،
وضعهما معاً في ملف تنفيذي واحد
يسمى الربط الساكن/الاستاتيكي static linking الذي ينتج
ملفات تنفيذية كبيرة الحجم، يمكن توفير الحجم المشترك في أكثر
من برنامج استاتيكي كبير بوضع الكود المشترك في ملف هدف منفصل
يسمى DLL أي المكتبات المربوطة ديناميكياً dynamically linked libraries
ويسمى في يونكس so أي الهدف المشترك shared objects
تسمى هذه الطريقة في الربط dynamic linking أي الربط الديناميكي.
البرامج المربوطة ديناميكياً أصغر حجماً ولكنها
تتطلب وقت أطول لتبدأ لتحميل هذه المكتبات.
أنظمة التشغيل - الأدوات
ما تحدثنا عنه في نظام التشغيل كان شيئاً لا تراه
إنه يعمل بين البرنامج أو المكتبة من جهة وبين الأجهزة من جهة أخرى؛
هذا ما نسميه نواة. ولكن بقية برمجيات النظم التي تتعامل معها
تسمى أدوات النظام أو برمجيّات النظام. في بعض الأنظمة
يكون كل شيء قطعة واحدة صندوق أسود BlackBox لا تستطيع فصل
هذه عن تلك ولكن في غنو/لينكس النواة هي لينكس والبرمجيات من غنو
(يوجد خيارات أخرى مثل GNU/HURD)
عندما تكتب برنامج بلغة معينة فإنك تكتبه بمحرر نصوص
وهذا أول وأبسط مكونات برمجيّات النظام ففي غنو كان محرر emacs أول قطعة فيه
(هل قلت أبسط !؟)
ثم يأتي المصنف compiler الذي يمكنك من تحويل كود اللغة إلى برنامج
يمكن تنفيذه وطبعاً لا ننس مفسر الأوامر التي تطبعها.
في بعض الأنظمة تكون الواجهة الرسومية جزء من النظام ولا يمكن تخطيها
أنظمة التشغيل - التعريفات و modules
التعريفات device driver و modules وهما أمران مختلفان تقنياً
لكن في الغالب يؤديان نفس الوظيفة (الثانية أشمل من الأولى) ،
لينكس يعتمد modules لهذا إذا قلنا Linux device driver فحن نقصد
أحد أنواع modules .
قلنا أن النظام دووس يستعمل مقاطعة interrupt ثابتة هي 21 (ست-عشري).
برنامج التعريف يقوم بتخزين مؤشر إلى موقع هذه المقاطعة في الذاكرة
ثم بإعادة برمجة هذه المقاطعة لتشير إلى عنوان البرنامج نفسه (التعريف) ،
ثم الخروج دون تحرير الذاكرة لهذا يسمى
TSR أي Terminate but Stay Resedent in memory
(وهي بالمناسبة طريقة مشابهة لعمل الفيروسات).
عندما يريد برنامج ما الإتصال بنظام التشغيل
يضع كما قلنا رقم الوظيفة في المسجل ax ثم يستدع المقاطعة 21
ولكنها لا تشير لنظام دووس بل للتعريف الآن
ينظر التعريف هل الوظيفة في ax تخصه (مثلاً إذا كان تعريف جهاز قرص فإن ما يخصه فتح الملفات) - نعم يتصرف
وإلا يستدع نظام التشغيل (لهذا حفظ عنوانه). إذا كان هناك أكثر من تعريف
فإن كلاً منها يظن أن الذي قبله هو النظام واستدعاء النظام
يحتاج للمرور بها كلها وفي حال تعطل أحدها تنقطع السلسلة،
كما أن إزالتها لا تتم إلا بالتقشير من الآخير للأول إضافة إلى أن
مسؤولية هذه العملية تقع على كل تعريف (لأنه وحده يملك عنوان ما كان قبله) .
كان هذا عن برامج TSR مثل تلك التي تعرف اللغة العربية
(الشاشة والمفاتيح)
أما التعريفات التي توضع في config.sys وتحمل بأمر
DEVICE فإنها تُحمل عند الإقلاع فقط ولا يمكن إزالتها إلا بإغلاق الجهاز،
وهي لها هئية خاصة بها وطريقة للتتبع ولا حاجة لأن تعيد
برمجة المقاطعة أو تستعمل TSR.
أما النظام لينكس فله ميّزة فريدة لتوسيع إمكانات النواة هي وحدات النواة kernel modules
التي هي جزء من كود النظام (هي عبارة عن كود هدف object code)
تذكر أن أي مشروع من عدة ملفات يتم تصنيفها إلى ملفات هدف object
ثم ربطها معاً linking. ولكن هنا لا تربط هذه مع النواة وتترك
ليتم تحميلها لاحقاً وذلك بإضافتها إلى نفس صفحة الذاكرة الافتراضية للنواة.
بكلمات أخرى يمكنك تصنيف برنامج وإلحاقه بالنواة
بهذه الطريقة (مثلاً يوجد خادم إنترنت -كما apache- اسمه tux وهو عبارة عن جزئين
أحدهما عبارة عن kernel module حطم الأرقام القياسية في السرعة)
أي module يجب أن يحتوي وظيفتين باسم
init_module و cleanup_module (الوظيفتان دون معاملات والأولى تعيد int والثانية بلا)
كما تحتوي على متغير عام char *kernel_version="X.Y.Z"
ويمكن أن تحتوي على وظائف أخرى يتم تسجيلها وإضافتها إلى
قائمة الوظائف التي توفرها النواة كما يمكن أن تسجل ملفات وهمية
ضمن proc انظر Kernel Hacker Guide أو تسجل تعريف لجهاز خاص في dev
(لا يتم معرفة الجهاز من اسمه بل من خلال رقمين major و minor ويتم عمل الجهاز بأمر mknod)
انظر http://coffee.sf.net
عن كيفية ربط آلة صنع القهوة مع الحاسوب ليتحكم بها ببساطة
echo 'cappuccino' > /dev/coffee
من العبارات المضحكة "يمكن التحكم بمن يسمح له شرب القهوة من خلال أذونات الملف /dev/coffee".
أو التحكم في الأجهزة المنزلية http://edc.sf.net
المثال التالي من Module-HOWTO وهو فقط يطبع رسالة عند إضافة/إزالة ال module
/* hello.c - dummy kernel module from Module-HOWTO
* Compile this with
* gcc -c hello.c -Wall
* put it in lib/modules and do modprobe hello
*/
#define __KERNEL__ /* We're part of the kernel */
#define MODULE /* Not a permanent part, though. */
#include <linux/modversions.h>
#include <linux/module.h>
#define _LOOSE_KERNEL_NAMES
#include <linux/tty.h> /* console_print() interface */
int init_module() {
console_print("Hello, world - this is the kernel speaking\n");
/* or simply use printk("Hello") */
return 0; /* 0 success ; else failed */
}
void cleanup_module() {
console_print("Short is the life of an LKM\n");
}
لاحظ أنك لا تستطيع استعمال المكتبات (لأن المكتبة تستدعي النواة ونحن في النواة) فقط
تستطيع استعمال وظائف من داخل النواة مثل printk.
لتفهم كيف تتبع عمل الملفات في النواة ارجع إلى
Linux 2.4.x Initialization for IA-32 HOWTO لمؤلفها Randy Dunlap.
أنظمة النويّة Microkernel والنواة الأحادية Monolithic
معظم الأنظمة كانت أنظمة تعتمد على نواة أحادية Monolithic ولينكس واحد منها.
يعتقد العديد من الناس أن أنظمة المستقبل ستكون
مبنية على تصميم النُوَيّة microkernel. وتقوم فكرة النويّة على تقليل
مهام النواة إلى الحد الأدنى المطلوب في كل أنظمة التشغيل
(إدارة العتاد والذاكرة وتوزيع وقت المعالج على العمليات)
أما بقية المهام (مثل بروتوكولات الشبكة، أنظمة الملفات، الصلاحيات،
التشفير ...إلخ) توفرها مجموعة من البرامج الخاصة
تسمى الخادمات servers أو المراقبات daemons (وتعني أيضاً العفاريت)
تقوم بالمهام البين النووية بشكل متوازي (في نفس الوقت) في عالم
المستخدم (وليس عالم النواة).
كل هذا من أجل الحصول على نظام مقسّم إلى وحدات modularized
مما يسهّل القيام عليه وتطويره.
إن الاتصالات البين نووية (بين الخادمات أو بينها وبين النويّة)
بواسطة تمرير الرسائل Message Passing تجعل الأنظمة المبنية على
النويّة أقل سرعة من أنظمة النواة الأحادية بسبب أعباء التصميم، حيث
يتم التبديل بين الخادمات (فهي مهام/عمليات تعمل في عالم المستخدم)
وذلك يستغرق شريحتي تبديل زمنيتين timeslices (دخولاً وخروجاً)
لكل خادم (ارجع إلى مقالة Roberto Arcomano بعنوان Kernel Analysis HOWTO).
والأكثر من ذلك أن الكثير منها (مثل Mac OS X و OSF/1 و NEXTSTEP و Lites و MkLinux)
ولا تجني فوائد تصميم النويّة (مثل modularization) لأنها تشغل خادم واحد فوق النويّة.
على الرغم أن تصميم لينكس لا يتبع اسلوب النويّة، فهو نواة أحادية Monolithic kernel،
إلا أنه نظام مقسّم modularized system بسبب وجود وحدات النواة modules!
كما أن هناك أجزاء من كود النواة تعمل بشكل متوازي (كما الخادمات في النويّة)
تسمى خيوط النواة kernel threads ولكنها تعد على أصابع اليدين،
إنها موجودة فقط في الحالات التي يكون هناك جدوى من ذلك يقلل من عبئ وجودها،
حيث يتم اختيارها بعناية (تلك التي تتطلب عمليات إدخال وإخراج) بحيث
لن تستغرق كل الشريحة الزمنية
(حيث تقوم خوارزمية تعدد المهام على القفز إلى المهمة/العملية التالية الجاهزة
في أحد حالتين: إنتها الشريحة الزمنية أو في حالة نوم العملية مثلاً بانتظار الإدخال والإخراج).
كما لاحظنا فإن التصميم العبقري لنظام لينكس يجمع حسنات كل الحلول المعروفة
ويتجنب سيئاتها.
هناك أنظمة واعدة مبنية على النويّة أهمها
نظامي Plan9 (من Bell-Labs أصل اليونكس) و GNU/Hurd (جزء من GNU)
حيث يتوقع أن يكونا منافسي لينكس المستقبليين. إنهما يوسّعان
العديد من المفاهيم في عالم يونكس، مثلاً هناك توحيد المجلدات
union directories (أو UnionFS). لا يهدف Plan9 إلى أن يكون يونكس على عكس
Hurd (من خلال التوافق مع معايير POSIX).
سمي Plan9 على اسم فيلم "Plan 9 from Outer Space" في حين كان HURD
اختصاراً متداخلاً مزدوجاً mutually recursive acronym يعني
"HIRD Unix-Replacing Daemons" أي "HIRD العفاريت التي تحل محل يونكس"
حيث HIRD تعني "HURD of Interfaces Representing Depth" أي "HURD من الواجهات التي تمثل العمق.
حالياً HURD يعمل فوق النويّة GNU Mach Microkernel
أو GNU L4 Microkernel ولكنه يهدف لأن يكون مستقلاً عن النويّة
(يمكن نقله ليعمل على نويّات أخرى).
لأنهما يشغلان عدة خادمات فوق النويّة هذا يجعلهما
أنظمة modularized (مقسّمة إلى وحدات)، هذا يجعلهما
أفضل من غيرهما ولكن ليس أفضل من لينكس لأنه هو الآخر يحمل هذه الصفة،
ولكن هذه الخادمات فيهما يمكن أن تعمل دون صلاحيات (بصلاحيات محدودة) في
عالم المستخدم مما يجعل إضافة الأجزاء التي تحتوي أخطاء buggy codes أقل خطراً
لدرجة أن المستخدم (العادي محدود الصلاحيات) يمكنه تشغيل Hurd داخل
آخر (تسمى العملية sub-hurd)، من جهة أخرى في لينكس العادي
يمكن إضافة الوحدات فقط من قبل المستخدم الجذر (مدير النظام مطلق الصلاحيات)
مما يعني أن إضافة وحدة لدعم نظام ملفات غير مجرب تعرض
النظام كله للخطر (بسبب الصلاحيات المطلقة)، ولكن
باستعمال حزمة اسمها user-mode-linux فإننا نحص على هذه الميّزة في لينكس
(حيث يمكنك تجربة الأجزاء التي قد تحتوي أخطاء وحتى تشغيل نواة كاملة
كأنها عملية لمستخدم محدود الصلاحيات داخل نواة لينكس أخرى).
بسبب ميّزة تمرير الرسائل Message passing بين الخادمات فإن
Hurd و Plan9 (أو بعض الأنظمة المشتقة منه مثل Inferno)
تجعلهما مفيدان في الحوسبة الموزعة (الموازية) ولكن حتى
هذه يمكن الحصول عليها في لينكس عبر بعض الرقاع (مثل OpenMosix و BProc)
التي تجعل لينكس أفضل نظام في هذا المجال.
باختصار إن الوضع الحالي لنظام لينكس يوفر بطريقة أو بأخرى
(قد لا تكون مباشرة)
مثيلاً للمزايا الإضافية مع تجاوزها في السرعة والأداء، انظر مقالة
Eric S. Raymond's على www.faqs.org/docs/artu/plan9.html
حول Plan9.
إدارة الذاكرة
هناك أمر غريب جداً في تصميم الأجهزة PC التي تعتمد على معالجات من عائلة
80x86 التي ينتمي لها البينتيوم وهي قصة طويلة.
حيث تم تصميمها على أساس أن أكبر سعة للذاكرة هي 640 كيلو-بايت
ولكن في البداية (قبل أن تكون الكلمة 32-بت) كان المسجل 16 بت
التي تكفي لعنونة 0xFFFF ست-عشري أي 64 كيلو-بايت فقط
فحن بحاجة إلى 20-بت (وهو عرض ناقل العنونة address bus في أجهزة 8086 الجد الأكبر) ،
أي نصف بايت (منزلة ست-عشرية) تسمى physical page
، ولأن سعة المسجل الواحد 16 بت فقط
فنحن بحاجة لمسجل آخر. يسمى الأول إزاحة offset والثاني
مقطع segment يرمز له بالطريقة segment:offset
ولكن بدلاً من وضع physical page
في المنزلة الست-عشرية الأقل أهمية تم وضعه في الأكثر أهمية في
أقصى اليسار (دون ترك أي بت للمستقبل،
حيث لا تكون الذاكرة محدودة بواحد ميغابايت) مما يعني
أن البايت بالعنوان الفيزيائي 0x51234
يمكن تمثيل عنوانه على سبيل المثال لا الحصر بما يلي:
0x5000:0x1234 أو 0x5100:0x0234 أو
0x5120:0x0034 أو 0x5124:0x0004
كلها تشير لنفس العنوان وذلك بجمع الإزاحة و المقطع بعد ضربه في 16
أي إزاحته لليسار منزلة ست-عشرية. وهذا يعطينا 20 بت أي واحد ميغا-بايت فقط
على الرغم من استعمال 32 بت التي يمكنها ترميز 4 غيغا-بايت.
السبب هو الفرض بأن كل برنامج يجب أن يعمل في مقطع منفصل
لأن تعليمات لغة الآلة ذات 16-بت
لا نحدد فيها سوى العنوان (الإزاحة offset) ب16-بت
يجب أن يكون نفسه مهما كان العنوان الذي وضع فيه البرنامج،
فقالو نقسم الذاكرة إلى مقاطع في كل واحد يمكن أن يحمل برنامج
على الإزاحة صفر فيه، وتكون العناوين هي الإزاحة عن بداية المقطع.
ولو وضعنا المنزلة الست-عشرية التي تمثل physical page في المنزلة الأقل أهمية
في مسجل المقطع فإن ذلك يعني أن لدينا 16 مقطعاً صالحاً
فقط (عندما يكون عرض الناقل 20-بت) أي يسمح بتشغيل 16 برنامج
لهذا اختاروا الجهة الأخرى.
مشكلة أخرى تنتج عن تقسيم الذاكرة إلى مقاطع
وهي أن البرنامج يجب أن يوجد له مقاطع متاحة ومتتالية ليوضع فيها
وإلا فإن حجمه سيكون محدود بحجم المقطع تسمى هذه Segmentation problem
لهذا في دووس لا يكفي أن يكون لديك 128 كيلو-بايت متاحة
لتشغيل برنامج يحتاج 128كيلو-بايت أو لحجز تلك الكمية بل يجب أن تكون متوفرة ومتتالية.
بعد ظهور أجهزة بناقل 24-بت (80286) ثم أجهزة 32-بت (80386) ،
بذواكر أكبر من الحد الأقصى المفترض لهذا يعمل الجهاز في طورين
الطور الحقيقي real mode وهو طور التوافقية مع 8086 حيث لا ترى سوى أول ميغا من الذاكرة
وتسمى الذاكرة التقليدية Conventional memory
ويتم الوصول للبقية بنقل جزء صغير منها إلى
الذاكرة التقليدية وقراءته هناك.
يتم النقل عبر تعريف في دووس EMS أو XMS
الأخير هذا يوفره HIMEM.SYS ولا يعمل ويندوز دونه.
الطور الآخر هو الطور المحمي protected mode
وفيه تمثل الذاكرة بطريقتين بعنوانها الفيزيائي(طريقة مسطحة) أي مجرد رقم 32-بت
يبدأ العد من صفر والثانية بطريقة افتراضية
لحل مشكلة Segmentation problem أي شرط التتالي في المقطع
ببساطة بتقسيم المقطع segment إلى صفحات pages كل منها له حجم ثابت وإعتمادها
كوحدة وعدم اشتراط أن تكون الصفحات متتالية
فيظهر هذا المقطع في العنوان الإفتراضي متتالياً مع أنه فيزيائياً
قد يكون مفصولاً ببرامج أوبيانات لبرامج أخرى لكنها غير مرئية له.
قد يسمى المقطع في الطور المحمي عند بعض المراجع program page
كي لا يختلط المفهوم مع المقطع في الطور الحقيقي.
وهكذا ويكون العنوان في المسجل هو الإزاحة عن بداية المقطع الافتراضي ،
تستعمل مسجلات 32-بت التي تبدأ بحرف e مثل eax لتمثيل الإزاحة
أما مسجلات المقطع فتكون مقسومة عدة قسام لتمثل selector و limit الأول
الذي يشير إلى أي مقطع عنها تحسب الإزاحة، والثاني إلى الحد الأعلى.
يتسبب هذا الحل بمشكلة Pagination Problem وهي الهدر الناتج
عن ثبات حجم الصفحة فقد يحدث هدر لا يزيد
عن حجم الصفحة×عدد البرامج لهذا نقلل حجم الصفحة
مما يزيد عدد الصفحات وهذا بدوره يصنع مشلكة في الاحتفاظ بجدول
بكل تلك الصفحات والسرعة الضائعة في تحديثه.
يستعمل DPMI أي DOS Protected Mode Interface
(ليس جزءاً من دووس وإنما يأتي بشكل مستقل أو مع ويندوز)
مجموعة من الوظائف عبر المقاطعة 0x2f
للدخول إلى هذا الطور (التحويل من الطور الحقيقي إلى المحمي) ،
والمقاطة 0x31 لحجز/تحرير الذاكرة ومحاكاة
المقاطعات التي صممت للطور الحقيقي مثل مقاطعة دووس 0x21
التي كانت تستقبل مقطع-حقيقي/إزاحة segment/offset.
يعمل ويندوز (95 و 98) على مرحلتين، تكون الأولى (أثناء عرض الشعار)،
اضغط ESC لترى دووس يعمل في الطور الحقيقي، يحمّل تعريفات محددة في
ملف CONFIG.SYS مثل HIMEM.SYS ثم ينفذ عدداً من تطبيقات ذات 16-بت
وربما بعض الفيروسات أو تكون حملت قبلاً مع قطاع رقم صفر
(لا شيء مرئي إلى الآن سوى أول ميغا).
ثم ينتقل للطور المحمي وبقية النظام متعدد المهام والواجهة الرسومية ... إلخ
بمجرد الانتقال للطور المحمي لا يمكن تنفيذ برامج دووس
لأنها لا تستدعي المقاطعات عبر 0x31
كما أن الذاكرة التقليدية قد تكون مليئة ويحمل البرنامج خارج أول ميغا
فلا يستطيع برنامج دووس بطريقة segment/offset أن يرى نفسه؛
لهذا يقوم ويندوز بمحاكاة دووس (داخل البئية الرسومية محاكاة ولكن قبلها
تنفيذ حقيقي وإذا اخترت restart in dos mode يعمل دووس حقيقي)
هذه المحاكاة تعمل على إظهار أن البرنامج لا يزال داخل أول ميغا.
الخطورة في هذا التصميم بأن البرامج(خصوصاً الفيروسات) قبل الدخول في الطور المحمي يمكنها
استعمال EMS و XMS أو طرق مشابهة للوصول لأي جزء من الذاكرة داخل وخارج البرنامج كما أن النظام
ليس له أي سلطة عليها.
النظام لينكس صمم والأمان في البال بالطبع لم يتبع هكذا التصميم.
بمجرد تحميل نواة لينكس أول ما تقوم به هو الدخول في الطور المحمي.
ويختلف لينكس عن باقي الأنظمة بأنه يقسم الذاكرة إلى 4 مقاطع segments فقط
(النواة وبيانتها والبرامج وبياناتها)
على عكس الأنظمة الأخرى التي تخصص مقطع لكل برنامج كما ذكرنا
كما أن فصل النواة في مقطع يجعلها بعيدة عن عبث البرامج.
كما أن هذا التقسيم يجعله يوفر في الذاكرة عند تشغيل برنامج/مكتبة أكثر من مرة
حيث يحجز له مرة واحدة كبرنامج وبعدد المرات كبيانات، فكود البرنامج
نفسه في كل مرة وفقط تختلف البيانات.
ويحل مشكلتي segmentation و pagentation معاً.
الأولى بالتقسيم لصفحات والثانية بجعل حجم الصفحة 4 كيلو-بايت فقط
دون دفع ثمن ذلك من السرعة لأنه يرتبها في Hierarchical Paging
تستخدم خوارزميات تسريع مثل Binary search tree (في كل دورة تقسم المجموعة إلى نصفين
تهمل مجموعة وتبحث في الثاني بنفس الطريقة).
كل البرامج تعطى عناوين افتراضية والنواة وحدها من يستعمل العناوين الفيزيائية المطلقة
لهذا كل برنامج لا يستطيع الوصول لذاكرة برنامج آخر. الطريقة الوحيدة
ليرى برنامج جزء من ذاكرة برنامج آخر هي عبر قسم/ملف التبديل swap
تلميح
عملية التبديل swap هي عملية توليد ذاكرة افتراضية وهمية
فعند الحاجة للمزيد من الذاكرة يتم البحث عن جزء غير مستعمل (برنامج نائم) ،
وإرساله (أو جزء/صفحة منه ) للقرص الصلب
وتحرير الذاكرة التي كان يشغلها. عند الحاجة
لجزء موجود على القرص الصلب يبحث عن جزء آخر غير مستعمل
ليأخذ مكانه ومن هنا جاء الاسم. ولا نحتاج لتعديل البرامج
لأن العناوين التي مع البرامج افتراضية يديره نظام التشغيل.
فإذا كان هناك برنامج يريد أن لا يرى أي برنامج آخر ذاكرته
من خلال swap يطلب قفل lock على الذاكرة الخاصة به
ليتم إبقاؤه داخل الرام ولأن ذلك يحجز الكثير من الموارد
(خطورة أن تكون كل البرامج تغلق ذكرتها فلا يجد النظام ما يرسله للتبديل swap لتحرير ذاكرة)
لهذا فقط الجذر يمكنه قفل الذاكرة.
تلميح
لهذا تحصل تحذير ذاكرة غير آمنة عند توليد مفتاح في برنامج ssh
لغير الجذر!
أما إدارة الذاكرة في النظام دووس فيحتفظ مقابل كل جزء من الذاكرة block بسجل
يحتوي على حرف M أو Z تبعاً إذا كان هناك block تالي أم لا
وحجم الذاكرة وإلى أي برنامج تعود (مؤشر إلى تركيب يسمى PSP - Program segment prefix)
فإذا أراد النظام الوصول لجزء من الذاكرة(حجز/تحرير) عليه المرور بكل تلك السجلات.
|