table of contents
- unstable 4.31.0-1
| pthreads(7) | Miscellaneous Information Manual | pthreads(7) |
الاسم¶
pthreads - خيوط POSIX
الوصف¶
يحدد POSIX.1 مجموعة من الواجهات (الدوال، ملفات الرأس) للبرمجة الخيطية المعروفة باسم خيوط POSIX، أو Pthreads. يمكن لعملية واحدة أن تحتوي على خيوط متعددة، جميعها تنفذ نفس البرنامج. تشارك هذه الخيوط نفس الذاكرة العامة (قطاعات البيانات والكومة)، لكن لكل خيط مكدسه الخاص (المتغيرات الآلية).
يتطلب POSIX.1 أيضًا أن تشارك الخيوط مجموعة من السمات الأخرى (أي أن هذه السمات على مستوى العملية وليس لكل خيط):
- •
- معرف العملية
- •
- معرف العملية الأم
- •
- معرف مجموعة العملية ومعرف الجلسة
- •
- الطرفية المسيطرة
- •
- معرفات المستخدم والمجموعة
- •
- واصفات الملفات المفتوحة
- •
- أقفال السجلات (انظر fcntl(2))
- •
- ترتيبات الإشارات
- •
- قناع إنشاء وضع الملف (umask(2))
- •
- الدليل الحالي (chdir(2)) والدليل الجذر (chroot(2))
- •
- مؤقتات الفترات (setitimer(2)) ومؤقتات POSIX (timer_create(2))
- •
- قيمة nice (setpriority(2))
- •
- حدود الموارد (setrlimit(2))
- •
- قياسات استهلاك وقت وحدة المعالجة المركزية (times(2)) والموارد (getrusage(2))
بالإضافة إلى المكدس، يحدد POSIX.1 أن سمات أخرى متنوعة مميزة لكل خيط، بما في ذلك:
- •
- معرف الخيط (نوع البيانات pthread_t)
- •
- قناع الإشارة (pthread_sigmask(3))
- •
- المتغير errno
- •
- مكدس الإشارة البديل (sigaltstack(2))
- •
- سياسة وأولوية الجدولة في الوقت الفعلي (sched(7))
الميزات التالية الخاصة بلينكس هي أيضًا لكل خيط:
- •
- القدرات (انظر capabilities(7))
- •
- الارتباط بوحدة المعالجة المركزية (sched_setaffinity(2))
قيم إرجاع دوال Pthreads¶
معظم دوال pthreads تُرجع 0 عند النجاح، ورقم خطأ عند الفشل. أرقام الأخطاء التي يمكن إرجاعها لها نفس معنى أرقام الأخطاء المُرجَعة في errno بواسطة استدعاءات النظام التقليدية ودوال مكتبة C. لاحظ أن دوال pthreads لا تضبط errno. لكل دالة من دوال pthreads التي يمكنها إرجاع خطأ، يُحدد POSIX.1-2001 أن الدالة لا يمكنها أبدًا الفشل بالخطأ EINTR.
معرفات الخيوط¶
كل خيط من الخيوط في عملية له معرف خيط فريد (مُخزَّن في النوع pthread_t). يُرجَع هذا المعرف إلى مُستدعي pthread_create(3)، ويمكن للخيط الحصول على معرف خيطه الخاص باستخدام pthread_self(3).
معرفات الخيوط مضمونة لتكون فريدة فقط داخل العملية. (في جميع دوال pthreads التي تقبل معرف خيط كوسيطة، يشير هذا المعرف بحكم التعريف إلى خيط في نفس عملية المُستدعي.)
قد يُعيد النظام استخدام معرف خيط بعد انضمام خيط مُنهَى، أو إنهاء خيط منفصل. يقول POSIX: "إذا حاول تطبيق استخدام معرف خيط انتهى عمره، فإن السلوك غير مُحدَّد."
الدوال الآمنة للخيوط¶
الدالة الآمنة للخيوط هي التي يمكن استدعاؤها بأمان (أي أنها ستُعطي نفس النتائج بغض النظر عن كونها) من خيوط متعددة في نفس الوقت.
يتطلب POSIX.1-2001 وPOSIX.1-2008 أن تكون جميع الدوال المُحدَّدة في المعيار آمنة للخيوط، باستثناء الدوال التالية:
asctime() basename() catgets() crypt() ctermid() if passed a non-NULL argument ctime() dbm_clearerr() dbm_close() dbm_delete() dbm_error() dbm_fetch() dbm_firstkey() dbm_nextkey() dbm_open() dbm_store() dirname() dlerror() drand48() ecvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)] encrypt() endgrent() endpwent() endutxent() fcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)] ftw() gcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)] getc_unlocked() getchar_unlocked() getdate() getenv() getgrent() getgrgid() getgrnam() gethostbyaddr() [POSIX.1-2001 only (function removed in
POSIX.1-2008)] gethostbyname() [POSIX.1-2001 only (function removed in
POSIX.1-2008)] gethostent() getlogin() getnetbyaddr() getnetbyname() getnetent() getopt() getprotobyname() getprotobynumber() getprotoent() getpwent() getpwnam() getpwuid() getservbyname() getservbyport() getservent() getutxent() getutxid() getutxline() gmtime() hcreate() hdestroy() hsearch() inet_ntoa() l64a() lgamma() lgammaf() lgammal() localeconv() localtime() lrand48() mrand48() nftw() nl_langinfo() ptsname() putc_unlocked() putchar_unlocked() putenv() pututxline() rand() readdir() setenv() setgrent() setkey() setpwent() setutxent() strerror() strsignal() [Added in POSIX.1-2008] strtok() system() [Added in POSIX.1-2008] tmpnam() if passed a non-NULL argument ttyname() unsetenv() wcrtomb() if its final argument is NULL wcsrtombs() if its final argument is NULL wcstombs() wctomb()
الدوال الآمنة للإلغاء غير المتزامن¶
الدالة الآمنة للإلغاء غير المتزامن هي التي يمكن استدعاؤها بأمان في تطبيق حيث الإلغاء غير المتزامن مُفعَّل (انظر pthread_setcancelstate(3)).
فقط الدوال التالية مطلوب أن تكون آمنة للإلغاء غير المتزامن بواسطة POSIX.1-2001 وPOSIX.1-2008:
pthread_cancel() pthread_setcancelstate() pthread_setcanceltype()
نقاط الإلغاء¶
يُحدد POSIX.1 أن دوالًا معينة يجب أن تكون، ودوالًا أخرى معينة قد تكون، نقاط إلغاء. إذا كان الخيط قابلًا للإلغاء، ونوع قابلية الإلغاء مؤجَّل، وطلب إلغاء معلق للخيط، فإن الخيط يُلغى عندما يستدعي دالة هي نقطة إلغاء.
الدوال التالية مطلوب أن تكون نقاط إلغاء بواسطة POSIX.1-2001 و/أو POSIX.1-2008:
accept() aio_suspend() clock_nanosleep() close() connect() creat() fcntl() F_SETLKW fdatasync() fsync() getmsg() getpmsg() lockf() F_LOCK mq_receive() mq_send() mq_timedreceive() mq_timedsend() msgrcv() msgsnd() msync() nanosleep() open() openat() [Added in POSIX.1-2008] pause() poll() pread() pselect() pthread_cond_timedwait() pthread_cond_wait() pthread_join() pthread_testcancel() putmsg() putpmsg() pwrite() read() readv() recv() recvfrom() recvmsg() select() sem_timedwait() sem_wait() send() sendmsg() sendto() sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)] sigsuspend() sigtimedwait() sigwait() sigwaitinfo() sleep() system() tcdrain() usleep() [POSIX.1-2001 only (function removed in POSIX.1-2008)] wait() waitid() waitpid() write() writev()
الدوال التالية قد تكون نقاط إلغاء وفقًا لـ POSIX.1-2001 و/أو POSIX.1-2008:
access() asctime() asctime_r() catclose() catgets() catopen() chmod() [Added in POSIX.1-2008] chown() [Added in POSIX.1-2008] closedir() closelog() ctermid() ctime() ctime_r() dbm_close() dbm_delete() dbm_fetch() dbm_nextkey() dbm_open() dbm_store() dlclose() dlopen() dprintf() [Added in POSIX.1-2008] endgrent() endhostent() endnetent() endprotoent() endpwent() endservent() endutxent() faccessat() [Added in POSIX.1-2008] fchmod() [Added in POSIX.1-2008] fchmodat() [Added in POSIX.1-2008] fchown() [Added in POSIX.1-2008] fchownat() [Added in POSIX.1-2008] fclose() fcntl() (for any value of cmd argument) fflush() fgetc() fgetpos() fgets() fgetwc() fgetws() fmtmsg() fopen() fpathconf() fprintf() fputc() fputs() fputwc() fputws() fread() freopen() fscanf() fseek() fseeko() fsetpos() fstat() fstatat() [Added in POSIX.1-2008] ftell() ftello() ftw() futimens() [Added in POSIX.1-2008] fwprintf() fwrite() fwscanf() getaddrinfo() getc() getc_unlocked() getchar() getchar_unlocked() getcwd() getdate() getdelim() [Added in POSIX.1-2008] getgrent() getgrgid() getgrgid_r() getgrnam() getgrnam_r() gethostbyaddr() [POSIX.1-2001 only (function removed in
POSIX.1-2008)] gethostbyname() [POSIX.1-2001 only (function removed in
POSIX.1-2008)] gethostent() gethostid() gethostname() getline() [Added in POSIX.1-2008] getlogin() getlogin_r() getnameinfo() getnetbyaddr() getnetbyname() getnetent() getopt() (if opterr is nonzero) getprotobyname() getprotobynumber() getprotoent() getpwent() getpwnam() getpwnam_r() getpwuid() getpwuid_r() gets() getservbyname() getservbyport() getservent() getutxent() getutxid() getutxline() getwc() getwchar() getwd() [POSIX.1-2001 only (function removed in POSIX.1-2008)] glob() iconv_close() iconv_open() ioctl() link() linkat() [Added in POSIX.1-2008] lio_listio() [Added in POSIX.1-2008] localtime() localtime_r() lockf() [Added in POSIX.1-2008] lseek() lstat() mkdir() [Added in POSIX.1-2008] mkdirat() [Added in POSIX.1-2008] mkdtemp() [Added in POSIX.1-2008] mkfifo() [Added in POSIX.1-2008] mkfifoat() [Added in POSIX.1-2008] mknod() [Added in POSIX.1-2008] mknodat() [Added in POSIX.1-2008] mkstemp() mktime() nftw() opendir() openlog() pathconf() pclose() perror() popen() posix_fadvise() posix_fallocate() posix_madvise() posix_openpt() posix_spawn() posix_spawnp() posix_trace_clear() posix_trace_close() posix_trace_create() posix_trace_create_withlog() posix_trace_eventtypelist_getnext_id() posix_trace_eventtypelist_rewind() posix_trace_flush() posix_trace_get_attr() posix_trace_get_filter() posix_trace_get_status() posix_trace_getnext_event() posix_trace_open() posix_trace_rewind() posix_trace_set_filter() posix_trace_shutdown() posix_trace_timedgetnext_event() posix_typed_mem_open() printf() psiginfo() [Added in POSIX.1-2008] psignal() [Added in POSIX.1-2008] pthread_rwlock_rdlock() pthread_rwlock_timedrdlock() pthread_rwlock_timedwrlock() pthread_rwlock_wrlock() putc() putc_unlocked() putchar() putchar_unlocked() puts() pututxline() putwc() putwchar() readdir() readdir_r() readlink() [Added in POSIX.1-2008] readlinkat() [Added in POSIX.1-2008] remove() rename() renameat() [Added in POSIX.1-2008] rewind() rewinddir() scandir() [Added in POSIX.1-2008] scanf() seekdir() semop() setgrent() sethostent() setnetent() setprotoent() setpwent() setservent() setutxent() sigpause() [Added in POSIX.1-2008] stat() strerror() strerror_r() strftime() symlink() symlinkat() [Added in POSIX.1-2008] sync() syslog() tmpfile() tmpnam() ttyname() ttyname_r() tzset() ungetc() ungetwc() unlink() unlinkat() [Added in POSIX.1-2008] utime() [Added in POSIX.1-2008] utimensat() [Added in POSIX.1-2008] utimes() [Added in POSIX.1-2008] vdprintf() [Added in POSIX.1-2008] vfprintf() vfwprintf() vprintf() vwprintf() wcsftime() wordexp() wprintf() wscanf()
قد يقوم أحد تطبيقات البرنامج أيضًا بتحديد وظائف أخرى غير مذكورة في المعيار كنقاط إلغاء. وعلى وجه الخصوص، من المرجح أن يقوم أحد تطبيقات البرنامج بتحديد أي وظيفة غير قياسية قد تتسبب في تعطل البرنامج كنقطة إلغاء.(وهذا يشمل معظم الوظائف التي يمكنها التعامل مع الملفات.)
تجدر الإشارة إلى أنه حتى لو لم يكن التطبيق يستخدم الإلغاء غير المتزامن، فإن استدعاء إحدى الدوال الواردة في القائمة أعلاه من معالج إشارة غير متزامن قد يؤدي إلى ما يعادل الإلغاء غير المتزامن. وقد لا يتوقع كود المستخدم الأساسي حدوث إلغاء غير متزامن، مما قد يؤدي إلى عدم اتساق حالة بيانات المستخدم.لذلك، ينبغي توخي الحذر عند استخدام الإشارات عند الدخول إلى منطقة الإلغاء المؤجل.
ترجمة المصدر على لينكس¶
في نظام لينكس، يجب ترجمة البرامج التي تستخدم واجهة برمجة التطبيقات Pthreads باستخدام cc -pthread.
تطبيقات لينكس لخيوط POSIX¶
مع مرور الوقت، تم توفير تطبيقين للخيوط بواسطة مكتبة GNU C على لينكس:
- LinuxThreads
- هذا هو التطبيق الأصلي لـ Pthreads. منذ glibc 2.4، لم يعد هذا التطبيق مدعومًا.
- NPTL (مكتبة خيوط POSIX الأصلية)
- هذا هو التطبيق الحديث لـ Pthreads. بالمقارنة مع LinuxThreads، يوفر NPTL توافقًا أوثق مع متطلبات مواصفات POSIX.1 وأداءً أفضل عند إنشاء أعداد كبيرة من الخيوط. NPTL متاح منذ glibc 2.3.2، ويتطلب ميزات موجودة في نواة لينكس 2.6.
كلا هذين التطبيقين هما ما يُسمى بتطبيقات 1:1، مما يعني أن كل خيط يُخطط لكيان جدولة نواة. يستخدم كلا تطبيقي الخيوط استدعاء النظام لينكس clone(2). في NPTL، يتم تنفيذ بدائيات مزامنة الخيوط (المُتضادات، انضمام الخيوط، وما إلى ذلك) باستخدام استدعاء النظام لينكس futex(2).
LinuxThreads¶
الميزات البارزة لهذا التطبيق هي التالية:
- •
- بالإضافة إلى الخيط الرئيسي (الأولي)، والخيوط التي ينشئها البرنامج باستخدام pthread_create(3)، ينشئ التطبيق خيط "مدير". يعالج هذا الخيط إنشاء الخيوط وإنهاءها. (قد تنتج مشاكل إذا تم قتل هذا الخيط عن غير قصد.)
- •
- تُستخدم الإشارات داخليًا بواسطة التطبيق. على لينكس 2.2 والإصدارات الأحدث، تُستخدم الإشارات الثلاث الأولى في الوقت الفعلي (انظر أيضًا signal(7)). على نوى لينكس الأقدم، تُستخدم SIGUSR1 و SIGUSR2. يجب على التطبيقات تجنب استخدام أي مجموعة من الإشارات التي يستخدمها التطبيق.
- •
- لا تشارك الخيوط معرفات العمليات. (في الواقع، يتم تنفيذ خيوط LinuxThreads كعمليات تشارك معلومات أكثر من المعتاد، ولكنها لا تشارك معرف عملية مشترك.) خيوط LinuxThreads (بما في ذلك خيط المدير) مرئية كعمليات منفصلة باستخدام ps(1).
ينحرف تطبيق LinuxThreads عن مواصفات POSIX.1 بعدة طرق، بما في ذلك التالي:
- •
- استدعاءات getpid(2) تُرجع قيمة مختلفة في كل خيط.
- •
- استدعاءات getppid(2) في خيوط غير الخيط الرئيسي تُرجع معرف عملية خيط المدير؛ بدلاً من ذلك، يجب أن تُرجع getppid(2) في هذه الخيوط نفس القيمة مثل getppid(2) في الخيط الرئيسي.
- •
- عندما ينشئ خيط عملية فرعية جديدة باستخدام fork(2)، يجب أن يكون أي خيط قادرًا على wait(2) على الفرعية. ومع ذلك، يسمح التطبيق فقط للخيط الذي أنشأ الفرعية بـ wait(2) عليها.
- •
- عندما يستدعي خيط execve(2)، يتم إنهاء جميع الخيوط الأخرى (كما هو مطلوب بواسطة POSIX.1). ومع ذلك، فإن العملية الناتجة لها نفس PID مثل الخيط الذي استدعى execve(2): يجب أن يكون لها نفس PID مثل الخيط الرئيسي.
- •
- لا تشارك الخيوط معرفات المستخدم والمجموعة. يمكن أن يسبب هذا تعقيدات مع برامج set-user-ID ويمكن أن يسبب فشلًا في وظائف Pthreads إذا قام تطبيق بتغيير بيانات اعتماده باستخدام seteuid(2) أو ما شابه.
- •
- لا تشارك الخيوط معرف جلسة مشترك ومعرف مجموعة عملية.
- •
- لا تشارك الخيوط أقفال السجلات المنشأة باستخدام fcntl(2).
- •
- المعلومات التي تُرجعها times(2) و getrusage(2) هي لكل خيط بدلاً من أن تكون على مستوى العملية.
- •
- لا تشارك الخيوط قيم التراجع عن الإشارات (انظر semop(2)).
- •
- لا تشارك الخيوط مؤقتات الفترات.
- •
- لا تشارك الخيوط قيمة nice مشتركة.
- •
- يميز POSIX.1 بين مفاهيم الإشارات الموجهة للعملية ككل والإشارات الموجهة للخيوط الفردية. وفقًا لـ POSIX.1، يجب معالجة إشارة موجهة للعملية (مرسلة باستخدام kill(2)، على سبيل المثال) بواسطة خيط واحد يتم اختياره عشوائيًا داخل العملية. لا يدعم LinuxThreads مفهوم الإشارات الموجهة للعملية: يمكن إرسال الإشارات فقط إلى خيوط محددة.
- •
- تمتلك الخيوط إعدادات مكدس إشارات بديلة مميزة. ومع ذلك، تُنسخ إعدادات مكدس الإشارات البديلة للخيط الجديد من الخيط الذي أنشأه، بحيث تشارك الخيوط مكدس إشارات بديلة في البداية. (يجب أن يبدأ الخيط الجديد بدون تعريف مكدس إشارات بديلة. إذا عالج خيطان الإشارات على مكدس الإشارات البديلة المشترك في نفس الوقت، فمن المحتمل حدوث أعطال غير متوقعة في البرنامج.)
NPTL¶
مع NPTL، تُوضع جميع الخيوط في عملية في نفس مجموعة الخيوط؛ يشارك جميع أعضاء مجموعة الخيوط نفس PID. لا تستخدم NPTL خيط مدير.
تستخدم NPTL داخليًا أول إشارتين زمنيتين حقيقيتين؛ لا يمكن استخدام هذه الإشارات في التطبيقات. انظر nptl(7) لمزيد من التفاصيل.
لا يزال لدى NPTL على الأقل عدم توافق واحد مع POSIX.1:
- •
- لا تشارك الخيوط قيمة nice مشتركة.
تحدث بعض حالات عدم توافق NPTL فقط مع النوى الأقدم:
- •
- المعلومات التي تُرجعها times(2) و getrusage(2) هي لكل خيط بدلاً من أن تكون على مستوى العملية (أُصلح في Linux 2.6.9).
- •
- لا تشارك الخيوط حدود الموارد (أُصلح في Linux 2.6.10).
- •
- لا تشارك الخيوط الموقتات الفاصلة (أُصلح في Linux 2.6.12).
- •
- يُسمح فقط للخيط الرئيسي ببدء جلسة جديدة باستخدام setsid(2) (أُصلح في Linux 2.6.16).
- •
- يُسمح فقط للخيط الرئيسي بجعل العملية قائد مجموعة عمليات باستخدام setpgid(2) (أُصلح في Linux 2.6.16).
- •
- تمتلك الخيوط إعدادات مكدس إشارات بديلة مميزة. ومع ذلك، تُنسخ إعدادات مكدس الإشارات البديلة للخيط الجديد من الخيط الذي أنشأه، بحيث تشارك الخيوط مكدس إشارات بديلة في البداية (أُصلح في Linux 2.6.16).
لاحظ النقاط الإضافية التالية حول تنفيذ NPTL:
- •
- إذا عُيّن حد الموارد الناعم لحجم المكدس (انظر وصف RLIMIT_STACK في setrlimit(2)) إلى قيمة غير غير محدود، فإن هذه القيمة تحدد حجم المكدس المبدئي للخيوط الجديدة. لكي يكون هذا الحد فعالاً، يجب تعيينه قبل تنفيذ البرنامج، ربما باستخدام الأمر المدمج في الصدفة ulimit -s (limit stacksize في صدفة C).
تحديد تنفيذ الترابط¶
منذ glibc 2.3.2، يمكن استخدام الأمر getconf(1) لتحديد تنفيذ الترابط للنظام، على سبيل المثال:
bash$ getconf GNU_LIBPTHREAD_VERSION NPTL 2.3.4
مع إصدارات glibc الأقدم، يجب أن يكون أمر مثل التالي كافيًا لتحديد تنفيذ الترابط المبدئي:
bash$ $( ldd /bin/ls | grep libc.so | awk '{print $3}' ) | \
egrep -i 'threads|nptl'
Native POSIX Threads Library by Ulrich Drepper et al
اختيار تنفيذ الترابط: LD_ASSUME_KERNEL¶
على الأنظمة التي تحتوي على glibc يدعم كلاً من LinuxThreads و NPTL (أي glibc 2.3.*)، يمكن استخدام متغير البيئة LD_ASSUME_KERNEL لتجاوز اختيار الرابط الديناميكي المبدئي لتنفيذ الترابط. يخبر هذا المتغير الرابط الديناميكي بافتراض أنه يعمل فوق إصدار نواة معين. بتحديد إصدار نواة لا يوفر الدعم المطلوب من قبل NPTL، يمكننا فرض استخدام LinuxThreads. (السبب الأكثر ترجيحًا لفعل ذلك هو تشغيل تطبيق (معطل) يعتمد على بعض السلوك غير المتوافق في LinuxThreads.) على سبيل المثال:
bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
awk '{print $3}' ) | egrep -i 'threads|nptl'
linuxthreads-0.10 by Xavier Leroy
انظر أيضًا¶
clone(2), fork(2), futex(2), gettid(2), proc(5), attributes(7), futex(7), nptl(7), sigevent(3type), signal(7)
صفحات دليل Pthreads متنوعة، على سبيل المثال: pthread_atfork(3), pthread_attr_init(3), pthread_cancel(3), pthread_cleanup_push(3), pthread_cond_signal(3), pthread_cond_wait(3), pthread_create(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_key_create(3), pthread_kill(3), pthread_mutex_lock(3), pthread_mutex_unlock(3), pthread_mutexattr_destroy(3), pthread_mutexattr_init(3), pthread_once(3), pthread_spin_init(3), pthread_spin_lock(3), pthread_rwlockattr_setkind_np(3), pthread_setcancelstate(3), pthread_setcanceltype(3), pthread_setspecific(3), pthread_sigmask(3), pthread_sigqueue(3), و pthread_testcancel(3)
ترجمة¶
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.
| 8 فبراير 2026 | صفحات دليل لينكس 6.18 |