eventfd(2)

الاسم
eventfd - إنشاء واصف ملف للإعلام بالأحداث

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

موجز
#include <sys/eventfd.h>

int eventfd(unsigned int initval, int flags);

الوصف
تنشئ eventfd() "كائن eventfd" يمكن استخدامه كآلية انتظار/إعلام بالأحداث من قبل تطبيقات مساحة المستخدم، ومن قبل النواة لإعلام تطبيقات مساحة المستخدم بالأحداث. يحتوي الكائن على عداد صحيح غير موقع 64 بت (uint64_t) تحتفظ به النواة. يُهيأ هذا العداد بالقيمة المحددة في الوسيط initval.

كقيمة إرجاع، تُرجع eventfd() واصف ملف جديد يمكن استخدامه للإشارة إلى كائن eventfd.

يمكن تطبيق عملية OR على مستوى البتات للقيم التالية في flags لتغيير سلوك eventfd():

EFD_CLOEXEC (منذ لينكس 2.6.27)
    اضبط علامة الإغلاق عند التنفيذ (FD_CLOEXEC) على واصف الملف الجديد. انظر وصف العلامة O_CLOEXEC في open(2) للأسباب التي تجعل هذا مفيدًا.

EFD_NONBLOCK (منذ لينكس 2.6.27)
    اضبط علامة حالة الملف O_NONBLOCK على وصف الملف المفتوح (انظر open(2)) المشار إليه بواسطة واصف الملف الجديد. استخدام هذه العلامة يوفر استدعاءات إضافية لـ fcntl(2) لتحقيق النتيجة نفسها.

EFD_SEMAPHORE (منذ لينكس 2.6.30)
    توفر دلالات شبيهة بالإشارة (semaphore) للقراءات من واصف الملف الجديد. انظر أدناه.

حتى لينكس 2.6.26، معطى flags غير مستخدم، ويجب تحديده كصفر.

يمكن تنفيذ العمليات التالية على واصف الملف المُعاد بواسطة eventfd():

read(2)
    تُرجع كل read(2) ناجحة عددًا صحيحًا من 8 بايت. تفشل read(2) مع الخطأ EINVAL إذا كان حجم المخزن المؤقت المقدم أقل من 8 بايت.

    القيمة المُعادة بواسطة read(2) تكون بترتيب بايت المضيف—أي ترتيب البايت الأصلي للأعداد الصحيحة على جهاز المضيف.

    تعتمد دلالات read(2) على ما إذا كان عداد eventfd لديه حاليًا قيمة غير صفرية وما إذا كانت العلامة EFD_SEMAPHORE قد حُددت عند إنشاء واصف ملف eventfd:

    •   إذا لم تُحدد EFD_SEMAPHORE وكان للعداد eventfd قيمة غير صفرية، فإن read(2) تُرجع 8 بايت تحتوي على تلك القيمة، وتُعاد قيمة العداد إلى الصفر.

    •   إذا حُددت EFD_SEMAPHORE وكان للعداد eventfd قيمة غير صفرية، فإن read(2) تُرجع 8 بايت تحتوي على القيمة 1، وتُقلل قيمة العداد بمقدار 1.

    •   إذا كان عداد eventfd صفرًا وقت استدعاء read(2)، فإن الاستدعاء إما أن يحظر حتى يصبح العداد غير صفري (وعندها، تستمر read(2) كما هو موصوف أعلاه) أو يفشل مع الخطأ EAGAIN إذا جُعل واصف الملف غير محظور.

write(2)
    يضيف استدعاء write(2) قيمة العدد الصحيح 8 بايت المقدمة في مخزنه المؤقت إلى العداد. القيمة القصوى التي يمكن تخزينها في العداد هي أكبر قيمة غير موقعة 64 بت ناقص 1 (أي 0xfffffffffffffffe). إذا تسببت الإضافة في تجاوز قيمة العداد للحد الأقصى، فإن write(2) إما تحظر حتى تُنفذ read(2) على واصف الملف، أو تفشل مع الخطأ EAGAIN إذا جُعل واصف الملف غير محظور.

    تفشل write(2) مع الخطأ EINVAL إذا كان حجم المخزن المؤقت المقدم أقل من 8 بايت، أو إذا جرت محاولة لكتابة القيمة 0xffffffffffffffff.

poll(2)
select(2)
(وما شابه ذلك)
    يدعم واصف الملف المُعاد poll(2) (وبالمثل epoll(7)) و select(2)، كما يلي:

    •   واصف الملف قابل للقراءة (وسيط select(2) readfds؛ علامة poll(2) POLLIN) إذا كان للعداد قيمة أكبر من 0.

    •   واصف الملف قابل للكتابة (وسيط select(2) writefds؛ علامة poll(2) POLLOUT) إذا كان من الممكن كتابة قيمة لا تقل عن "1" دون حظر.

    •   إذا اكتُشف تجاوز لقيمة العداد، فإن select(2) تشير إلى واصف الملف على أنه قابل للقراءة والكتابة معًا، وتُرجع poll(2) حدث POLLERR. كما ذُكر أعلاه، لا يمكن لـ write(2) أبدًا تجاوز العداد. ومع ذلك، يمكن أن يحدث تجاوز إذا نُفذت 2^64 "إشارة إرسال" eventfd بواسطة النظام الفرعي KAIO (ممكن نظريًا، لكنه غير محتمل عمليًا). إذا حدث تجاوز، فإن read(2) ستُرجع قيمة uint64_t القصوى (أي 0xffffffffffffffff).

    يدعم واصف ملف eventfd أيضًا واجهات برمجة تطبيقات تعدد إرسال واصفات الملف الأخرى: pselect(2) و ppoll(2).

