makecontext(3)

الاسم
makecontext, swapcontext - معالجة سياق المستخدم

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <ucontext.h>

void makecontext(ucontext_t *ucp, typeof(void (int arg0, ...)) *func,
                 int argc, ...);
int swapcontext(ucontext_t *restrict oucp,
                 const ucontext_t *restrict ucp);

الوصف
في بيئة شبيهة بـ System V، يوجد النوع ucontext_t (المُعرَّف في <ucontext.h> والموصوف في getcontext(3)) والدوال الأربع getcontext(3) وsetcontext(3) وmakecontext() وswapcontext() التي تسمح بتبديل السياق على مستوى المستخدم بين خيوط تحكم متعددة داخل عملية.

تعدّل الدالة makecontext() السياق المُشار إليه بواسطة ucp (الذي حُصِل عليه من استدعاء getcontext(3)). قبل استدعاء makecontext()، يجب على المستدعي تخصيص مكدس جديد لهذا السياق وتعيين عنوانه إلى ucp->uc_stack، وتعريف سياق خلف وتعيين عنوانه إلى ucp->uc_link.

عند تفعيل هذا السياق لاحقًا (باستخدام setcontext(3) أو swapcontext())، تُستدعى الدالة func وتُمرَّر إليها سلسلة وسائط الأعداد الصحيحة (int) التي تلي argc؛ يجب على المستدعي تحديد عدد هذه الوسائط في argc. عند عودة هذه الدالة، يُفعَّل السياق الخلف. إذا كان مؤشر السياق الخلف NULL، يخرج الخيط.

تحفظ الدالة swapcontext() السياق الحالي في البنية المُشار إليها بواسطة oucp، ثم تُفعِّل السياق المُشار إليه بواسطة ucp.

قيمة الإرجاع
عند النجاح، لا تعود swapcontext(). (لكن قد نعود لاحقًا، في حالة تفعيل oucp، حيث يبدو أن swapcontext() تعيد 0.) عند الخطأ، تعيد swapcontext() -1 وتضبط errno للإشارة إلى الخطأ.

الأخطاء

ENOMEM
    مساحة مكدس متبقية غير كافية.

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
makecontext() | سلامة الخيوط | آمن للمسارات المتعددة (MT-Safe) سباق:ucp
swapcontext() | سلامة الخيوط | MT-Safe race:oucp race:ucp

المعايير
لا شيء.

التاريخ
glibc 2.1. SUSv2, POSIX.1-2001. أُزيل في POSIX.1-2008، مستشهدًا بمشاكل قابلية النقل، ويوصي بإعادة كتابة التطبيقات لاستخدام خيوط POSIX بدلاً من ذلك.

ملاحظات
تفسير ucp->uc_stack هو تمامًا كما في sigaltstack(2)، أي أن هذه البنية تحتوي على بداية وطول منطقة ذاكرة لتُستخدم كمكدس، بغض النظر عن اتجاه نمو المكدس. وبالتالي، ليس من الضروري لبرنامج المستخدم القلق بشأن هذا الاتجاه.

في البنى حيث int وأنواع المؤشرات بنفس الحجم (مثل x86-32، حيث كلا النوعين 32 بت)، قد تتمكن من تمرير المؤشرات كوسائط إلى makecontext() بعد argc. لكن، القيام بذلك غير مضمون ليكون محمولاً، وهو غير مُعرَّف وفقًا للمعايير، ولن يعمل في البنى حيث المؤشرات أكبر من int. ومع ذلك، بدءًا من glibc 2.8، أجرت glibc بعض التغييرات على makecontext() للسماح بذلك في بعض البنى 64 بت (مثل x86-64).

أمثلة
يوضح برنامج المثال أدناه استخدام getcontext(3) وmakecontext() وswapcontext(). يؤدي تشغيل البرنامج إلى إخراج التالي:

    $ ./a.out
    main: swapcontext(&uctx_main, &uctx_func2)
    func2: started
    func2: swapcontext(&uctx_func2, &uctx_func1)
    func1: started
    func1: swapcontext(&uctx_func1, &uctx_func2)
    func2: returning
    func1: returning
    main: exiting

  مصدر البرنامج
    #include <err.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <ucontext.h>

    static ucontext_t uctx_main, uctx_func1, uctx_func2;

    static void
    func1(void)
    {
        printf("%s: started\n", __func__);
        printf("%s: swapcontext(&uctx_func1, &uctx_func2)\n", __func__);
        if (swapcontext(&uctx_func1, &uctx_func2) == -1)
            err(EXIT_FAILURE, "swapcontext");
        printf("%s: returning\n", __func__);
    }

    static void
    func2(void)
    {
        printf("%s: started\n", __func__);
        printf("%s: swapcontext(&uctx_func2, &uctx_func1)\n", __func__);
        if (swapcontext(&uctx_func2, &uctx_func1) == -1)
            err(EXIT_FAILURE, "swapcontext");
        printf("%s: returning\n", __func__);
    }

    int
    main(int argc, char *argv[])
    {
        char func1_stack[16384];
        char func2_stack[16384];

        if (getcontext(&uctx_func1) == -1)
            err(EXIT_FAILURE, "getcontext");
        uctx_func1.uc_stack.ss_sp = func1_stack;
        uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
        uctx_func1.uc_link = &uctx_main;
        makecontext(&uctx_func1, func1, 0);

        if (getcontext(&uctx_func2) == -1)
            err(EXIT_FAILURE, "getcontext");
        uctx_func2.uc_stack.ss_sp = func2_stack;
        uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
        /* Successor context is f1(), unless argc > 1 */
        uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
        makecontext(&uctx_func2, func2, 0);

        printf("%s: swapcontext(&uctx_main, &uctx_func2)\n", __func__);
        if (swapcontext(&uctx_main, &uctx_func2) == -1)
            err(EXIT_FAILURE, "swapcontext");

        printf("%s: exiting\n", __func__);
        exit(EXIT_SUCCESS);
    }

انظر أيضًا
sigaction(2), sigaltstack(2), sigprocmask(2), getcontext(3), sigsetjmp(3)

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

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

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