sigaltstack(2)

الاسم
sigaltstack - ضبط و/أو الحصول على سياق كومة الإشارة

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

موجز
#include <signal.h>

int sigaltstack(const stack_t *_Nullable restrict ss,
                stack_t *_Nullable restrict old_ss);

    متطلبات ماكروات اختبار الميزات لـ glibc (انظر feature_test_macros(7)):

sigaltstack():
    _XOPEN_SOURCE >= 500
        || /* منذ glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
        || /* glibc <= 2.19: */ _BSD_SOURCE

الوصف
تسمح sigaltstack() لسلسلة تنفيذ بتعريف كومة إشارة بديلة جديدة و/أو استرداد حالة كومة إشارة بديلة موجودة. تُستخدم كومة الإشارة البديلة أثناء تنفيذ معالج إشارة إذا طلب إنشاء ذلك المعالج (انظر sigaction(2)) ذلك.

التسلسل الطبيعي للأحداث لاستخدام كومة إشارة بديلة هو التالي:

1.  تخصيص منطقة ذاكرة لاستخدامها ككومة إشارة بديلة.

2.  استخدام sigaltstack() لإعلام النظام بوجود وموقع كومة الإشارة البديلة.

3.  عند إنشاء معالج إشارة باستخدام sigaction(2)، إعلام النظام بأنه يجب تنفيذ معالج الإشارة على كومة الإشارة البديلة بتحديد العلم SA_ONSTACK.

تُستخدم الوسيطة ss لتحديد كومة إشارة بديلة جديدة، بينما تُستخدم الوسيطة old_ss لاسترداد معلومات حول كومة الإشارة المنشأة حاليًا. إذا كنا مهتمين بأداء مهمة واحدة فقط من هذه المهام، فيمكن تحديد الوسيطة الأخرى كـ NULL.

النوع stack_t المستخدم لكتابة وسائط هذه الدالة يُعرف كما يلي:

    typedef struct {
        void  *ss_sp;     /* Base address of stack */
        int    ss_flags;  /* Flags */
        size_t ss_size;   /* Number of bytes in stack */
    } stack_t;

لإنشاء كومة إشارة بديلة جديدة، تُضبط حقول هذه البنية كما يلي:

ss.ss_flags
    يحتوي هذا الحقل إما على 0، أو العلم التالي:

    SS_AUTODISARM (منذ Linux 4.7)
        مسح إعدادات كومة الإشارة البديلة عند الدخول إلى معالج الإشارة. عند عودة معالج الإشارة، تُستعاد إعدادات كومة الإشارة البديلة السابقة.

        أُضيف هذا العلم لجعل التبديل بعيدًا عن معالج الإشارة باستخدام swapcontext(3) آمنًا. بدون هذا العلم، ستُفسد إشارة تُعالج لاحقًا حالة معالج الإشارة المُبدّل بعيدًا. على النوى التي لا يُدعم فيها هذا العلم، تفشل sigaltstack() مع الخطأ EINVAL عند توفير هذا العلم.

ss.ss_sp
    يحدد هذا الحقل عنوان بداية الكومة. عند استدعاء معالج إشارة على الكومة البديلة، يقوم النواة آليًا بمحاذاة العنوان المعطى في ss.ss_sp إلى حد عنوان مناسب لبنية العتاد الأساسية.

ss.ss_size
    يحدد هذا الحجم حجم الكومة. يُعرف الثابت SIGSTKSZ ليكون كبيرًا بما يكفي لتغطية متطلبات الحجم المعتادة لكومة إشارة بديلة، ويُعرف الثابت MINSIGSTKSZ الحد الأدنى للحجم المطلوب لتنفيذ معالج إشارة.

لتعطيل كومة موجودة، حدد ss.ss_flags كـ SS_DISABLE. في هذه الحالة، تتجاهل النواة أي أعلام أخرى في ss.ss_flags والحقول المتبقية في ss.

إذا لم يكن old_ss NULL، فإنه يُستخدم لإرجاع معلومات حول كومة الإشارة البديلة التي كانت سارية قبل استدعاء sigaltstack(). يُرجع الحقلان old_ss.ss_sp و old_ss.ss_size عنوان البداية وحجم تلك الكومة. قد يُرجع old_ss.ss_flags إحدى القيم التالية:

SS_ONSTACK
    تنفذ سلسلة التنفيذ حاليًا على كومة الإشارة البديلة. (لاحظ أنه لا يمكن تغيير كومة الإشارة البديلة إذا كانت سلسلة التنفيذ تنفذ عليها حاليًا.)

SS_DISABLE
    كومة الإشارة البديلة معطلة حاليًا.

    بدلاً من ذلك، تُرجع هذه القيمة إذا كانت سلسلة التنفيذ تنفذ حاليًا على كومة إشارة بديلة أُنشئت باستخدام العلم SS_AUTODISARM. في هذه الحالة، من الآمن التبديل بعيدًا عن معالج الإشارة باستخدام swapcontext(3). من الممكن أيضًا إعداد كومة إشارة بديلة مختلفة باستخدام استدعاء إضافي لـ sigaltstack().

SS_AUTODISARM
    تم وضع علامة على مكدس الإشارة البديل ليتم نزع سلاحه آليًا كما هو موصوف أعلاه.

