قراءة - نسخ - تحديث

في علوم الحاسوب ، تُعدّ آلية القراءة والنسخ والتحديث ( RCU ) آلية تزامن تتجنب استخدام أدوات القفل الأساسية، حيث تقوم عدة خيوط في وقت واحد بقراءة وتحديث العناصر المرتبطة عبر المؤشرات والتي تنتمي إلى هياكل بيانات مشتركة (مثل القوائم المرتبطة ، والأشجار ، وجداول التجزئة ). [ 1 ]

عندما يقوم أحد الخيوط بإدراج أو حذف عناصر من هياكل البيانات في الذاكرة المشتركة ، يضمن لجميع القراء رؤية وتصفح إما الهيكل القديم أو الجديد، وبالتالي تجنب التناقضات (مثل فك مرجعية المؤشرات الفارغة ). [ 1 ]

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

الاسم ونظرة عامة

يُستمد الاسم من طريقة استخدام RCU لتحديث بنية مرتبطة في مكانها. يستخدم الخيط الذي يرغب في القيام بذلك الخطوات التالية:

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

لذا، تُقرأ البنية بالتزامن مع عملية نسخ البيانات في سلسلة العمليات لإجراء التحديث ، ومن هنا جاء اسم "تحديث القراءة والنسخ". يُعدّ الاختصار "RCU" أحد المساهمات العديدة من مجتمع لينكس. ومن الأسماء الأخرى للتقنيات المشابهة: التسلسل السلبي وتأجيل MP من قِبل مبرمجي VM/XA، وتقنية الأجيال من قِبل مبرمجي K42 و Tornado .

وصف تفصيلي

إجراء إدراج القراءة والنسخ والتحديث. يقوم مؤشر ترابط بتخصيص بنية بثلاثة حقول، ثم يقوم بتعيين المؤشر العام gptr ليشير إلى هذه البنية.

من الخصائص الأساسية لتقنية RCU أن القراء يمكنهم الوصول إلى بنية البيانات حتى أثناء تحديثها: لا تستطيع برامج تحديث RCU منع القراء أو إجبارهم على إعادة محاولة الوصول. تبدأ هذه النظرة العامة بتوضيح كيفية إدراج البيانات وحذفها من البنى المرتبطة بأمان رغم وجود قراء متزامنين. يوضح الرسم التخطيطي الأول على اليمين إجراء إدراج من أربع مراحل، مع تقدم الوقت من اليسار إلى اليمين.

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

إجراء الحذف بالقراءة والنسخ والتحديث

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

تُظهر الحالة الأولى قائمة مرتبطة تحتوي على العناصر A و B و C. جميع العناصر الثلاثة مُلوّنة باللون الأحمر للإشارة إلى إمكانية وصول قارئ RCU إليها في أي وقت. باستخدام دالة list_del_rcu لإزالة العنصر B من هذه القائمة، ننتقل إلى الحالة الثانية. لاحظ أن الرابط من العنصر B إلى C يبقى سليمًا للسماح للقراء الذين يشيرون حاليًا إلى العنصر B بالوصول إلى بقية القائمة. سيحصل القراء الذين يصلون إلى الرابط من العنصر A إما على مرجع إلى العنصر B أو العنصر C ، ولكن في كلتا الحالتين، سيرى كل قارئ قائمة مرتبطة صالحة ومنسقة بشكل صحيح. يُلوّن العنصر B الآن باللون الأصفر للإشارة إلى أنه بينما قد لا يزال لدى القراء الحاليين مرجع إلى العنصر B ، لا يمكن للقراء الجدد الحصول على مرجع إليه. تنتقل عملية انتظار القراء إلى الحالة الثالثة. لاحظ أن عملية انتظار القراء هذه لا تحتاج إلا إلى انتظار القراء الحاليين، وليس القراء الجدد. يُلوّن العنصر B الآن باللون الأخضر للإشارة إلى أنه لم يعد بإمكان القراء الإشارة إليه. لذلك، أصبح من الآمن الآن للمحدث تحرير العنصر B ، وبالتالي الانتقال إلى الحالة الرابعة والأخيرة.

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

توضح هذه العملية كيفية إزالة البيانات القديمة من بنية بيانات مرتبطة، حتى وإن كان القراء يتصفحون بنية البيانات في الوقت نفسه قبل الحذف وأثناءه وبعده. وبالنظر إلى إمكانية الإضافة والحذف، يمكن تطبيق مجموعة واسعة من هياكل البيانات باستخدام RCU.

تُنفَّذ عمليات قراءة RCU ضمن أقسام حرجة للقراءة ، والتي تُحدَّد عادةً بواسطة rcu_read_lock و rcu_read_unlock . يُقال إن أي عبارة لا تقع ضمن قسم حرج للقراءة في RCU تكون في حالة سكون ، ولا يُسمح لهذه العبارات بالاحتفاظ بمراجع لهياكل البيانات المحمية بواسطة RCU، كما لا يُشترط على عملية انتظار القراء انتظار الخيوط في حالات السكون. تُسمى أي فترة زمنية يقضيها كل خيط مرة واحدة على الأقل في حالة سكون بفترة سماح . بحسب التعريف، يجب أن يكتمل أي قسم حرج للقراءة في RCU موجود في بداية فترة سماح معينة قبل نهاية تلك الفترة، وهو ما يُمثل الضمان الأساسي الذي تُوفره RCU. بالإضافة إلى ذلك، يجب أن تنتظر عملية انتظار القراء انقضاء فترة سماح واحدة على الأقل. اتضح أن هذا الضمان يمكن توفيره مع تكاليف إضافية ضئيلة للغاية على جانب القراءة، في الواقع، في الحالة القصوى التي يتم تحقيقها فعليًا بواسطة إصدارات نواة لينكس من فئة الخادم، تكون التكاليف الإضافية على جانب القراءة صفرًا تمامًا. [ 2 ]

