جعل المتغيرات الساكنة العالمية متعددة القراءة آمنة

StackOverflow https://stackoverflow.com/questions/2662575

سؤال

لديّ متغيرات ثابتة عالمية في مكتبة C ، والتي تولد استثناءات في تشغيل Multithread. أحتاج إلى جعلها آمنة بطريقة ما (أي ، يجب أن يرتبط كل مؤشر ترابط بمثيل مختلف لهذه المتغيرات). أي طرق موصى بها؟

هل كانت مفيدة؟

المحلول

لا توجد طريقة قياسية تعمل في جميع تطبيقات C ، ولكن توجد حلول خاصة بالتنفيذ. على سبيل المثال ، مع برنامج التحويل البرمجي لشركة Microsoft (انظر المستندات),

__declspec( thread ) int tls_i = 1;

يصنع tls_i Live in Thread-Local Storage (كل مؤشر ترابط له مثيل منفصل خاص به لهذا المتغير). مع مجلس التعاون الخليجي, بناء الجملة

__thread int tls_i;

قد ترغب أيضًا في التحقق من دخول ويكيبيديا حول هذا الموضوع.

نصائح أخرى

السؤال الأول:

  • هل تحتاج المواضيع إلى نسخها الخاصة من المتغيرات؟
  • أو هل يحتاجون إلى تنسيق الوصول إلى نسخة مشتركة واحدة؟

إذا كنت بحاجة إلى السابق ، فقد قدمت الإجابات الأخرى اقتراحات حول "تخزين الخيط المحلي".

إذا كنت بحاجة إلى هذا الأخير ، فأنت بطريقة ما أو لآخر تحتاج إلى التأكد من وجود طفرات مناسبة على تلك المتغيرات (نطاق Mutex هو أحد المشكلات التي تواجهها) ، وأن جميع الخيوط تستخدم Mutex ، وتحرير Mutex. هذا أصعب. قد تكون بحاجة إلى توفير وظائف تتحكم في الوصول إلى المتغيرات.

المتغير القياسي errno يمكن أن يكون lvalue قابلة للتعديل:

extern int *_errno_func(void);
#define errno (*(_errno_func)())

في تطبيق ملولب (تم تجميعه باستخدام -dreentrant) ، هذا ما يحدث ؛ على MacOS X ، يبدو أنه ما يحدث على أي حال (يستخدمون الاسم __error بدلاً من _errno_func; ؛ كلاهما في مساحة اسم التنفيذ).

قد ترغب في القيام بشيء مماثل ، أو ينتهي بك الأمر إلى القيام بشيء مشابه لمتغيراتك. حقيقة أنك تقول أنها ثابتة يحسن الأمور قليلاً. لديك ملف واحد فقط للتعامل معه (ما لم تكن مهملًا بما يكفي لتمرير - أو على مؤشرات لتلك المتغيرات).

ما تحتاجه هو TLS (موضوع تخزين محلي), ، وهو المعروف أيضًا باسم بيانات محددة أو البيانات الخاصة بالاتصالات. يمكن أن تضمن هذه الآلية كل مؤشر ترابط للوصول إلى نسخة منفصلة من البيانات ، دون القلق بشأن مزامنة الوصول مع مؤشرات الترابط الأخرى.


هناك طريقتان لاستخدام TLS:

  1. ضمنيًا: استخدام الكلمة الرئيسية

    شبابيك: __declspec (thread) int tls_var = 10 ؛

    Linux مع GCC: __thread int tls_var = 10

  2. صريح: استخدام واجهة برمجة تطبيقات TLS محددة

    شبابيك:

      tlsalloc (): تخصيص الذاكرة لبيانات TLS
      tlsfree (): تحرير ذكرى بيانات TLS
      tlssetvalue (): اضبط قيمة TLS
      tlsgetValue (): احصل على قيمة TLS

    يرجى الرجوع إلى MSDN للحصول على معلومات مفصلة.

    Linux مع GCC:

      pthread_key_create (): إنشاء بيانات TLS
      pthread_key_delete (): مصير بيانات TLS
      pthread_getspecific (): احصل على قيمة TLS
      PTHREAD_SETSPecific(): تعيين قيمة TLS
    انتقل إلى Manpage للحصول على معلومات محددة ومفصلة.

معظم المترجمين لديهم طريقة لتخزين الخيوط المحلية. على افتراض أنه متاح ، هذا ما تريده.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top