pthread_getattr_np(3)

الاسم
pthread_getattr_np - الحصول على سمات الخيط المُنشأ

المكتبة
مكتبة مسالك POSIX (libpthread، -lpthread)

موجز
#define _GNU_SOURCE             /* انظر feature_test_macros(7) */
#include <pthread.h>

int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);

الوصف
الدالة pthread_getattr_np() تُهيئ كائن سمات الخيط المشار إليه بواسطة attr بحيث يحتوي على قيم السمات الفعلية التي تصف الخيط الجاري thread.

قد تختلف قيم السمات المُرجعة عن قيم السمات المُقابلة المُمررة في كائن attr الذي استُخدم لإنشاء الخيط باستخدام pthread_create(3). على وجه الخصوص، قد تختلف السمات التالية:

•   حالة الفصل، حيث قد يفصل الخيط القابل للانضمام نفسه بعد الإنشاء؛

•   حجم المكدس، والذي قد تُحاذيه التطبيقات إلى حد مناسب.

•   وحجم الحارس، والذي قد تُقرّبه التطبيقات لأعلى إلى مضاعف حجم الصفحة، أو تتجاهله (أي تعامله كـ 0)، إذا كان التطبيق يخصص مكدسه الخاص.

علاوة على ذلك، إذا لم تُضبط سمة عنوان المكدس في كائن سمات الخيط المستخدم لإنشاء الخيط، فإن كائن سمات الخيط المُعاد سيُبلغ عن عنوان المكدس الفعلي الذي اختارته التطبيقات للخيط.

عندما لا يعود كائن سمات الخيط المُعاد بواسطة pthread_getattr_np() مطلوبًا، يجب تدميره باستخدام pthread_attr_destroy(3).

قيمة الإرجاع
عند النجاح، تعيد هذه الدالة 0؛ وعند حدوث خطأ، تعيد رقم خطأ غير صفري.

الأخطاء

ENOMEM
    ذاكرة غير كافية.

بالإضافة إلى ذلك، إذا كان thread يشير إلى الخيط الرئيسي، فقد تفشل pthread_getattr_np() بسبب أخطاء من استدعاءات أساسية متنوعة: fopen(3)، إذا تعذر فتح /proc/self/maps؛ و getrlimit(2)، إذا لم يكن حد المورد RLIMIT_STACK مدعومًا.

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
pthread_getattr_np() | سلامة الخيوط | MT-Safe

المعايير
جنو؛ ومن هنا جاءت اللاحقة "_np" (غير محمول) في الاسم.

التاريخ
glibc 2.2.3.

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

في التشغيل الأول، على نظام x86-32، يُنشأ خيط باستخدام السمات المبدئية:

    $ ulimit -s      # No stack limit ==> default stack size is 2 MB
    unlimited
    $ ./a.out
    Attributes of created thread:
            Guard size          = 4096 bytes
            Stack address       = 0x40196000 (EOS = 0x40397000)
            Stack size          = 0x201000 (2101248) bytes