يمكن الاستفادة من الضمان الأساسي لـ RCU بتقسيم التحديثات إلى مرحلتي إزالة واستعادة . تزيل مرحلة الإزالة المراجع إلى عناصر البيانات داخل بنية البيانات (ربما باستبدالها بمراجع إلى إصدارات جديدة من هذه العناصر) ، ويمكن تشغيلها بالتزامن مع الأقسام الحرجة للقراءة في RCU. يكمن سبب أمان تشغيل مرحلة الإزالة بالتزامن مع قارئات RCU في أن دلالات وحدات المعالجة المركزية الحديثة تضمن أن القارئات سترى إما الإصدار القديم أو الجديد من بنية البيانات، وليس مرجعًا مُحدَّثًا جزئيًا. بمجرد انقضاء فترة السماح، لن يكون هناك أي قارئات تُشير إلى الإصدار القديم، وبالتالي يصبح من الآمن لمرحلة الاستعادة تحرير ( استعادة ) عناصر البيانات التي كانت تُشكِّل ذلك الإصدار القديم. [ 3 ]

يُتيح تقسيم التحديث إلى مرحلتي الإزالة والاستعادة للمُحدِّث تنفيذ مرحلة الإزالة فورًا، وتأجيل مرحلة الاستعادة حتى اكتمال جميع القراء النشطين خلال مرحلة الإزالة، أي حتى انقضاء فترة سماح. [ ملاحظة 1 ]

لذا، فإن تسلسل تحديث RCU النموذجي يسير على النحو التالي: [ 4 ]

  1. تأكد من أن جميع القراء الذين يصلون إلى هياكل البيانات المحمية بواسطة RCU يقومون بإجراء مراجعهم من داخل قسم RCU الحرج للقراءة.
  2. قم بإزالة المؤشرات إلى بنية البيانات، بحيث لا يتمكن القراء اللاحقون من الحصول على مرجع لها.
  3. انتظر حتى تنقضي فترة سماح، بحيث يكون جميع القراء السابقين (الذين قد لا يزال لديهم مؤشرات إلى بنية البيانات التي تمت إزالتها في الخطوة السابقة) قد أكملوا أقسامهم الحرجة للقراءة RCU.
  4. في هذه المرحلة، لا يمكن أن يكون هناك أي قارئين لا يزالون يحتفظون بمراجع لبنية البيانات، لذا يمكن الآن استعادتها بأمان (مثلاً، تحريرها). [ ملاحظة 2 ]

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

ربما تكون خوارزمية RCU هي الخوارزمية غير الحظرية الأكثر شيوعًا لهياكل البيانات المشتركة. تتميز RCU بأنها لا تتطلب أي انتظار مهما كان عدد القراء. كما أن تطبيقات RCU أحادية الكاتب لا تتطلب أي تأمين للكاتب. [ 5 ] بعض تطبيقات RCU متعددة الكتاب لا تتطلب تأمينًا أيضًا. [ 6 ] بينما تقوم تطبيقات أخرى متعددة الكتاب بتسلسل الكتاب باستخدام تأمين. [ 7 ]

الاستخدامات

بحلول أوائل عام 2008، بلغ عدد استخدامات واجهة برمجة تطبيقات RCU في نواة لينكس ما يقارب 2000 استخدام [ 8 ] ، بما في ذلك حزم بروتوكولات الشبكات [ 9 ] ونظام إدارة الذاكرة [ 10 ] . واعتبارًا من مارس 2014 بلغ عدد استخداماته أكثر من 9000 استخدام. [ 11 ] منذ عام 2006، طبّق الباحثون تقنية RCU وتقنيات مشابهة على عدد من المشكلات، بما في ذلك إدارة البيانات الوصفية المستخدمة في التحليل الديناميكي، [ 12 ] وإدارة دورة حياة الكائنات المجمعة، [ 13 ] وإدارة دورة حياة الكائنات في نظام التشغيل البحثي K42 ، [ 14 ] [ 15 ] وتحسين تطبيقات ذاكرة المعاملات البرمجية . [ 16 ] [ 17 ] يستخدم نظام Dragonfly BSD تقنية مشابهة لتقنية RCU، وهي الأقرب إلى تطبيق Sleepable RCU (SRCU) في نظام Linux.

المزايا والعيوب

