مؤشر مُوسوم

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

طي العلامات داخل المؤشر

توجد تقنيات متنوعة لتحويل العلامات إلى مؤشر. [ 1 ]

معظم البنى المعمارية قابلة للعنونة بالبايت (أصغر وحدة عنونة هي البايت)، ولكن بعض أنواع البيانات غالبًا ما تُحاذى وفقًا لحجم البيانات، والذي يكون عادةً كلمة أو مضاعفاتها. هذا التباين يُبقي بعض البتات الأقل أهمية في المؤشر غير مستخدمة، والتي يمكن استخدامها للعلامات - غالبًا كحقل بت (كل بت علامة منفصلة) - بشرط أن يقوم الكود الذي يستخدم المؤشر بحجب هذه البتات قبل الوصول إلى الذاكرة. على سبيل المثال، في بنية معمارية 32 بت (للعناوين وحجم الكلمة)، الكلمة هي 32 بت = 4 بايت، لذا فإن العناوين المحاذية للكلمة هي دائمًا من مضاعفات 4، وبالتالي تنتهي بـ 00، مما يترك آخر بتتين متاحتين؛ بينما في بنية معمارية 64 بت ، الكلمة هي 64 بت = 8 بايت، لذا فإن العناوين المحاذية للكلمة تنتهي بـ 000، مما يترك آخر 3 بتات متاحة. في الحالات التي تُحاذى فيها البيانات بمضاعفات حجم الكلمة، تتوفر بتات إضافية. في حالة البنى القابلة للعنونة بالكلمات ، لا تترك البيانات المحاذية للكلمات أي بتات متاحة، حيث لا يوجد تباين بين المحاذاة والعنونة، ولكن البيانات المحاذية بمضاعفات حجم الكلمة تفعل ذلك.

في المقابل، في بعض أنظمة التشغيل، تكون العناوين الافتراضية أضيق من عرض بنية المعالج الكلية، مما يتيح استخدام البتات الأكثر أهمية للوسوم؛ ويمكن دمج ذلك مع الأسلوب السابق في حالة العناوين المُحاذية. وينطبق هذا بشكل خاص على معالجات 64 بت، حيث أن 64 بت من مساحة العناوين تتجاوز بكثير متطلبات البيانات لجميع التطبيقات باستثناء التطبيقات الكبيرة جدًا، وبالتالي فإن العديد من معالجات 64 بت العملية لها عناوين أضيق. تجدر الإشارة إلى أن عرض العنوان الافتراضي قد يكون أضيق من عرض العنوان الفعلي ، والذي بدوره قد يكون أضيق من عرض بنية المعالج؛ بالنسبة لوسم المؤشرات في مساحة المستخدم ، فإن مساحة العنوان الافتراضي التي يوفرها نظام التشغيل (والتي توفرها بدورها وحدة إدارة الذاكرة ) هي العرض المناسب. في الواقع، تمنع بعض المعالجات تحديدًا استخدام هذه المؤشرات الموسومة على مستوى المعالج، ولا سيما x86-64 ، الذي يتطلب استخدام عناوين نموذجية من قِبل نظام التشغيل، حيث تكون البتات الأكثر أهمية إما أصفارًا أو آحادًا.

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

تاريخ

كان نظام IBM System/38 أحد أوائل الأمثلة على دعم الأجهزة للمؤشرات الموسومة في منصة تجارية . [ 2 ] أضافت IBM لاحقًا دعم المؤشرات الموسومة إلى بنية PowerPC لدعم نظام التشغيل IBM i ، وهو تطوير لمنصة System/38. [ 3 ]

من الأمثلة البارزة على استخدام المؤشرات الموسومة بيئة تشغيل Objective-C على نظام iOS 7 على معالجات ARM64 ، والتي تُستخدم بشكل خاص في هاتف iPhone 5S . في نظام iOS 7، تحتوي العناوين الافتراضية على 33 بت فقط من معلومات العنوان، بينما يبلغ طولها 64 بت، مما يترك 31 بت للوسوم. أما مؤشرات فئات Objective-C فهي مُحاذية لـ 8 بايت، مما يُحرر 3 بت إضافية من مساحة العنوان، وتُستخدم حقول الوسوم لأغراض متعددة، مثل تخزين عدد المراجع وما إذا كان للكائن مُدمِّر . [ 4 ] [ 5 ]

