في Linux ، يمكنك إنشاء وإدارة سلاسل الرسائل في C / C ++ باستخدام مكتبة POSIX thread (pthread). على عكس أنظمة التشغيل الأخرى ، لا يوجد فرق كبير بين الخيط والعملية في Linux. لهذا السبب يشير Linux غالبًا إلى خيوطه على أنها عمليات خفيفة الوزن.
باستخدام مكتبة pthread ، يمكنك إنشاء سلاسل رسائل ، وانتظر حتى يتم إنهاؤها ، وإنهائها بشكل صريح.
تاريخ استخدام الخيط على لينكس
قبل إصدار Linux 2.6 ، كان تطبيق مؤشر الترابط الرئيسي هو LinuxThreads. كان لهذا التنفيذ حدود كبيرة من حيث الأداء وعمليات المزامنة. تم تقييد الحد الأقصى لعدد سلاسل الرسائل التي يمكن تشغيلها في 1000 ثانية.
في عام 2003 ، نجح فريق بقيادة مطورين من IBM و RedHat في إنشاء مكتبة خيوط POSIX الأصلية (NPTL) مشروع متاح. تم تقديمه لأول مرة في الإصدار 3 من RedHat Enterprise لحل مشكلات الأداء مع Java Virtual Machine على نظام Linux. تحتوي مكتبة جنو سي اليوم على تطبيقات لآليتي الترابط.
لا يعد أي من هذين التطبيقين تطبيقًا للخيوط الخضراء ، والتي يمكن للجهاز الظاهري إدارتها وتشغيلها في وضع المستخدم البحت. عند استخدام مكتبة pthread ، تنشئ النواة سلسلة رسائل في كل مرة يبدأ فيها البرنامج.
يمكنك العثور على معلومات خاصة بمؤشر الترابط لأي عملية قيد التشغيل في الملفات الموجودة أسفل /proc/
منطق عمل الخيوط
الخيوط تشبه العمليات التي تعمل حاليًا على نظام التشغيل. في أنظمة المعالج الفردي (مثل المتحكمات الدقيقة) ، تحاكي نواة نظام التشغيل الخيوط. هذا يسمح للمعاملات بالعمل في وقت واحد من خلال التقطيع.
يمكن لنظام التشغيل أحادي النواة تشغيل عملية واحدة فقط في كل مرة. ومع ذلك، في أنظمة متعددة النواة أو متعددة المعالجات، يمكن تشغيل هذه العمليات في وقت واحد.
إنشاء الخيط في C
يمكنك استخدام ال إنشاء pthread_create وظيفة لإنشاء موضوع جديد. ال pthread.h يتضمن ملف الرأس تعريف التوقيع الخاص به إلى جانب الوظائف الأخرى ذات الصلة بمؤشر الترابط. تستخدم الخيوط نفس مساحة العنوان وأوصاف الملفات مثل البرنامج الرئيسي.
تتضمن مكتبة pthread أيضًا الدعم الضروري لعمليات كائن المزامنة والعمليات الشرطية المطلوبة لعمليات المزامنة.
عند استخدام وظائف مكتبة pthread ، يجب عليك التأكد من أن المترجم يربط ملف pthread مكتبة في الملف القابل للتنفيذ الخاص بك. إذا لزم الأمر ، يمكنك توجيه المترجم إلى الارتباط بالمكتبة باستخدام امتداد -ل خيار:
دول مجلس التعاون الخليجي -o امتحان test_thread.c -lpthread
تحتوي الدالة pthread_create على التوقيع التالي:
intإنشاء pthread_create(pthread_t *خيط، مقدار ثابتpthread_attr_t * Attr ، فارغ * (* start_routine) (فارغ *), فارغ * حج)
تقوم بإرجاع 0 إذا كان الإجراء ناجحًا. إذا كانت هناك مشكلة ، فإنها تُرجع رمز خطأ غير صفري. في توقيع الوظيفة أعلاه:
- ال خيط المعلمة من النوع pthread_t. سيكون الخيط الذي تم إنشاؤه دائمًا متاحًا لهذا المرجع.
- ال أتر تتيح لك المعلمة تحديد سلوك مخصص. يمكنك استخدام سلسلة من الوظائف الخاصة بمؤشر الترابط بدءًا من pthread_attr_ لاقامة هذه القيمة. التخصيصات المحتملة هي سياسة الجدولة وحجم المكدس وسياسة الفصل.
- start_routine يحدد الوظيفة التي سيتم تشغيل مؤشر الترابط.
- حج يمثل بنية بيانات عامة تم تمريرها إلى الوظيفة بواسطة مؤشر الترابط.
إليك مثال على التطبيق:
#يشمل
#يشمل
#يشمل
#يشملفارغ *عامل(فارغ *بيانات)
{
شار * الاسم = (شار*)بيانات؛
ل (int أنا = 0; أنا < 120; أنا ++)
{
انت نائم(50000);
printf("مرحبًا من اسم مؤشر الترابط =٪ s \ n" ، الاسم) ؛
}
printf("تم تنفيذ مؤشر الترابط٪ s! \ n" ، الاسم) ؛
يعودباطل;
}
intرئيسي(فارغ)
{
pthread_t th1 ، th2 ؛
pthread_create (& th1 ، باطل، عامل ، "X") ؛
pthread_create (& th2، باطل، عامل ، "Y") ؛
ينام(5);
printf("الخروج من البرنامج الرئيسي \ n")؛
يعود0;
}
أنواع الخيوط
عندما يعود موضوع من ملف رئيسي() تعمل في تطبيق ما ، تنتهي جميع سلاسل الرسائل ويحرر النظام جميع الموارد التي استخدمها البرنامج. وبالمثل ، عند الخروج من أي سلسلة رسائل بأمر مثل ملف مخرج()، سيقوم برنامجك بإنهاء كافة سلاسل الرسائل.
مع ال pthread_join وظيفة ، يمكنك الانتظار حتى ينتهي الموضوع بدلا من ذلك. سيتم حظر مؤشر الترابط الذي يستخدم هذه الوظيفة حتى ينتهي مؤشر الترابط المتوقع. لا يتم إرجاع الموارد التي يستخدمونها من النظام حتى في حالات مثل إنهاء سلاسل الرسائل القابلة للانضمام ، أو غير المجدولة بواسطة وحدة المعالجة المركزية ، أو حتى الفشل في الانضمام إليها ptread_join.
في بعض الأحيان توجد مواقف لا يكون فيها الانضمام إلى pthread_join منطقيًا ؛ إذا كان من المستحيل التنبؤ بموعد انتهاء الخيط ، على سبيل المثال. في هذه الحالة ، يمكنك التأكد من قيام النظام بإرجاع جميع الموارد تلقائيًا عند النقطة التي يعود فيها مؤشر الترابط.
لتحقيق ذلك ، يجب أن تبدأ المواضيع ذات الصلة بامتداد منفصل حالة. عند بدء الخيط ، فصل يمكن تعيين الحالة من خلال قيم سمة الموضوع أو بامتداد pthread_detach وظيفة:
intpthread_attr_setdetachstate(& سمة ، PTHREAD_CREATE_DETACHED);
intpthread_detach(pthread_t خيط);
إليك مثال على استخدام pthread_join (). استبدل الوظيفة الرئيسية في البرنامج الأول بما يلي:
intرئيسي(فارغ)
{
pthread_t th1 ، th2 ؛
pthread_create (& th1 ، باطل، عامل ، "X") ؛
pthread_create (& th2، باطل، عامل ، "Y") ؛
ينام(5);
printf("الخروج من البرنامج الرئيسي \ n")؛
pthread_join (th1 ، باطل);
pthread_join (th2 ، باطل);
يعود0;
}
عند تجميع البرنامج وتشغيله ، سيكون الإخراج الخاص بك:
مرحبًا من الموضوع Y
مرحبًا من الموضوع X
مرحبًا من الموضوع Y
...
مرحبًا من الموضوع Y
الخروج من البرنامج الرئيسي
مرحبًا من الموضوع X
...
مرحبًا من الموضوع X
تم تنفيذ الموضوع X!
مرحبًا من الموضوع Y
تم تنفيذ الموضوع "ص"!
إنهاء الخيط
يمكنك إلغاء موضوع مع استدعاء pthread_cancel ، تمرير المقابلة pthread_t بطاقة تعريف:
intpthread_cancel(pthread_t خيط);
يمكنك رؤية هذا في العمل في الكود التالي. مرة أخرى ، فقط ملف رئيسي الوظيفة مختلفة:
intرئيسي(فارغ)
{
pthread_t th1 ، th2 ؛
pthread_create (& th1 ، باطل، عامل ، "X") ؛
pthread_create (& th2، باطل، عامل ، "Y") ؛
ينام(1);
printf("> إلغاء الموضوع Y!! \ n")؛
pthread_cancel (th2) ؛
انت نائم(100000);
printf("> إلغاء الموضوع X! \ n")؛
pthread_cancel (th1) ؛
printf("الخروج من البرنامج الرئيسي \ n")؛
يعود0;
}
لماذا يتم إنشاء الخيوط؟
تحاول أنظمة التشغيل دائمًا تشغيل مؤشرات الترابط على وحدة معالجة مركزية واحدة أو أكثر ، إما من قائمة تم إنشاؤها ذاتيًا أو من قائمة خيوط تم إنشاؤها بواسطة المستخدم. لا يمكن تشغيل بعض سلاسل العمليات لأنها تنتظر إشارة إدخال / إخراج من الجهاز. قد يكونون أيضًا ينتظرون طواعية ، أو ينتظرون استجابة من سلسلة رسائل أخرى ، أو لديهم مؤشر ترابط آخر يحجبهم.
يمكنك ضبط الموارد التي تخصصها للسلاسل التي تقوم بإنشائها باستخدام pthread. يمكن أن تكون هذه سياسة جدولة مخصصة ، أو يمكنك اختيار خوارزميات الجدولة مثل FIFO أو Round-robin إذا رغبت في ذلك.