بتحديد ss كقيمة NULL، و old_ss كقيمة غير NULL، يمكن للمرء الحصول على الإعدادات الحالية لمكدس الإشارة البديل دون تغييرها.

قيمة الإرجاع
تُرجع sigaltstack() 0 عند النجاح، أو -1 عند الفشل مع تعيين errno للإشارة إلى الخطأ.

الأخطاء

EFAULT
    إما ss أو old_ss ليس NULL ويشير إلى منطقة خارج نطاق عنوان العملية.

EINVAL
    ss ليس NULL ويحتوي حقل ss_flags على علامة غير صالحة.

ENOMEM
    الحجم المحدد لمكدس الإشارة البديل الجديد ss.ss_size كان أقل من MINSIGSTKSZ.

EPERM
    تمت محاولة تغيير مكدس الإشارة البديل بينما كان نشطًا (أي، كان الخيط ينفذ بالفعل على مكدس الإشارة البديل الحالي).

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

المعايير
POSIX.1-2024.

SS_AUTODISARM هو امتداد لنظام لينكس.

التاريخ
POSIX.1-2001, SUSv2, SVr4.

ملاحظات
الاستخدام الأكثر شيوعًا لمكدس الإشارة البديل هو معالجة إشارة SIGSEGV التي تُنشأ إذا استُنفدت المساحة المتاحة للمكدس القياسي: في هذه الحالة، لا يمكن استدعاء معالج إشارة لـ SIGSEGV على المكدس القياسي؛ إذا أردنا معالجتها، يجب استخدام مكدس إشارة بديل.

إنشاء مكدس إشارة بديل مفيد إذا توقع خيط أنه قد يستنفد مكدسه القياسي. قد يحدث هذا، على سبيل المثال، لأن المكدس ينمو بشكل كبير لدرجة أنه يصطدم بالكومة المتنامية لأعلى، أو يصل إلى حد محدد بواسطة استدعاء setrlimit(RLIMIT_STACK, &rlim). إذا استُنفد المكدس القياسي، ترسل النواة إشارة SIGSEGV إلى الخيط. في هذه الظروف، الطريقة الوحيدة لالتقاط هذه الإشارة هي على مكدس إشارة بديل.

في معظم بنى العتاد التي يدعمها لينكس، تنمو المكدسات لأسفل. تراعي sigaltstack() آليًا اتجاه نمو المكدس.

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

يزيل استدعاء ناجح لـ execve(2) أي مكدس إشارة بديل موجود. ترث عملية فرعية مُنشأة عبر fork(2) نسخة من إعدادات مكدس الإشارة البديل لأبويها. وينطبق الشيء نفسه على عملية فرعية مُنشأة باستخدام clone(2)، ما لم تتضمن أعلام clone CLONE_VM ولا تتضمن CLONE_VFORK، وفي هذه الحالة يتم تعطيل أي مكدس إشارة بديل تم إنشاؤه في العملية الأم في العملية الفرعية.

تحل sigaltstack() محل الاستدعاء الأقدم sigstack(). للتوافق مع الإصدارات السابقة، توفر glibc أيضًا sigstack(). يجب كتابة جميع التطبيقات الجديدة باستخدام sigaltstack().

  السجل
كان لدى 4.2BSD استدعاء نظام sigstack(). استخدم هيكلًا مختلفًا قليلاً، وكان له عيب رئيسي وهو أن المُستدعي كان عليه معرفة اتجاه نمو المكدس.

العلل
في لينكس 2.2 والإصدارات الأقدم، كانت العلامة الوحيدة التي يمكن تحديدها في ss.sa_flags هي SS_DISABLE. في الفترة التي سبقت إصدار نواة لينكس 2.4، تم إجراء تغيير للسماح لـ sigaltstack() بالسماح بـ ss.ss_flags==SS_ONSTACK بنفس معنى ss.ss_flags==0 (أي، إدراج SS_ONSTACK في ss.ss_flags هو عملية لا تأثير لها). في التطبيقات الأخرى، ووفقًا لـ POSIX.1، يظهر SS_ONSTACK فقط كعلامة مُبلغ عنها في old_ss.ss_flags. في لينكس، ليست هناك حاجة أبدًا لتحديد SS_ONSTACK في ss.ss_flags، وفي الواقع يجب تجنب ذلك لأسباب تتعلق بقابلية النقل: تعطي العديد من الأنظمة الأخرى خطأً إذا تم تحديد SS_ONSTACK في ss.ss_flags.

أمثلة
يوضح مقطع الكود التالي استخدام sigaltstack() (و sigaction(2)) لتثبيت مكدس إشارة بديل يستخدمه معالج إشارة SIGSEGV:

    stack_t ss;

    ss.ss_sp = malloc(SIGSTKSZ);
    if (ss.ss_sp == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    if (sigaltstack(&ss, NULL) == -1) {
        perror("sigaltstack");
        exit(EXIT_FAILURE);
    }

    sa.sa_flags = SA_ONSTACK;
    sa.sa_handler = handler();      /* Address of a signal handler */
    sigemptyset(&sa.sa_mask);
    if (sigaction(SIGSEGV, &sa, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

انظر أيضًا
execve(2), setrlimit(2), sigaction(2), siglongjmp(3), sigsetjmp(3), signal(7)

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

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

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