pidfd_open(2)

الاسم
pidfd_open - الحصول على واصف ملف يشير إلى مهمة

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

موجز
#include <sys/syscall.h>      /* تعريف ثوابت SYS_* */
#include <unistd.h>

int syscall(SYS_pidfd_open, pid_t pid, unsigned int flags);

ملاحظة: لا توفر glibc غلافًا لـ pidfd_open()، مما يستلزم استخدام syscall(2).

الوصف
استدعاء النظام pidfd_open() ينشئ واصف ملف يشير إلى المهمة المشار إليها بواسطة pid. يُعاد واصف الملف كنتيجة للدالة؛ ويتم تعيين علامة الإغلاق عند التنفيذ على واصف الملف.

الوسيطة flags إما أن تكون قيمتها 0، أو تحتوي على الأعلام التالية:

PIDFD_NONBLOCK (منذ لينكس 5.10)
    إرجاع واصف ملف غير محظور. إذا لم تنتهِ المهمة المشار إليها بواسطة واصف الملف بعد، فإن محاولة الانتظار على واصف الملف باستخدام waitid(2) ستعيد الخطأ EAGAIN فورًا بدلاً من الحظر.

PIDFD_THREAD (منذ لينكس 6.9)
    إنشاء واصف ملف يشير إلى خيط محدد، بدلاً من عملية (قائد مجموعة الخيوط). إذا لم يتم تعيين هذا العلم، يجب أن يشير pid إلى عملية.

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

الأخطاء

EINVAL
    flags غير صالح.

EINVAL
    pid غير صالح.

EMFILE
    وُصل إلى الحد الأقصى لعدد واصفات الملفات المفتوحة لكل عملية (انظر وصف RLIMIT_NOFILE في getrlimit(2)).

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

ENODEV
    نظام ملفات العقدة المجهول غير متوفر في هذه النواة.

ENOMEM
    ذاكرة النواة المتوفرة غير كافية.

ESRCH
    العملية المحددة بواسطة pid غير موجودة.

المعايير
لينكس.

التاريخ
لينكس 5.3.

ملاحظات
يمكن استخدام تسلسل الكود التالي للحصول على واصف ملف لابن fork(2):

    pid = fork();
    if (pid > 0) {     /* If parent */
        pidfd = pidfd_open(pid, 0);
        ...
    }

حتى إذا كان الابن قد انتهى بالفعل بحلول وقت استدعاء pidfd_open()، فلن يتم إعادة استخدام PID الخاص به وسيشير واصف الملف المُعاد إلى عملية الزومبي الناتجة. لاحظ، مع ذلك، أن هذا مضمون فقط إذا تحققت الشروط التالية:

•   لم يتم تعيين تصرف SIGCHLD صراحةً إلى SIG_IGN (انظر sigaction(2))؛

•   لم يتم تحديد العلم SA_NOCLDWAIT أثناء إنشاء معالج لـ SIGCHLD أو أثناء تعيين تصرف تلك الإشارة إلى SIG_DFL (انظر sigaction(2))؛ و

•   لم يتم حصاد عملية الزومبي في مكان آخر في البرنامج (على سبيل المثال، إما بواسطة معالج إشارة يُنفذ بشكل غير متزامن أو بواسطة wait(2) أو ما شابه ذلك في خيط آخر).

إذا لم يتحقق أي من هذه الشروط، فيجب بدلاً من ذلك إنشاء العملية الابن (مع واصف ملف PID يشير إليها) باستخدام clone(2) مع العلم CLONE_PIDFD.

  حالات استخدام واصفات ملفات PID
يمكن استخدام واصف ملف PID المُعاد بواسطة pidfd_open() (أو بواسطة clone(2) مع العلم CLONE_PID) للأغراض التالية:

•   يمكن استخدام استدعاء النظام pidfd_send_signal(2) لإرسال إشارة إلى العملية المشار إليها بواسطة واصف ملف PID.

