الملحق صفر - ما هو الحاسوب وكيف يعمل ؟ | كتاب لينكس الشامل | >> |
إذا قلنا بأن الحاسوب هو آلة تساعدنا على القيام بالعمليات الحسابية فعلينا أن نعتبر العداد الخشبي حاسوباً. حسناً هكذا كانت المحاولات الأولى ثم جاءت الآت ميكانيكية كالتي صنعها العالم "باسكال" وهي تقوم على اسطوانات مسننة تدويرها يحرك أرقام لتمثل الجمع والطرح والضرب والقسمة (على الأعداد الصحيحة). هذه لم تكن حواسيب بالمعنى الحقيقي بل مجرد عدادات. مع بداية الحرب العالمية ظهرت الحاجة لحساب مسار القذائف والتعامل مع الشيفرات .فتم الاستعانة بآلات بشرية مزودة بجداول ولكن هذا لم يكن ليلبي الحاجات فتم تمويل أبحاث لتصنيع أجهزة تقوم بالعمليات الحسابية المختلفة التي تطلب منها ولكن إكتمال أي من هذه المشاريع لم يكتمل قبل إنتهاء الحربين. جاءت آلات تعتمد على مبدأ كهربائي-ميكانيكي مثل قطعة Relay (تستخدم الآن في إضاءة وإطفاء مصابيح الغماز في الباص) من الأمثلة عليها Mark1 الذي يستند إلى 3 آلاف Relay ويستطيع القيام ب3 عمليات جمع في ثانية صنع في عام 1944
بعد الحرب تابعت شركات مثل IBM وجامعات هذه الأبحاث وحصلنا على الجيل الأول من الحواسب. إنه جيل الصمامات المفرغة من الهواء وهي قطع كهربائية سريعة التلف. كانت هذه الأجهزة بحجم طابق كامل وتحتوي لوحة من المصابيح تضيء وتطفئ بحسب الناتج ولوحة من الوصلات توصل معاً بتسلسل يمثل البرنامج المطلوب منها ENIAC وهو جهاز يحتوي أقل بقليل من 18 ألف صمام ويقوم بعدة آلاف عملية جمع في الثانية.
ENIAC Electronic Numerical Integrator And Computer 1943-1946 EDVAC Electronic Discvete 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
وعند اكتشاف الدارات المتكاملة وهي شريحة سليكون يحفر عليها
كل أنواع الإلكترونيات بما فيه الترانزستر في مكان صغير جداً
(يمكن حفر عدة آلاف ترانزستر في نصف سنتيمتر مربع)
،عندها ظهر الجيل الثالث جيل السبعينات هو الجيل الذي ظهرت فيه
المصطلحات "حاسوب شخصي" و "نظام تشغيل" ،
وهو الوقت الذي ظهرت فيه لغة البرمجة سي اللغة التي
غيرت مجرى البرمجة من وجهة نظري فهي لغة من المستوى العالي
ولكنها قادرة على عمل أي شيء بنفس سرعة اللغات الدنيا.
الحاسوب الشخصي هو حاسوب تجاري أقل سرعة لا يحتاج
طابق كامل ولا أجهزة تبريد خاصة وكل ما يحتاجه
مكتب في منزل وشخص عادي غير مختص ليشغله.
في هذا الجيل وفي العالم الآخر (غير التجاري أو الشخصي)
ظهر نظام التشغيل يونكس! في مختبرات بيل (ليس بيل غيتس)
هذا النظام كان يستطيع تشغيل أكثر من طرفية(شاشة ولوحة مفاتيح) يعمل
في كل منها مستخدم مستقل يتشاركون كلهم
في نفس الحاسوب Time Sharing
والطباعة في أثناء القيام بعمليات أخرى وتشغيل أكثر من
برنامج في نفس الوقت.
في أجهزة اليوم أجهزة الجيل الرابع أصبح لا فرق من ناحية الأداء والسرعة بين الحاسوب الشخصي والحاسوب العملاق، بل الفرق في التطبيقات التي تعمل هنا وهناك. ففي العالم التجاري كانت هناك واجهة الاستخدام الرسومية GUI أي Graphical User Interface وكانت السهولة هدفاً للبرامج User friendly في الآخر كانت القوة والسرعة والأمان الموثوقية وعدم التعليق. وتسمع كثيراً عن الجيل الخامس جيل الذكاء الصناعي والعقد/الشبكات العصبية ولكن هذا ليس أكثر من إعلام فالذكاء الصناعي موجود منذ الجيل الثالث وتقنية العقد العصبية موجودة في لعبة طاولة الزهر(النرد) في لينكس. فإذا كان هناك جيل خامس فهو سيكون نتيجة لاكتشاف جديد مثل فرط الموصلية أو المعالجة الضوئية (وليس الكهربائية) أو مزج التكنولوجيا الحيوية(العضوية) والإلكترونية السليكونية وهذا لم يتحقق بعد.
لاحظنا أنه في كل جيل كان الحاسوب يقوم بمهمات أكبر فمن مجرد عمليات جمع إلى كل الذي يقوم به الآن ولكن بشكل أساسي مهمة حاسوب اليوم هي أن يكون جهاز للأغراض العامة فحتى الحواسيب المصنعة لأغراض خاصة مثل أجهزة ألعاب الفيديو فهي تحتوي على جهاز حاسوب عام الأغراض ولكن لا يشغل سوى برامج خاصة. أما لماذا نريد الحاسوب فهو السؤال الذي يجب أن تدرسه جيداً قبل تخصيص ميزانية لشرائه(في شركة/دائرة) فهو مكلف ولا يوضع للزينة ولا لتشجيع السياحة ليس فقط ثمنه بل ثمن الدعم وتكاليف الإصلاح والتطوير وثم البرمجيات ورواتب الموظفين والدورات فهو كالسيارة لا يكفي أن تدفع ثمنها بل وثمن الوقود. فبعد كل هذه التكاليف لماذا نشتري الحواسيب. تقوم الحواسيب بالكثير من العمل في وقت أقل مما يوفر الوقت والجهد والمال والعمالة أيضاً وهذه الأخيرة تعني بطالة وهي ليست مشكلة في تلك البلدان حيث هناك حاجة للموارد البشرية لتقوم بالتفكير بدلاً من الأعمال التقليدية لأن الأعمال التقليدية (ترهل وعمالة مقنعة) لا تساهم فعلياً في الدخل القومي. فالمعاملة التي كان الزبون أو المواطن يحتاج أن يدققها في مكان ويقدمها في مكان ويحصل على موافقة من مكان آخر أصبحت ممكنة بنفس المكان عبر الشبكات والبحث اليدوي بين ملفات ورقية كبيرة مؤرشفة في غرفة كبيرة ثم أخذ تقرير منها ونقله إلى موظف آخر ليأخذ الحكم المناسب بناءً على التقرير يتم تلقائياً بواسطة قواعد البيانات المحوسبة على نفس الجهاز الأول بهذا نوفر الوقت والجهد ونكسب الدقة لأن الحاسوب لا يعرف الوساطة ونوفر الأموال بتقليل الموظفين الذين لا يقومون بشيء سوى الأعمال البيروقراطية ونكسب المال من جهت المراجع فهو لا يعطل وقته بل يعود بسرعة لعمله ومساهمته في الدخل القومي.
حتى تفهم كيف يفيد الحاسوب في الدخل القومي عندما يخلصنا من موظفين فهو لا يصنع بطالة بذلك بل يقلل من البطالة المقنعة وهي أن يقوم عدة أشخاص بعمل يكفيه شخص واحد. ثم إن الجهاز البيروقراطي في شركة أو دولة ليس هدفاً بل خدمة للبقية.
في الدول النامية الحاسوب هو إهدار لأموال الضرائب وزيادة في الترهل والعمالة المقنعة وشماعة تلقى عليها الأخطاء البشرية. فعندما تراجع شركة/بنك تريد أن تسحب نقود من السهل أن يجيبك الموظف أن الجهاز معطل! أو أن اسمك غير مدخل وأن ملفك في فرع الشركة بالعقبة. أو تراجع دائرة بها جهاز شخصي حديث تصم أذنك "فيروز" من سماعاته في الوقت الذي يتم البحث عن ملفك الورقي حيث تنازع الموظف الآخر على انتباهه في لعبة الشدة solitaire
عرض شرائح بشاشة زرقاء زاهية ومبهرجة لإنجازات الشركة تنزل الكتابة بها على شكل مطر يرافقه صوت رصاص وصورة نهر وأشجار ومصانع وفتيات مبتسمات لا يجعل شركتك رابحة ولا يقنعي بشراء أسهم فيها، ولا يغيّر من حقيقة كونها تخسر.
الحاسوب عام الأغراض يستطيع القيام بعمليات مختلفة
توضع له هذه العمليات في سلسلة من التعليمات/الأوامر التي
يفهمها عبر وسيط تخزين يقرأها الحاسوب ويحفظها في ذاكرته
الرئيسية ويبدأ بتفيذها واحدة واحدة دون تدخل الإنسان،
إلا عندما تطلب منه هذه التعليمات ذلك بأن ينظر ماذا ضغط المستخدم
وماذا تقول لوحة المفاتيح وأين تضغط الفأرة.
كما تعمل هذه التعليمات بصمت حتى يكون هناك تعليمات تطلب
منه كتابة شيء على الشاشة أو طباعة شيء أو إصدار صوت.
سلسلة التعليمات هذه تسمى برنامج
يمكن أن تكون هذه البرامج على شكل لغة عالية المستوى
أي قريبة من لغة البشر والتعابير الرياضية
ويسمى الملف الذي يحتوي هذه التعليمات النصية الكود المصدر source code
اكتب "ما هو الطول :" اسأل عن ل اكتب "ما هو العرض :" اسأل عن ع احسب م = ط × ع اكتب "المساحة تساوي" م
; 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 code
أو الملف الجاهز 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
001011
.
جمع الأرقام الثائية لا يختلف عن العشرية كثيراً
صفر + صفر = صفر ، صفر + واحد = واحد ، واحد + واحد = صفر وباليد واحد.
هذا المثال يوضح ذلك
3d + 13d = ? 3d = 000011b 13d = 001101b 1111 000011b 001101b + ---------- 010000b --> 16d
00001101b=13d 11110011b= ?? ~11110011b=00001100b 11110011b=-(00001100b+1)=-(00001101b)=-13d
13d + (-13)d = 0 1 1111111 00001101b 11110011b + ------------ 1 00000000b
00000000b
وتعيده خطوة للوراء 11111111b
أو خطوتين 11111110b
وهما يمثلان -1 و -2.
الضرب والقسمة عمليتان تأخذان الكثير من الوقت ولكن كحالة خاصة يمكن القيام بهما بسرعة فالضرب والقسمة في 2 مرفوعة لأي قوة (صحيحة) هو إزحة لليسار واليمين على الترتيب بعدد من المنازل تساوي القوة وهي تشبه الضرب في 10 والقسمة عليه في النظام العشري مثلاً:
11d x 8d = 11d x 23d 0001011b << 2d = 1011000b = 88d
هذا بالنسبة للأعداد الصحيحة أما النسبية فيتم التعامل
معها عبر تمثيل يسمى بالفاصلة العائمة float-point
وهي تشبه التمثيل الهندسي للأرقام مثلاً
سرعة الضوء 0.3x109
كم/س
و شحنة الإلكترون 0.16x10-18
كولوم
وهكذا ... لاحظ أن المنزلة الأولى بعد الفاصلة
لا تمثل عشراً بل تعتمد قيمتها على القوة التي نرفع لها العشرة
فيكون الرقم عدة أجزاء (رقم صحيح هو القوة والجزء النسبي)
العمليات التي يمكن القيام بها مثل عمليات "و" و "أو" و "أو الحصرية" تقسم إلى نوعين منطقية وثنائية المنطقية نأخذ قيمة كل رقم هل هي صفر أم لا أما الثنائية فنتعامل مع كل منزلة في الطرفين. تستخدم ‘أو‘ لوضع واحد في منزلة محددة سواء أكانت قيمته السابقة 1 أم 0 أما أو الحصرية XOR فهي تعطي واحد إذا كان أحد الطرفين واحد وليس كلاهما. أما ‘و‘ فهي تعطي واحد إذا كان كلا الطرفين واحد. انظر هذا المثال:
110110b 110110b 110110b 001100b | 001100b & 001100b ^ -------- -------- -------- 111110b 000100b 111010b
الوحدات الأساسية هي
عندما يعمل الحاسوب يتم تشغيل برنامج موجود في ذاكرة القراءة فقط ROM في شريحة اسمها BIOS أي نظام الإدخال والإخراج الأساسي - Basic Input/Output System
ROM في الحقيقة ليست للقراءة فقط؛ إذ يوجد أنواع قابلة لإعادة البرمجة (منها بالأشعة أو بأجهزة خاصة) ولكن الكتابة بها مسؤولية الشركة الصانعة فقط.
إذا أخذ جهازان نفس المنفذ فهذا يسمى تضارب conflict وكان يتم حله بتوصيل jumpers أما الآن فتتم في بطاقات من نوع ISA من خلال تقنية PNP. وهذه المشكلة غير مجودة في بطاقات PCI الأحدث وتقنية PNP بلا معنى فيها.
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 تكون مقلوبة "من" ثم "إلى" وليس العكس.
اسم ملفات GAS ينتهي ب S مثل hello.S ويتم تحويله إلى ملف تنفيذي بواسطة as كما يلي
as hello.S -o hello.o && ld -s -o hello hello.o
في مستوى أعلى تأتي المكتبة في لغات البرمجة عالية المستوى مثل سي فبدلاً من حفظ أرقام وجداول لديك أسماء سهلة الحفظ مثل open. كما أن لغات البرمجة توفر واجهة موحدة على الأنظمة المختلفة والأجهزة المختلفة مثل لغة سي ولكن بعض اللغات مثل VB لا تعمل سوى على نظام واحد.
ما تحدثنا عنه في نظام التشغيل كان شيئاً لا تراه إنه يعمل بين البرنامج أو المكتبة من جهة وبين الأجهزة من جهة أخرى؛ هذا ما نسميه نواة. ولكن بقية نظام التشغيل التي تتعامل معها تسمى أدوات النظام أو برمجيّات النظام. في بعض الأنظمة يكون كل شيء قطعة واحدة صندوق أسود BlackBox لا تستطيع فصل هذه عن تلك ولكن في جنو/لينكس النواة هي لينكس والبرمجيات من جنو (يوجد خيارات أخرى مثل GNU/HURD)
عندما تكتب برنامج بلغة معينة فإنك تكتبه بمحرر نصوص وهذا أول وأبسط مكونات برمجيّات النظام ففي جنو كان محرر emacs أول قطعة فيه (هل قلت أبسط !؟) ثم يأتي المصنف compiler الذي يمكنك من تحويل كود اللغة إلى برنامج يمكن تنفيذه وطبعاً لا ننس مفسر الأوامر التي تطبعها. في بعض الأنظمة تكون الواجهة الرسومية جزء من النظام ولا يمكن تخطيها
التعريفات 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.
أما النظام لينكس فهو الوحيد الذي يمتاز ب 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"); }
معظم الأنظمة هي أنظمة Monolithic ولينكس واحد منها. النوع الآخر هو النواة الميكروية Microkernel مثل نواة GNU/HURD المسماة Mach Microkernel في هذا النوع تقسم النواة إلى عدة مهام منفصلة تعمل معاً inter-kernel tasks أو kernel threads (ليس كما modules من ناحية وجودها في ملف منفصل بل في كون كل منها يعمل كبرنامج منفصل process أما modules فتستدعى عند الحاجة فقط) ذلك يضيف سهولة في التصميم والتطوير وسلاسة في العمل ولكنه يزيد من العبئ حيث يتم التبديل بينها بعدد مهمات النواة مرتين (دخولاً وخروجاً) مضروباً في زمن الإنتظار بين التبديل بين المهمات مما يضيع الكثير من الوقت. يختلف لينكس عن الأنظمة الأخرى ذلك مع أنه نظام Monolithic ولكنه يشبه ال microkernel في أن به kernel threads مثل kswapd ولكنها محدودة في عدد قليل (ربما 4) وهي التي هناك جدوى منها فقط. قلة عددها قلل من العبئ الذي تحدثنا عنه كم أن مهمتها منتقاة بعناية (فقط تلك التي تحتاج عمليات I/O طويلة) بحيث فلا تأخذ كامل وقت التبديل بين كل مهمتين لأن خوارزمية التبديل بين المهمات هي التبديل عند إنقضاء الزمن أو النوم بإنتظار عملية I/O أيهما يأتي أولاً. مرة أخرى نجد أن التصميم العبقري للينكس يجمع حسنات أفضل الطرق المعروفة ويتجنب سيئاتها.
هناك أمر غريب جداً في تصميم الأجهزة PC من عائلة
80x86
التي ينتمي لها البينتيوم وهي قصة طويلة.
حيث تم تصميمها على أساس أن أكبر سعة للذاكرة هي 640 كيلو-بايت
ولكن في البداية (قبل أن تكون الكلمة 32-بت) كان المسجل 16 بت
التي تكفي لعنونة 0xFFFF
ست-عشري أي 64 كيلو-بايت فقط
فحن بحاجة إلى 20-بت (وهو عرض الناقل bus في أجهزة 8086 الجد الأكبر) ،
أي نصف بايت (منزلة ست-عشرية) تسمى physical page
، ولأن سعة المسجل الواحد 16 بت فقط
فنحن بحاجة لمسجل آخر. يسمى الأول إزاحة offset والثاني
مقطع segment يرمز له بالطريقة segment:offset
ولكن بدلاً من وضع physical page
من الجهة الأقل أهمية تم وضعه في الأكثر أهمية مما يعني
أن البايت بالعنوان الفيزيائي 0x51234
0x5000:0x1234
أو 0x5100:0x0234
أو
0x5120:0x0034
أو 0x5124:0x0004
كلها تشير لنفس العنوان وذلك بجمع الإزاحة و المقطع بعد ضربه في 16
أي إزاحته لليسار منزلة ست-عشرية. وهذا يعطينا 20 بت أي واحد ميغا-بايت فقط
على الرغم من استعمال 32 بت التي يمكنها ترميز 4 غيغا-بايت.
السبب هو الفرض بأن كل برنامج يجب أن يعمل في مقطع منفصل
لأن تعليمات لغة الآلة تقول إقفز إلى العنوان رقم كذا
فإن تحمل البرنامج في عنوان آخر علينا كتابته من جديد
فقالو نقسم الذاكرة إلى مقاطع يحمل فيها البرنامج
ويكون العنوان هو الإزاحة عن بداية المقطع.
ولو جعلنا المقطع هو physical page ذلك يعني أن لدينا 16 مقطع فقط
أي يسمح بتشغيل 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.
نظام ويندوز عبارة عن جزئين في البداية
يظهر الشعار -اضغط ESC- لترى دووس
يعمل في الطور الحقيقي يقوم بتحميل التعريفات من ملف config.sys
مثل نظام HIMEM.SYS ثم تنفيذ autoexec.bat وربما بعض الفيروسات
أو تكون حملت قبلاً مع قطاع رقم صفر
(لا شيء مرئي إلى الآن سوى أول ميغا)
ثم ينتقل للطور المحمي وبقية النظام متعدد المهام والواجهة الرسومية ... إلخ
بمجرد الانتقال للطور المحمي لا يمكن تنفيذ برامج دووس
لأنها لا تستدعي المقاطعات عبر 0x31
كما أن الذاكرة التقليدية قد تكون مليئة ويحمل البرنامج خارج أول ميغا
فلا يستطيع برنامج دووس بطريقة segment/offset أن يرى نفسه؛
لهذا يقوم ويندوز بمحاكاة خووس (داخل البئية الرسومية محاكاة ولكن قبلها
تفيذ حقيقي وإذا اخترت restart in dos mode يعمل دووس حقيقي)
هذه المحاكاة تعمل على إظهار أن البرنامج لا يزال داخل أول ميغا.
الخطورة في هذا التصميم بأن البرامج(الفيروسات) قبل الدخول في الطور المحمي يمكنها
استعمال EMS و XMS للوصول لأي جزء من الذاكرة داخل وخارج البرنامج كما أن النظام
ليس له أي سلطة عليها.
النظام لينكس صمم والأمان في البال بالطبع لم يتبع هكذا التصميم. بمجرد تحميل نواة لينكس أول ما تقوم به هو الدخول في الطور المحمي. ويختلف لينكس عن باقي الأنظمة بأنه يقسم الذاكرة إلى 4 مقاطع segments فقط (النواة وبيانتها والبرامج وبياناتها) على عكس الأنظمة الأخرى التي تخصص مقطع لكل برنامج كما ذكرنا كما أن فصل النواة في مقطع يجعلها بعيدة عن عبث البرامج. كما أن هذا التقسيم يجعله يوفر في الذاكرة عند تشغيل برنامج/مكتبة أكثر من مرة حيث يحجز له مرة واحدة كبرنامج وبعدد المرات كبيانات، فكود البرنامج نفسه في كل مرة وفقط تختلف البيانات. ويحل مشكلتي segmentation و pagentation معاً. الأولى بالتقسيم لصفحات والثانية بجعل حجم الصفحة 4 كيلو-بايت فقط دون دفع ثمن ذلك من السرعة لأنه يرتبها في Hierarchical Paging تستخدم خوارزميات تسريع مثل Binary search tree (في كل دورة تقسم المجموعة إلى نصفين تهمل مجموعة وتبحث في الثاني بنفس الطريقة). كل البرامج تعطى عناوين افتراضية والنواة وحدها من يستعمل العناوين الفيزيائية المطلقة لهذا كل برنامج لا يستطيع الوصول لذاكرة برنامج آخر. الطريقة الوحيدة ليرى برنامج جزء من ذاكرة برنامج آخر هي عبر قسم/ملف التبديل swap
عملية التبديل swap هي عملية توليد ذاكرة افتراضية وهمية فعند الحاجة للمزيد من الذاكرة يتم البحث عن جزء غير مستعمل (برنامج نائم) ، وإرساله (أو جزء/صفحة منه ) للقرص الصلب وتحرير الذاكرة التي كان يشغلها. عند الحاجة لجزء موجود على القرص الصلب يبحث عن جزء آخر غير مستعمل ليأخذ مكانه ومن هنا جاء الاسم. ولا نحتاج لتعديل البرامج لأن العناوين التي مع البرامج افتراضية يديره نظام التشغيل.
لهذا تحصل تحذير ذاكرة غير آمنة عند توليد مفتاح في برنامج ssh لغير الجذر!
<< السابق | كتاب لينكس الشامل | التالي >> |