استخدمت الإصدارات الأولى من نظام macOS عناوين مُوسومة تُسمى "المقابض" لتخزين مراجع لكائنات البيانات. تشير البتات العليا من العنوان إلى ما إذا كان كائن البيانات مُقفلًا، أو قابلًا للحذف، أو مصدره ملف موارد، على التوالي. تسبب هذا في مشاكل توافق عندما تطورت عنونة macOS من 24 بت إلى 32 بت في النظام 7. [ 6 ]

المؤشر الفارغ مقابل المؤشر المحاذي

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

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

في بنية البيانات الموسومة ، يتم حجز عدد من البتات في كل كلمة من الذاكرة لتكون بمثابة وسم. غالبًا ما تتمتع البنى الموسومة، مثل أجهزة لغة ليسب ، بدعم برمجي لتفسير ومعالجة المؤشرات الموسومة.

توفر مكتبة GNU libcmalloc() عناوين ذاكرة محاذية لثمانية بايتات لمنصات 32 بت، ومحاذية لستة عشر بايتًا لمنصات 64 بت. [ 7 ] ويمكن الحصول على قيم محاذاة أكبر باستخدام [ 8 ]posix_memalign() .

أمثلة

المثال 1

في كود C التالي، تُستخدم القيمة صفر للإشارة إلى مؤشر فارغ:

void optionally_return_a_value ( int * optional_return_value_pointer ) { /* ... */ int value_to_return = 1 ;/* هل هو ليس NULL؟ (لاحظ أن NULL، والخطأ المنطقي، والصفر متساوية في لغة C) */ if ( optional_return_value_pointer ) /* إذا كان الأمر كذلك، فاستخدمه لتمرير قيمة إلى الدالة المستدعِية */ * optional_return_value_pointer = value_to_return ;/* وإلا، فلن يتم إلغاء مرجعية المؤشر أبدًا */ }

المثال 2

هنا، قام المبرمج بتوفير متغير عام، يتم استخدام عنوانه كحارس:

#تعريف سينتينل &sentinel_snode_t sentinel_s ;void do_something_to_a_node ( node_t * p ) { if ( NULL == p ) /* نفّذ شيئًا ما */ else if ( SENTINEL == p ) /* نفّذ شيئًا آخر */ else /* تعامل مع p كمؤشر صالح إلى عقدة */ }

المثال 3

لنفترض أن لدينا بنية بيانات table_entryمحاذية دائمًا لحدود 16 بايت. بعبارة أخرى، تكون البتات الأربع الأقل أهمية في عنوان مدخل الجدول دائمًا صفرًا ( 2 ^4 = 16 ). يمكننا استخدام هذه البتات الأربع لتمييز مدخل الجدول بمعلومات إضافية. على سبيل المثال، قد يعني البت 0 أنه للقراءة فقط، وقد يعني البت 1 أنه غير مُعدّل (يحتاج مدخل الجدول إلى التحديث)، وهكذا.

إذا كانت المؤشرات عبارة عن قيم مكونة من 16 بت، فإن:

  • 0x3421هو مؤشر للقراءة فقط إلى table_entryالعنوان at0x3420
  • 0xf472هو مؤشر إلى table_entryعنوان مُعدَّل0xf470

المزايا

تتمثل الميزة الرئيسية للمؤشرات الموسومة في أنها تشغل مساحة أقل من المؤشر مع حقل وسم منفصل. وهذا الأمر بالغ الأهمية، خاصةً عندما يكون المؤشر قيمة مُعادة من دالة . كما أنه مهم أيضًا في جداول المؤشرات الكبيرة.

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

العيوب

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

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

مراجع

  1. أسئلة وأجوبة يوم الجمعة 27 يوليو 2012: لنقم ببناء مؤشرات مُوسومة ، بقلم مايك آش
  2. ليفي، هنري م. (1984). "نظام IBM/38" (ملف PDF) . أنظمة الحاسوب القائمة على القدرات . دار النشر الرقمية. ISBN 0-932376-22-3.
  3. فرانك ج. سولتيس (1997). داخل نظام AS/400، الطبعة الثانية . دار نشر ديوك. رقم ISBN 978-1882419661.
  4. أسئلة وأجوبة يوم الجمعة 27-09-2013: ARM64 وأنت ، بقلم مايك آش
  5. [objc explain]: مجموعة بيانات غير مؤشرة
  6. بريكنيل، كي جيه ماكنتوش سي: دليل الهواة لبرمجة نظام التشغيل ماك باستخدام لغة سي .
  7. "أمثلة على استخدام دالة malloc" . مكتبة GNU C. تم الاطلاع عليه بتاريخ 5 سبتمبر 2018 .
  8. دليل مبرمج لينكس – وظائف المكتبة من Manned.orgposix_memalign(3)