•   يمكن مراقبة واصف ملف PID باستخدام poll(2) وselect(2) وepoll(7).

    عندما تنتهي المهمة التي يشير إليها وتصبح زومبي، تشير هذه الواجهات إلى واصف الملف كقابل للقراءة (EPOLLIN). عندما يتم حصاد المهمة، تُنتج هذه الواجهات حدث تعليق (EPOLLHUP).

    لاحظ، مع ذلك، أنه في التنفيذ الحالي، لا يمكن قراءة أي شيء من واصف الملف (read(2) على واصف الملف يفشل مع الخطأ EINVAL). يعتمد سلوك الاستقصاء على ما إذا كان العلم PIDFD_THREAD قد استُخدم عند الحصول على واصف الملف:

    •   مع PIDFD_THREAD، يصبح واصف الملف قابلاً للقراءة عندما تخرج المهمة وتصبح زومبي، حتى لو لم تكن مجموعة الخيوط فارغة.

    •   بدون PIDFD_THREAD، يصبح واصف الملف قابلاً للقراءة فقط عندما يخرج آخر خيط في مجموعة الخيوط.

•   إذا كان واصف ملف PID يشير إلى ابن لعملية الاستدعاء، فيمكن الانتظار عليه باستخدام waitid(2).

•   يمكن استخدام استدعاء النظام pidfd_getfd(2) للحصول على نسخة مكررة من واصف ملف لعملية أخرى يُشار إليها بواسطة واصف ملف PID.

•   يمكن استخدام واصف ملف PID كوسيطة لـ setns(2) للانتقال إلى واحد أو أكثر من نفس مساحات الأسماء (namespaces) مثل العملية المشار إليها بواسطة واصف الملف.

•   يمكن استخدام واصف ملف PID كوسيطة لـ process_madvise(2) لتقديم نصائح حول أنماط استخدام الذاكرة للعملية المشار إليها بواسطة واصف الملف.

استدعاء النظام pidfd_open() هو الطريقة المفضلة للحصول على واصف ملف PID لعملية موجودة بالفعل. البديل هو الحصول على واصف ملف بفتح دليل /proc/pid. ومع ذلك، فإن التقنية الأخيرة ممكنة فقط إذا كان نظام الملفات proc(5) مركبًا (mounted)؛ علاوة على ذلك، واصف الملف الذي يتم الحصول عليه بهذه الطريقة ليس قابلًا للاستقصاء (pollable) ولا يمكن الانتظار عليه باستخدام waitid(2).

أمثلة
البرنامج أدناه يفتح واصف ملف PID للعملية التي يتم تحديد PID الخاص بها كوسيطة سطر أوامر. ثم يستخدم poll(2) لمراقبة واصف الملف لخروج العملية، كما هو موضح بواسطة حدث EPOLLIN.

  مصدر البرنامج
    #define _GNU_SOURCE
    #include <poll.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <unistd.h>

    static int
    pidfd_open(pid_t pid, unsigned int flags)
    {
        return syscall(SYS_pidfd_open, pid, flags);
    }

    int
    main(int argc, char *argv[])
    {
        int            pidfd, ready;
        struct pollfd  pollfd;

        if (argc != 2) {
            fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
            exit(EXIT_SUCCESS);
        }

        pidfd = pidfd_open(atoi(argv[1]), 0);
        if (pidfd == -1) {
            perror("pidfd_open");
            exit(EXIT_FAILURE);
        }

        pollfd.fd = pidfd;
        pollfd.events = POLLIN;

        ready = poll(&pollfd, 1, -1);
        if (ready == -1) {
            perror("poll");
            exit(EXIT_FAILURE);
        }

        printf("Events (%#x): POLLIN is %sset\n", pollfd.revents,
               (pollfd.revents & POLLIN) ? "" : "not ");

        close(pidfd);
        exit(EXIT_SUCCESS);
    }

انظر أيضًا
clone(2), kill(2), pidfd_getfd(2), pidfd_send_signal(2), poll(2), process_madvise(2), select(2), setns(2), waitid(2), epoll(7)

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

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

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