تتيح إمكانية الانتظار حتى انتهاء جميع القراء لقارئات RCU استخدام مزامنة أخف وزنًا بكثير ، وفي بعض الحالات، الاستغناء عن المزامنة تمامًا. في المخططات التقليدية القائمة على الأقفال، يجب على القراء استخدام مزامنة ثقيلة الوزن لمنع المُحدِّث من حذف بنية البيانات دون علمهم. والسبب هو أن المُحدِّثات القائمة على الأقفال تُحدِّث البيانات عادةً في مكانها، وبالتالي يجب استبعاد القراء. في المقابل، تستفيد المُحدِّثات القائمة على RCU عادةً من حقيقة أن الكتابة إلى مؤشرات مُحاذية مفردة هي عمليات ذرية على وحدات المعالجة المركزية الحديثة، مما يسمح بالإدراج والإزالة والاستبدال الذري للبيانات في بنية مرتبطة دون تعطيل القراء. يمكن لقارئات RCU المتزامنة بعد ذلك الاستمرار في الوصول إلى الإصدارات القديمة والاستغناء عن تعليمات القراءة والتعديل والكتابة الذرية، وحواجز الذاكرة، وأخطاء ذاكرة التخزين المؤقت التي تُعد مكلفة للغاية على أنظمة الكمبيوتر SMP الحديثة ، حتى في حالة عدم وجود تنازع على الأقفال. [ 18 ] [ 19 ] توفر الطبيعة الخفيفة لعناصر القراءة الأساسية في RCU مزايا إضافية تتجاوز الأداء الممتاز وقابلية التوسع والاستجابة في الوقت الفعلي. فعلى سبيل المثال، توفر هذه الأدوات مناعة ضد معظم حالات الجمود والتوقف المؤقت . [ ملاحظة 3 ]

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

تُعد إمكانية تطبيق RCU موضوعًا لبحث مستمر.

براءات الاختراع

تُغطّي هذه التقنية براءة اختراع أمريكية للبرمجيات رقم 5,442,758 ، الصادرة في 15 أغسطس 1995، والمُسجّلة باسم شركة سيكوينت لأنظمة الحاسوب ، بالإضافة إلى براءات اختراع أمريكية أخرى هي: 5,608,893 (انتهت صلاحيتها في 30 مارس 2009)، و5,727,209 (انتهت صلاحيتها في 5 أبريل 2010)، و6,219,690 (انتهت صلاحيتها في 18 مايو 2009)، و 6,886,162 (انتهت صلاحيتها في 25 مايو 2009). وتُغطي براءة الاختراع الأمريكية رقم 4,809,168، التي انتهت صلاحيتها أيضاً، تقنيةً وثيقة الصلة. كما تُعدّ تقنية RCU موضوع إحدى الدعاوى القضائية المرفوعة من قِبل شركة SCO ضد شركة IBM .

نموذج واجهة وحدة التحكم عن بعد

يتوفر RCU في عدد من أنظمة التشغيل، وقد أُضيف إلى نواة لينكس في أكتوبر 2002. كما تتوفر تطبيقات على مستوى المستخدم مثل liburcu . [ 20 ]

يُعدّ تطبيق RCU في الإصدار 2.6 من نواة لينكس من بين أشهر تطبيقات RCU، وسيُستعان به كمصدر إلهام لواجهة برمجة تطبيقات RCU في بقية هذا المقال. تتميز واجهة برمجة التطبيقات الأساسية (API ) بصغر حجمها نسبيًا: [ 21 ]

  • rcu_read_lock(): يقوم بوضع علامة على بنية بيانات محمية بواسطة RCU بحيث لا يتم استعادتها طوال مدة ذلك القسم الحرج.
  • rcu_read_unlock(): يستخدمها القارئ لإعلام المُسترجع بأن القارئ يخرج من قسم حرج للقراءة في وحدة التحكم بالقراءة (RCU). يُرجى ملاحظة أن الأقسام الحرجة للقراءة في وحدة التحكم بالقراءة (RCU) قد تكون متداخلة أو متشابكة.
  • تقوم الدالة synchronize_rcu() بحظر التنفيذ حتى اكتمال جميع أقسام القراءة الحرجة الموجودة مسبقًا في RCU على جميع وحدات المعالجة المركزية. لاحظ أنها لنsynchronize_rcu تنتظر بالضرورة اكتمال أي أقسام قراءة حرجة لاحقة في RCU. على سبيل المثال، انظر إلى تسلسل الأحداث التالي:
 وحدة المعالجة المركزية 0 وحدة المعالجة المركزية 1 وحدة المعالجة المركزية 2 ----------------- ------------------------- --------------- 1. rcu_read_lock() 2. يدخل إلى synchronize_rcu() 3. rcu_read_lock() 4. rcu_read_unlock() 5. الخروج من synchronize_rcu() 6. rcu_read_unlock() 
بما synchronize_rcuأن واجهة برمجة التطبيقات (API) هي المسؤولة عن تحديد وقت انتهاء عمليات القراءة، فإن تنفيذها يُعدّ أساسيًا لتقنية RCU. ولكي تكون RCU مفيدة في جميع الحالات باستثناء الحالات التي تتطلب قراءة مكثفة للغاية، synchronize_rcuيجب أن يكون الحمل الزائد لواجهة برمجة التطبيقات صغيرًا جدًا.
بدلاً من ذلك، وبدلاً من الحظر، قد تُسجّل دالة synchronize_rcu دالة رد نداء ليتم استدعاؤها بعد اكتمال جميع الأقسام الحرجة الجارية في جانب القراءة من RCU. يتم استدعاء هذا النوع من دوال رد النداء call_rcuفي نواة لينكس.
  • rcu_assign_pointer(): يستخدم المُحدِّث هذه الدالة لتعيين قيمة جديدة لمؤشر محمي بواسطة RCU، وذلك لضمان نقل التغيير في القيمة من المُحدِّث إلى القارئ بشكل آمن. تُعيد هذه الدالة القيمة الجديدة، وتُنفِّذ أيضًا أي تعليمات لحاجز الذاكرة المطلوبة لبنية وحدة المعالجة المركزية المُحدَّدة. ولعل الأهم من ذلك، أنها تُوثِّق المؤشرات المحمية بواسطة RCU.
  • تُستخدم الدالة rcu_dereference() rcu_dereferenceلجلب مؤشر محمي بواسطة RCU، حيث تُعيد قيمةً يمكن الوصول إليها بأمان. كما تُنفّذ أي توجيهات مطلوبة من قِبل المُصرّف أو وحدة المعالجة المركزية، مثل التحويل المتقلب لـ gcc، أو تحميل memory_order_consume لـ C/C++11، أو تعليمة حاجز الذاكرة المطلوبة لوحدة المعالجة المركزية القديمة DEC Alpha. القيمة المُعادة rcu_dereferenceصالحة فقط داخل القسم الحرج للقراءة من جانب RCU. وكما هو الحال مع الدالة rcu_dereference() rcu_assign_pointer، فإن إحدى الوظائف المهمة للدالة rcu_dereferencercu_dereference() هي توثيق المؤشرات المحمية بواسطة RCU.