close(2)
    عندما لا يعود واصف الملف مطلوبًا، يجب إغلاقه. عندما تُغلق جميع واصفات الملف المرتبطة بنفس كائن eventfd، تُحرر النواة موارد الكائن.

تُورث نسخة من واصف الملف الذي أنشأته eventfd() بواسطة العملية التابعة الناتجة عن fork(2). يرتبط واصف الملف المكرر بنفس كائن eventfd. تُحفظ واصفات الملف التي أنشأتها eventfd() عبر execve(2)، ما لم تُضبط علامة الإغلاق عند التنفيذ.

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

الأخطاء

EINVAL
    عُيّنت قيمة غير مدعومة في flags.

EMFILE
    وُصل إلى الحد الأقصى لواصفات الملفات المفتوحة لكل عملية.

ENFILE
    وُصل إلى الحد الأقصى لإجمالي عدد الملفات المفتوحة على مستوى النظام.

ENODEV
    تعذر وصل جهاز inode (داخلي) مجهول.

ENOMEM
    لم تكن هناك ذاكرة كافية لإنشاء واصف ملف eventfd جديد.

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

الإصدارات

  الاختلافات بين مكتبة C والنواة
يوجد استدعاءان نظاميان أساسيان في لينكس: eventfd() و eventfd2() الأحدث. لا ينفذ استدعاء النظام الأول وسيط flags. ينفذ استدعاء النظام الثاني قيم flags الموصوفة أعلاه. ستستخدم دالة الغلاف glibc eventfd2() حيثما كانت متاحة.

  ميزات glibc إضافية
تعرف مكتبة C في GNU نوعًا إضافيًا، ودالتين تحاولان تجريد بعض تفاصيل القراءة والكتابة على واصف ملف eventfd:

    typedef uint64_t eventfd_t;

    int eventfd_read(int fd, eventfd_t *value);
    int eventfd_write(int fd, eventfd_t value);

تنفذ الدالتان عمليات القراءة والكتابة على واصف ملف eventfd، وتُعيدان 0 إذا نُقل العدد الصحيح من البايتات، أو -1 بخلاف ذلك.

المعايير
لينكس، جنو.

التاريخ

eventfd()
    لينكس 2.6.22، glibc 2.8.

eventfd2()
    لينكس 2.6.27 (انظر الإصدارات). منذ glibc 2.9، ستستخدم الدالة المغلفة eventfd() استدعاء النظام eventfd2() إذا كان مدعومًا من النواة.

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

عند استخدامه في النواة، يمكن لواصف ملف eventfd توفير جسر من النواة إلى مساحة المستخدم، مما يسمح، على سبيل المثال، لوظائف مثل KAIO (AIO النواة) بالإشارة إلى واصف ملف بأن عملية ما قد اكتملت.

نقطة رئيسية حول واصف ملف eventfd هي أنه يمكن مراقبته تمامًا مثل أي واصف ملف آخر باستخدام select(2) أو poll(2) أو epoll(7). هذا يعني أن التطبيق يمكنه مراقبة جاهزية الملفات "التقليدية" وجاهزية آليات النواة الأخرى التي تدعم واجهة eventfd في وقت واحد. (بدون واجهة eventfd()، لا يمكن تعدد هذه الآليات عبر select(2) أو poll(2) أو epoll(7).)

يمكن عرض القيمة الحالية لعداد eventfd عبر الإدخال الخاص بواصف الملف المقابل في دليل /proc/pid/fdinfo الخاص بالعملية. انظر proc(5) لمزيد من التفاصيل.

أمثلة
يقوم البرنامج التالي بإنشاء واصف ملف eventfd ثم يتفرع لإنشاء عملية تابعة. بينما ينام الأب لفترة وجيزة، يكتب الابن كل عدد صحيح من الأعداد الصحيحة المقدمة في وسائط سطر أوامر البرنامج إلى واصف ملف eventfd. عندما ينهي الأب النوم، يقرأ من واصف ملف eventfd.

تظهر جلسة الصدفة التالية تشغيلًا نموذجيًا للبرنامج:

    $ ./a.out 1 2 4 7 14
    Child writing 1 to efd
    Child writing 2 to efd
    Child writing 4 to efd
    Child writing 7 to efd
    Child writing 14 to efd
    Child completed write loop
    Parent about to read
    Parent read 28 (0x1c) from efd

  مصدر البرنامج
    #include <err.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/eventfd.h>
    #include <sys/types.h>
    #include <unistd.h>

    int
    main(int argc, char *argv[])
    {
        int       efd;
        uint64_t  u;
        ssize_t   s;

        if (argc < 2) {
            fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        efd = eventfd(0, 0);
        if (efd == -1)
            err(EXIT_FAILURE, "eventfd");

        switch (fork()) {
        case 0:
            for (size_t j = 1; j < argc; j++) {
                printf("Child writing %s to efd\n", argv[j]);
                u = strtoull(argv[j], NULL, 0);
                        /* strtoull() allows various bases */
                s = write(efd, &u, sizeof(uint64_t));
                if (s != sizeof(uint64_t))
                    err(EXIT_FAILURE, "write");
            }
            printf("Child completed write loop\n");

            exit(EXIT_SUCCESS);

        default:
            sleep(2);

            printf("Parent about to read\n");
            s = read(efd, &u, sizeof(uint64_t));
            if (s != sizeof(uint64_t))
                err(EXIT_FAILURE, "read");
            printf("Parent read %w64u (%#w64x) from efd\n", u, u);
            exit(EXIT_SUCCESS);

        case -1:
            err(EXIT_FAILURE, "fork");
        }
    }

انظر أيضًا
futex(2), pipe(2), poll(2), read(2), select(2), signalfd(2), timerfd_create(2), write(2), epoll(7), sem_overview(7)

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

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

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