في التشغيل التالي، نرى أنه إذا حُدد حجم حارس، يُقرّب لأعلى إلى المضاعف التالي لحجم صفحة النظام (4096 بايت على x86-32):

    $ ./a.out -g 4097
    Thread attributes object after initializations:
            Guard size          = 4097 bytes
            Stack address       = (nil)
            Stack size          = 0x0 (0) bytes

    Attributes of created thread:
            Guard size          = 8192 bytes
            Stack address       = 0x40196000 (EOS = 0x40397000)
            Stack size          = 0x201000 (2101248) bytes

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

    $ ./a.out -g 4096 -s 0x8000 -a
    Allocated thread stack at 0x804d000

    Thread attributes object after initializations:
            Guard size          = 4096 bytes
            Stack address       = 0x804d000 (EOS = 0x8055000)
            Stack size          = 0x8000 (32768) bytes

    Attributes of created thread:
            Guard size          = 0 bytes
            Stack address       = 0x804d000 (EOS = 0x8055000)
            Stack size          = 0x8000 (32768) bytes

  مصدر البرنامج
    #define _GNU_SOURCE     /* To get pthread_getattr_np() declaration */
    #include <err.h>
    #include <errno.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    static void
    display_stack_related_attributes(pthread_attr_t *attr, char *prefix)
    {
        int s;
        size_t stack_size, guard_size;
        void *stack_addr;

        s = pthread_attr_getguardsize(attr, &guard_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_getguardsize");
        printf("%sGuard size          = %zu bytes\n", prefix, guard_size);

        s = pthread_attr_getstack(attr, &stack_addr, &stack_size);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_getstack");
        printf("%sStack address       = %p", prefix, stack_addr);
        if (stack_size > 0)
            printf(" (EOS = %p)", (char *) stack_addr + stack_size);
        printf("\n");
        printf("%sStack size          = %#zx (%zu) bytes\n",
               prefix, stack_size, stack_size);
    }

    static void
    display_thread_attributes(pthread_t thread, char *prefix)
    {
        int s;
        pthread_attr_t attr;

        s = pthread_getattr_np(thread, &attr);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_getattr_np");

        display_stack_related_attributes(&attr, prefix);

        s = pthread_attr_destroy(&attr);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_attr_destroy");
    }

    static void *           /* Start function for thread we create */
    thread_start(void *arg)
    {
        printf("Attributes of created thread:\n");
        display_thread_attributes(pthread_self(), "\t");

        exit(EXIT_SUCCESS);         /* Terminate all threads */
    }

    static void
    usage(char *pname, char *msg)
    {
        if (msg != NULL)
            fputs(msg, stderr);
        fprintf(stderr, "Usage: %s [-s stack-size [-a]]"
                " [-g guard-size]\n", pname);
        fprintf(stderr, "\t\t-a means program should allocate stack\n");
        exit(EXIT_FAILURE);
    }

    static pthread_attr_t *   /* Get thread attributes from command line */
    get_thread_attributes_from_cl(int argc, char *argv[],
                                  pthread_attr_t *attrp)
    {
        int s, opt, allocate_stack;
        size_t stack_size, guard_size;
        void *stack_addr;
        pthread_attr_t *ret_attrp = NULL;   /* Set to attrp if we initialize
                                               a thread attributes object */
        allocate_stack = 0;
        stack_size = -1;
        guard_size = -1;

        while ((opt = getopt(argc, argv, "ag:s:")) != -1) {
            switch (opt) {
            case 'a':   allocate_stack = 1;                     break;
            case 'g':   guard_size = strtoul(optarg, NULL, 0);  break;
            case 's':   stack_size = strtoul(optarg, NULL, 0);  break;
            default:    usage(argv[0], NULL);
            }
        }

        if (allocate_stack && stack_size == -1)
            usage(argv[0], "Specifying -a without -s makes no sense\n");

        if (argc > optind)
            usage(argv[0], "Extraneous command-line arguments\n");

        if (stack_size != -1 || guard_size > 0) {
            ret_attrp = attrp;

            s = pthread_attr_init(attrp);
            if (s != 0)
                errc(EXIT_FAILURE, s, "pthread_attr_init");
        }

        if (stack_size != -1) {
            if (!allocate_stack) {
                s = pthread_attr_setstacksize(attrp, stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
            } else {
                s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),
                                   stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "posix_memalign");
                printf("Allocated thread stack at %p\n\n", stack_addr);

                s = pthread_attr_setstack(attrp, stack_addr, stack_size);
                if (s != 0)
                    errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
            }
        }

        if (guard_size != -1) {
            s = pthread_attr_setguardsize(attrp, guard_size);
            if (s != 0)
                errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
        }

        return ret_attrp;
    }

    int
    main(int argc, char *argv[])
    {
        int s;
        pthread_t thr;
        pthread_attr_t attr;
        pthread_attr_t *attrp = NULL;    /* Set to &attr if we initialize
                                            a thread attributes object */

        attrp = get_thread_attributes_from_cl(argc, argv, &attr);

        if (attrp != NULL) {
            printf("Thread attributes object after initializations:\n");
            display_stack_related_attributes(attrp, "\t");
            printf("\n");
        }

        s = pthread_create(&thr, attrp, &thread_start, NULL);
        if (s != 0)
            errc(EXIT_FAILURE, s, "pthread_create");

        if (attrp != NULL) {
            s = pthread_attr_destroy(attrp);
            if (s != 0)
                errc(EXIT_FAILURE, s, "pthread_attr_destroy");
        }

        pause();    /* Terminates when other thread calls exit() */
    }

انظر أيضًا
pthread_attr_getaffinity_np(3)، pthread_attr_getdetachstate(3)، pthread_attr_getguardsize(3)، pthread_attr_getinheritsched(3)، pthread_attr_getschedparam(3)، pthread_attr_getschedpolicy(3)، pthread_attr_getscope(3)، pthread_attr_getstack(3)، pthread_attr_getstackaddr(3)، pthread_attr_getstacksize(3)، pthread_attr_init(3)، pthread_create(3)، pthreads(7)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.