اتصالات واجهة برمجة تطبيقات RCU بين القارئ والمحدث والمسترجع

يوضح الرسم البياني على اليمين كيفية تواصل كل واجهة برمجة تطبيقات بين القارئ والمحدث والمسترجع.

تراقب بنية RCU التسلسل الزمني rcu_read_lockللاستدعاءات لتحديد متى (1) يمكن rcu_read_unlockللاستدعاءات العودة إلى مستدعيها، ومتى (2) synchronize_rcuيمكن استدعاء وظائف رد الاتصال. وتعتمد التطبيقات الفعالة لبنية RCU بشكل كبير على التجميع لتوزيع تكاليفها الإضافية على استخدامات متعددة لواجهات برمجة التطبيقات المقابلة.call_rcusynchronize_rcucall_rcu

تنفيذ بسيط

يحتوي RCU على تطبيقات "تجريبية" بسيطة للغاية يمكن أن تساعد في فهم RCU. يعرض هذا القسم أحد هذه التطبيقات "التجريبية" التي تعمل في بيئة غير استباقية . [ 22 ]

void rcu_read_lock ( void ) { }void rcu_read_unlock ( void ) { }void call_rcu ( void ( * callback ) ( void * ), void * arg ) { // إضافة زوج رد الاتصال/الوسيط إلى قائمة }void synchronize_rcu ( void ) { int cpu , ncpus = 0 ;for each_cpu ( cpu ) schedule_current_task_to ( cpu );لكل عنصر في قائمة call_rcu ، يتم استدعاء دالة رد الاتصال ( الوسيط الخاص بالعنصر ) .

في نموذج الكود، يمكن تجاهل rcu_assign_pointerهذه rcu_dereferenceالعناصر دون فقدان الكثير من المعلومات. ومع ذلك، فهي ضرورية لكبح تحسينات المُصرّف الضارة ومنع وحدات المعالجة المركزية من إعادة ترتيب عمليات الوصول.

#define rcu_assign_pointer(p, v) ({ \  smp_wmb(); /* ترتيب عمليات الكتابة السابقة. */ \  ACCESS_ONCE(p) = (v); \ })#define rcu_dereference(p) ({ \  typeof(p) _value = ACCESS_ONCE(p); \  smp_read_barrier_depends(); /* nop on most architectures */ \  (_value); \ })

لاحظ ذلك rcu_read_lockولا rcu_read_unlockتفعل شيئًا. هذه هي قوة RCU الكلاسيكية في نواة غير استباقية: تكلفة جانب القراءة تساوي صفرًا تمامًا، كما smp_read_barrier_depends()هو الحال مع الماكرو الفارغ على جميع وحدات المعالجة المركزية باستثناء DEC Alpha ؛ [ 23 ] لا حاجة لمثل هذه الحواجز في الذاكرة على وحدات المعالجة المركزية الحديثة. الماكرو عبارة عن تحويل متقلب لا يُولّد أي كود إضافي في معظم الحالات. ولا توجد طريقة يمكن أن تُشارك في حلقة جمود ، أو تتسبب في تفويت عملية الوقت الحقيقي لموعد جدولتها، أو تُؤدي إلى انعكاس الأولوية ، أو تُؤدي إلى تنازع شديد على القفل . ومع ذلك، في هذا التطبيق التجريبي لـ RCU، يُعد الحظر داخل القسم الحرج لجانب القراءة في RCU غير قانوني، تمامًا كما هو الحال مع الحظر أثناء الاحتفاظ بقفل دوراني خالص.ACCESS_ONCE()rcu_read_lock

ينقل تنفيذ synchronize_rcusynchronize_cpu الدالة المستدعِية إلى كل وحدة معالجة مركزية، مما يؤدي إلى حظر التنفيذ حتى تتمكن جميع وحدات المعالجة المركزية من إجراء تبديل السياق. تجدر الإشارة إلى أن هذه بيئة غير استباقية، وأن الحظر داخل قسم القراءة الحرج في RCU غير مسموح به، مما يعني أنه لا يمكن وجود نقاط استباق داخل قسم القراءة الحرج في RCU. لذلك، إذا نفذت وحدة معالجة مركزية معينة تبديل سياق (لجدولة عملية أخرى)، فإننا نعلم أن هذه الوحدة قد أكملت جميع أقسام القراءة الحرجة السابقة في RCU. بمجرد أن تنفذ جميع وحدات المعالجة المركزية تبديل سياق، ستكون جميع أقسام القراءة الحرجة السابقة في RCU قد اكتملت.

تشبيه بقفل القارئ والكاتب

على الرغم من إمكانية استخدام RCU بطرقٍ عديدة، إلا أن أحد استخداماته الشائعة جدًا يُشابه قفل القراءة والكتابة. يُظهر عرض الكود المتجاور التالي مدى الترابط الوثيق بين قفل القراءة والكتابة وRCU. [ 24 ]

/* قفل القارئ والكاتب */ /* RCU */1 struct el { 1 struct el { 2 struct list_head lp ; 2 struct list_head lp ; 3 long key ; 3 long key ; 4 spinlock_t mutex ; 4 spinlock_t mutex ; 5 int data ; 5 int data ; 6 /* حقول بيانات أخرى */ 6 /* حقول بيانات أخرى */ 7 }; 7 }; 8 DEFINE_RWLOCK ( listmutex ); 8 DEFINE_SPINLOCK ( listmutex ); 9 LIST_HEAD ( head ); 9 LIST_HEAD ( head );1 int search ( long key , int * result ) 1 int search ( long key , int * result ) 2 { 2 { 3 struct el * p ; 3 struct el * p ; 4 4 5 read_lock ( & listmutex ); 5 rcu_read_lock (); 6 list_for_each_entry ( p , & head , lp ) { 6 list_for_each_entry_rcu ( p , & head , lp ) { 7 if ( p -> key == key ) { 7 if ( p -> key == key ) { 8 * result = p -> data ; 8 * result = p -> data ; 9 read_unlock ( & listmutex ); 9 rcu_read_unlock (); 10 return 1 ; 10 return 1 ; 11 } 11 } 12 } 12 } 13 read_unlock ( & listmutex ); 13 rcu_read_unlock (); 14 return 0 ; 14 return 0 ; 15 } 15 }1 int delete ( long key ) 1 int delete ( long key ) 2 { 2 { 3 struct el * p ; 3 struct el * p ; 4 4 5 write_lock ( & listmutex ); 5 spin_lock ( & listmutex ); 6 list_for_each_entry ( p , & head , lp ) { 6 list_for_each_entry ( p , & head , lp ) { 7 if ( p -> key == key ) { 7 if ( p -> key == key ) { 8 list_del ( & p -> lp ); 8 list_del_rcu ( & p -> lp ); 9 write_unlock ( & listmutex ); 9 spin_unlock ( & listmutex ); 10 synchronize_rcu (); 10 kfree ( p ); 11 kfree ( p ); 11 return 1 ; 12 return 1 ; 12 } 13 } 13 } 14 } 14 write_unlock ( & listmutex ); 15 spin_unlock ( & listmutex ); 15 return 0 ; 16 return 0 ; 16 } 17 }

الاختلافات بين النهجين طفيفة للغاية. ينتقل تأمين جانب القراءة إلى rcu_read_lockو rcu_read_unlock، وينتقل تأمين جانب التحديث من قفل القارئ والكاتب إلى قفل دوراني بسيط، synchronize_rcuويسبق kfree.

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

كذلك، فإن وجود هذا synchronize_rcuيعني أن نسخة RCU من هذه النسخة deleteيمكنها الآن الحظر. إذا كانت هذه مشكلة، call_rcuفيمكن استخدام هذه النسخة بدلاً call_rcu (kfree, p)من النسخة الأخرى synchronize_rcu. وهذا مفيد بشكل خاص عند استخدامها مع عدّ المراجع.

تاريخ

تم اختراع تقنيات وآليات تشبه RCU بشكل مستقل عدة مرات: [ 25 ]

  1. وصف كل من إتش تي كونغ وكيو ليمان استخدام جامعات القمامة لتنفيذ الوصول الشبيه بـ RCU إلى شجرة بحث ثنائية. [ 26 ]
  2. قام أودي مانبر وريتشارد لادنر بتوسيع نطاق عمل كونغ وليمان ليشمل البيئات التي لا تعتمد على جمع البيانات المهملة، وذلك بتأجيل عملية استعادة الذاكرة حتى تنتهي جميع العمليات الجارية وقت الإزالة، وهو ما ينجح في البيئات التي لا تحتوي على عمليات طويلة الأمد. [ 27 ]
  3. وصف ريتشارد رشيد وآخرون تطبيقًا لمخزن مؤقت للترجمة الكسولة (TLB) يؤجل استعادة مساحة العناوين الافتراضية حتى تقوم جميع وحدات المعالجة المركزية بتفريغ مخزن TLB الخاص بها، وهو ما يشبه في جوهره بعض تطبيقات RCU. [ 28 ]
  4. حصل جيمس ب. هينيسي، وداميان ل. أوسيسيك، وجوزيف و. سيغ الثاني على براءة الاختراع الأمريكية رقم 4,809,168 في عام 1989 (انتهت صلاحيتها منذ ذلك الحين). تصف هذه البراءة آلية شبيهة بوحدة التحكم عن بُعد (RCU) والتي استُخدمت على ما يبدو في نظام التشغيل VM/XA على أجهزة الكمبيوتر المركزية من شركة IBM . [ 29 ]
  5. وصف ويليام بو آلية تشبه آلية RCU تعتمد على تحديد العلامات بشكل صريح من قبل القراء. [ 30 ]
  6. اقترح أجو جون تطبيقًا مشابهًا لـ RCU حيث ينتظر المحدثون ببساطة فترة زمنية محددة، على افتراض أن جميع القراء سيكملون خلال تلك الفترة الزمنية المحددة، كما قد يكون مناسبًا في نظام الوقت الحقيقي الصارم. [ 31 ] اقترح فان جاكوبسون مخططًا مشابهًا في عام 1993 (التواصل اللفظي).
  7. حصل كل من ج. سلنجواين وبي إي ماكيني على براءة الاختراع الأمريكية رقم 5,442,758 في أغسطس 1995، والتي تصف RCU كما تم تنفيذها في DYNIX/ptx ولاحقًا في نواة لينكس. [ 32 ]
  8. وصف كل من ب. جامسا، و أ. كريجر، و ج. أبافو، و م. ستوم آلية شبيهة بـ RCU مستخدمة في نظام التشغيل البحثي تورنادو التابع لجامعة تورنتو وأنظمة التشغيل البحثية IBM Research K42 ذات الصلة الوثيقة . [ 33 ]
  9. وصف كل من راستي راسل وفيل رومبف تقنيات مشابهة لتقنية RCU للتعامل مع تفريغ وحدات نواة لينكس. [ 34 ] [ 35 ]
  10. أضاف د. سارما RCU إلى الإصدار 2.5.43 من نواة لينكس في أكتوبر 2002.
  11. قام روبرت كولفين وآخرون بالتحقق رسميًا من خوارزمية مجموعة قائمة متزامنة كسولة تشبه RCU. [ 36 ]
  12. نشر السيد ديسنوييه وآخرون وصفًا لـ RCU في مساحة المستخدم. [ 37 ] [ 38 ]
  13. قام أ. جوتسمان وآخرون باستخلاص دلالات رسمية لـ RCU بناءً على منطق الفصل. [ 39 ]
  14. حصل كل من إيلان فرينكل، ورومان جيلر، ويورام رامبرغ، ويورام سنير على براءة الاختراع الأمريكية رقم 7,099,932 في عام 2006. تصف هذه البراءة آلية شبيهة بـ RCU لاسترجاع وتخزين معلومات إدارة سياسة جودة الخدمة باستخدام خدمة دليل بطريقة تضمن اتساق القراءة/الكتابة وتتيح التزامن في القراءة/الكتابة. [ 40 ]

انظر أيضاً

ملحوظات

  1. يجب مراعاة القراء النشطين فقط أثناء مرحلة الإزالة، لأنه لن يتمكن أي قارئ يبدأ بعد مرحلة الإزالة من الحصول على مرجع لعناصر البيانات التي تمت إزالتها، وبالتالي لا يمكن تعطيله بواسطة مرحلة الاستعادة.
  2. يمكن استخدام جامعات القمامة ، حيثما توفرت، لتنفيذ هذه الخطوة.
  3. لا تزال حالات التعطل القائمة على RCU ممكنة، على سبيل المثال عن طريق تنفيذ عبارة تحظر حتى تكتمل فترة السماح داخل قسم القراءة الحرج RCU.

مراجع

  1. 1 2 تانينباوم، أندرو (2015). أنظمة التشغيل الحديثة (الطبعة الرابعة  ). الولايات المتحدة الأمريكية: بيرسون. ص.  148. ردمك 9781292061429.
  2. غونيغونتالا، ديناكار؛ ماكيني، بول إي؛ تريبلت، جوشوا؛ والبول، جوناثان (أبريل–يونيو 2008). "آلية القراءة والنسخ والتحديث لدعم تطبيقات الوقت الحقيقي على أنظمة المعالجات المتعددة ذات الذاكرة المشتركة مع نظام لينكس". مجلة أنظمة آي بي إم . 47 (2): 221–236 . doi : 10.1147/sj.472.0221 .
  3. ماكيني، بول إي؛ والبول، جوناثان (17 ديسمبر 2007). "ما هو RCU، من حيث المبدأ؟" . أخبار لينكس الأسبوعية . تم الاطلاع عليه في 24 سبتمبر 2010 .
  4. ماكيني، بول إي؛ سلنجواين، جون دي (أكتوبر 1998). تحديث القراءة والنسخ: استخدام سجل التنفيذ لحل مشاكل التزامن (ملف PDF) . الحوسبة والأنظمة المتوازية والموزعة . الصفحات 509-518 . 
  5. نعمة بن ديفيد؛ جاي إي. بليلوش؛ ييهان صن؛ يوانهاو وي. "التزامن الفعال لكاتب واحد" .
  6. "تعدد الخيوط بدون قفل مع عمليات ذرية" .
  7. إيدي كولر. "ملاحظات حول تحديث القراءة والنسخ" . اقتباس: "لإدارة تعارضات الكتابة، تستخدم معظم هياكل بيانات RCU التأمين المنتظم."
  8. ماكيني، بول إي؛ والبول، جوناثان (يوليو 2008). "إدخال التكنولوجيا في نواة لينكس: دراسة حالة". مجلة SIGOPS لأنظمة التشغيل ، 42 (5): 4-17 . doi : 10.1145/1400097.1400099 . S2CID 12748421 . 
  9. أولسون، روبرت؛ نيلسون، ستيفان (مايو 2007). "TRASH: بنية بيانات ديناميكية من نوع LC-trie و hash". ورشة عمل 2007 حول التبديل والتوجيه عالي الأداء . الصفحات 1-6 . doi : 10.1109/HPSR.2007.4281239 . ISBN  978-1-4244-1205-1. S2CID 17493674 . 
  10. بيجين، نيك (يوليو 2006). ذاكرة تخزين مؤقتة للصفحات بدون قفل في لينكس - مقدمة، تقدم، أداء . ندوة أوتاوا لينكس .
  11. "بول إي. ماكيني: استخدام نظام لينكس RCU" .
  12. كانان، هاري (2009). "ترتيب عمليات الوصول إلى البيانات الوصفية المنفصلة في المعالجات المتعددة". وقائع الندوة الدولية السنوية الثانية والأربعين لمعهد مهندسي الكهرباء والإلكترونيات/رابطة مكائن ​​الحوسبة حول الهندسة المعمارية الدقيقة - Micro-42 . الصفحات 381-390 . doi : 10.1145/1669112.1669161 . ISBN  978-1-60558-798-1. S2CID 2465311 . 
  13. ماثيوز، كريس؛ كودي، إيفون؛ أبافو، جوناثان (2009). "أحداث قابلية النقل: نموذج برمجي لبنى تحتية نظامية قابلة للتوسع". وقائع ورشة العمل الثالثة حول لغات البرمجة وأنظمة التشغيل: الدعم اللغوي لأنظمة التشغيل الحديثة . سان خوسيه، كاليفورنيا، الولايات المتحدة الأمريكية: رابطة آلات الحوسبة. ص 11. doi : 10.1145/1215995.1216006 . ISBN  978-1-59593-577-9.
  14. دا سيلفا، ديلما ؛ كريجر، أوران؛ ويسنيوسكي، روبرت و.؛ ووترلاند، آموس؛ تام، ديفيد؛ باومان، أندرو (أبريل 2006). "K42: بنية تحتية لأبحاث أنظمة التشغيل". مجلة ACM SIGOPS لاستعراض أنظمة التشغيل . 40 (2): 34-42 . doi : 10.1145/1131322.1131333 . S2CID 669053 . 
  15. أبافو، جوناثان؛ دا سيلفا، ديلما؛ كريجر، أوران؛ أوسلاندر، مارك؛ أوستروفسكي، ميخال؛ روزنبرغ، برايان؛ ووترلاند، آموس؛ ويسنيوسكي، روبرت و.؛ زينيديس، جيمي (أغسطس 2007). "تجربة توزيع الكائنات في نظام تشغيل SMMP". معاملات ACM لأنظمة الحاسوب . 25 (3): 6/1–6/52. doi : 10.1145/1275517.1275518 . S2CID 931202 . 
  16. فريزر، كير؛ هاريس، تيم (2007). "البرمجة المتزامنة بدون أقفال". معاملات ACM لأنظمة الحاسوب . 25 (2): 34-42 . CiteSeerX 10.1.1.532.5050 . doi : 10.1145/1233307.1233309 . S2CID 3030814 .  
  17. بورتر، دونالد إي.؛ هوفمان، أوين إس.؛ روسباخ، كريستوفر جيه.؛ بن، ألكسندر؛ ويتشل، إيميت (2009). "معاملات أنظمة التشغيل". وقائع ندوة ACM SIGOPS الثانية والعشرين حول مبادئ أنظمة التشغيل - SOSP '09 . ص 161. doi : 10.1145/1629575.1629591 . hdl : 2152/ETD-UT-2010-12-2488 . ISBN  978-1-60558-752-3. S2CID 28504 . 
  18. هارت، توماس إي.؛ ماكيني، بول إي.؛ ديمكي براون، أنجيلا؛ والبول، جوناثان (ديسمبر 2007). "أداء استعادة الذاكرة للتزامن بدون تأمين". مجلة الحوسبة المتوازية والموزعة. 67 ( 12): 1270-1285 . doi : 10.1016/j.jpdc.2007.04.010 .
  19. ماكيني، بول إي. (4 يناير 2008). "RCU الجزء 2: الاستخدام" . أخبار لينكس الأسبوعية . تم الاسترجاع في 24 سبتمبر 2010 .
  20. ^ ماتيو ديسنويرز (ديسمبر 2009). تتبع نظام التشغيل منخفض التأثير (PDF) . مدرسة البوليتكنيك في مونتريال (مع أطروحة).
  21. ماكيني، بول إي. (17 يناير 2008). "RCU الجزء 3: واجهة برمجة تطبيقات RCU" . أخبار لينكس الأسبوعية . تم الاسترجاع في 24 سبتمبر 2010 .
  22. ^ ماكيني، بول إي. أبافو، جوناثان؛ كلين، آندي؛ كريجر، وهران؛ راسل، رستي؛ سارما، ديبانكار؛ سوني مانيش (يوليو 2001). تحديث القراءة والنسخ (PDF) . ندوة أوتاوا لينكس .
  23. مجلة Wizard (أغسطس 2001). "الذاكرة المشتركة، الخيوط، الاتصال بين العمليات" . هيوليت-باكارد . مؤرشف من الأصل في 20 يوليو 2011. تم الاطلاع عليه في 26 ديسمبر 2010 .
  24. ماكيني، بول إي. (أكتوبر 2003). "استخدام {RCU} في نواة {Linux} 2.5" . مجلة لينكس . تم الاطلاع عليه في 24 سبتمبر 2010 .
  25. ماكيني، بول إي. (يوليو 2004). استغلال التدمير المؤجل: تحليل لتقنيات القراءة والنسخ والتحديث (ملف PDF) . كلية العلوم والهندسة في جامعة أوريغون للصحة والعلوم (أطروحة).
  26. كونغ، إتش تي؛ ليمان، كيو. (سبتمبر 1980). "الصيانة المتزامنة لأشجار البحث الثنائية". معاملات ACM لأنظمة قواعد البيانات . 5 (3): 354. CiteSeerX 10.1.1.639.8357 . doi : 10.1145/320613.320619 . S2CID 13007648 .  
  27. مانبر، أودي؛ لادنر، ريتشارد إي. (سبتمبر 1984). "التحكم في التزامن في بنية بحث ديناميكية". معاملات ACM لأنظمة قواعد البيانات . 9 (3).
  28. رشيد، ريتشارد؛ تيفانيان، أفاديس؛ يونغ، مايكل؛ غولوب، ديفيد؛ بارون، روبرت؛ بولوسكي، ويليام؛ تشيو، جوناثان (أكتوبر 1987). إدارة الذاكرة الافتراضية المستقلة عن الجهاز لبنى المعالجات الأحادية والمعالجات المتعددة ذات الصفحات (ملف PDF) . الندوة الثانية حول الدعم المعماري للغات البرمجة وأنظمة التشغيل . رابطة آلات الحوسبة.
  29. US 4809168 ، هينيسي، جيمس ب.؛ أوسيسيك، داميان ل. وسيغ الثاني، جوزيف و.، "التسلسل السلبي في بيئة متعددة المهام"، نُشر في فبراير 1989 
  30. بو، ويليام (يونيو 1990). الصيانة المتزامنة لقوائم التخطي (تقرير فني). معهد الدراسات المتقدمة لعلوم الحاسوب، قسم علوم الحاسوب، جامعة ميريلاند. CS-TR-2222.1.
  31. جون، أجو (يناير 1995). العقد الافتراضية الديناميكية - التصميم والتنفيذ . مؤتمر USENIX الشتوي 1995 .
  32. US 5442758 ، سلنجواين، جون د. وماكيني ، بول إي.، "جهاز وطريقة لتحقيق استبعاد متبادل منخفض التكاليف والحفاظ على التماسك في نظام متعدد المعالجات"، نُشر في أغسطس 1995 
  33. غامسا، بن؛ كريغر، أوران؛ أبافو، جوناثان؛ ستوم، مايكل (فبراير 1999). تورنادو: تعظيم الموضعية والتزامن في نظام تشغيل متعدد المعالجات ذي ذاكرة مشتركة (ملف PDF) . وقائع الندوة الثالثة حول تصميم وتنفيذ أنظمة التشغيل .
  34. راسل، راستي (يونيو 2000). "ردًا على: برامج تشغيل الشبكات المعيارية" . مؤرشف من الأصل في 31 مارس 2012. تم الاسترجاع في 1 أكتوبر 2010 .
  35. راسل، راستي (يونيو 2000). "ردًا على: برامج تشغيل الشبكات المعيارية" . مؤرشف من الأصل في 31 مارس 2012. تم الاسترجاع في 1 أكتوبر 2010 .
  36. كولفين، روبرت؛ غروفز، ليندسي؛ لوتشانغكو، فيكتور؛ موير، مارك (أغسطس 2006). التحقق الرسمي من خوارزمية مجموعة متزامنة كسولة قائمة على القوائم (ملف PDF) . التحقق بمساعدة الحاسوب . مؤرشف من الأصل (ملف PDF) بتاريخ 17 يوليو 2009.
  37. ديسنوييه، ماثيو؛ ماكيني، بول إي؛ ستيرن، آلان؛ داغينايس، ميشيل ر؛ والبول، جوناثان (فبراير 2012). "تطبيقات على مستوى المستخدم لتحديث القراءة والنسخ" (ملف PDF) . معاملات IEEE للأنظمة المتوازية والموزعة . 23 (2): 375-382 . Bibcode : 2012ITPDS..23..375D . doi : 10.1109/TPDS.2011.159 . S2CID 832767 . 
  38. ماكيني، بول إي؛ ديسنوييه، ماثيو؛ جيانغشان، لاي (13 نوفمبر 2013). "وحدة التحكم عن بُعد في مساحة المستخدم" . أخبار لينكس الأسبوعية . تم الاطلاع عليه في 17 نوفمبر 2013 .
  39. غوتسمان، أليكسي؛ رينيتزكي، نوام؛ يانغ، هونغسوك (16-24 مارس 2013). التحقق من صحة خوارزميات استعادة الذاكرة المتزامنة باستخدام Grace (ملف PDF) . ESOP'13: الندوة الأوروبية حول البرمجة .
  40. US 7099932 ، Frenkel، Ilan؛ Geller، Roman & Ramberg، Yoram et al.، "طريقة وجهاز لاسترجاع معلومات سياسة جودة خدمة الشبكة من دليل في نظام إدارة سياسة جودة الخدمة"، نُشر في 2006-08-29، مُسند إلى Cisco Tech Inc. 

باور، آر تي، (يونيو 2009)، "التحقق التشغيلي من برنامج نسبي" تقرير تقني من جامعة ولاية بورتلاند TR-09-04 ( http://www.pdx.edu/sites/www.pdx.edu.computer-science/files/tr0904.pdf مؤرشف في 18-06-2015 على موقع Wayback Machine )