kcmp(2)

الاسم
kcmp - مقارنة عمليتين لتحديد ما إذا كانتا تشاركان مورد نواة

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

موجز
#include <linux/kcmp.h>       /* Definition of KCMP_* constants */
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>

int syscall(SYS_kcmp, pid_t pid1, pid_t pid2, int type,
            unsigned long idx1, unsigned long idx2);

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

الوصف
يمكن استخدام استدعاء النظام kcmp() للتحقق مما إذا كانت العمليتان المحددتان بواسطة pid1 و pid2 تشاركان مورد نواة مثل الذاكرة الافتراضية، وواصفات الملفات، وما إلى ذلك.

يخضع الإذن لاستخدام kcmp() لفحوصات وضع الوصول ptrace PTRACE_MODE_READ_REALCREDS ضد كل من pid1 و pid2؛ انظر ptrace(2).

تحدد الوسيطة type أي مورد سيتم مقارنته في العمليتين. تأخذ إحدى القيم التالية:

KCMP_FILE
    التحقق مما إذا كان واصف الملف idx1 في العملية pid1 يشير إلى نفس وصف الملف المفتوح (انظر open(2)) مثل واصف الملف idx2 في العملية pid2. يمكن أن يحدث وجود واصفي ملف يشيران إلى نفس وصف الملف المفتوح نتيجة لـ dup(2) (وما شابه) fork(2)، أو تمرير واصفات الملفات عبر مقبس نطاق (انظر unix(7)).

KCMP_FILES
    التحقق مما إذا كانت العمليتان تشاركان نفس مجموعة واصفات الملفات المفتوحة. يتم تجاهل الوسيطتين idx1 و idx2. انظر مناقشة العلم CLONE_FILES في clone(2).

KCMP_FS
    التحقق مما إذا كانت العمليتان تشاركان نفس معلومات نظام الملفات (أي قناع إنشاء وضع الملف، دليل العمل، وجذر نظام الملفات). يتم تجاهل الوسيطتين idx1 و idx2. انظر مناقشة العلم CLONE_FS في clone(2).

KCMP_IO
    التحقق مما إذا كانت العمليتان تشاركان سياق الإدخال/الإخراج. يتم تجاهل الوسيطتين idx1 و idx2. انظر مناقشة العلم CLONE_IO في clone(2).

KCMP_SIGHAND
    التحقق مما إذا كانت العمليتان تشاركان نفس جدول ترتيبات الإشارات. يتم تجاهل الوسيطتين idx1 و idx2. انظر مناقشة العلم CLONE_SIGHAND في clone(2).

KCMP_SYSVSEM
    تحقق مما إذا كانت العمليات تشترك في نفس قائمة عمليات التراجع عن إشارات System يتم تجاهل الوسيطتين idx1 و idx2. انظر شرح العلامة CLONE_SYSVSEM في clone(2).

KCMP_VM
    التحقق مما إذا كانت العمليتان تشاركان نفس مساحة العنوان. يتم تجاهل الوسيطتين idx1 و idx2. انظر مناقشة العلم CLONE_VM في clone(2).

KCMP_EPOLL_TFD (منذ Linux 4.13)
    التحقق مما إذا كان واصف الملف idx1 للعملية pid1 موجودًا في مثيل epoll(7) الموصوف بواسطة idx2 للعملية pid2. الوسيطة idx2 هي مؤشر لبنية حيث يتم وصف الملف الهدف. هذه البنية لها الشكل:

    struct kcmp_epoll_slot {
        __u32 efd;
        __u32 tfd;
        __u64 toff;
    };

داخل هذه البنية، efd هو واصف ملف epoll مُعاد من epoll_create(2)، tfd هو رقم واصف ملف هدف، و toff هو إزاحة ملف هدف تُحسب من الصفر. يمكن تسجيل عدة أهداف مختلفة بنفس رقم واصف الملف، ويساعد تعيين إزاحة محددة في فحص كل منها.

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

قيمة الإرجاع
قيمة الإرجاع لاستدعاء ناجح لـ kcmp() هي ببساطة نتيجة المقارنة الحسابية لمؤشرات النواة (عندما تقارن النواة الموارد، تستخدم عناوين ذاكرتها).

أسهل طريقة للشرح هي النظر في مثال. افترض أن v1 و v2 هما عنوانا الموارد المناسبة، فإن قيمة الإرجاع تكون إحدى التالية:

    0   v1 يساوي v2؛ بمعنى آخر، تشارك العمليتان المورد.

    1   v1 أصغر من v2.

    2   v1 أكبر من v2.

    3   v1 لا يساوي v2، لكن معلومات الترتيب غير متوفرة.

عند الخطأ، تُعاد القيمة -1، ويُضبط errno للإشارة إلى الخطأ.

صُمم kcmp() لإرجاع قيم مناسبة للفرز. هذا مفيد بشكل خاص إذا احتاج المرء لمقارنة عدد كبير من واصفات الملفات.

الأخطاء

EBADF
    type هو KCMP_FILE و fd1 أو fd2 ليس واصف ملف مفتوح.

EFAULT
    فتحة epoll المُشار إليها بواسطة idx2 خارج نطاق عنوان المستخدم.

EINVAL
    type غير صالح.

ENOENT
    الملف الهدف غير موجود في مثيل epoll(7).

EPERM
    صلاحية غير كافية لفحص موارد العملية. القدرة CAP_SYS_PTRACE مطلوبة لفحص العمليات التي لا تملكها. قد تنطبق قيود ptrace أخرى أيضًا، مثل CONFIG_SECURITY_YAMA، والتي عندما تكون /proc/sys/kernel/yama/ptrace_scope مساوية لـ 2، تحد kcmp() من العمليات الفرعية؛ انظر ptrace(2).

ESRCH
    العملية pid1 أو pid2 غير موجودة.

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

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

قبل لينكس 5.12، تكون استدعاء النظام هذا متاحة فقط إذا كان النواة مُهيأة بـ CONFIG_CHECKPOINT_RESTORE، لأن الغرض الأصلي من استدعاء النظام كان لميزة نقطة التفتيش/الاستعادة في مساحة المستخدم (CRIU). (البديل لاستدعاء النظام هذا كان سيكون كشف معلومات العملية المناسبة عبر نظام ملفات proc(5)؛ اعتُبر هذا غير مناسب لأسباب أمنية.) منذ لينكس 5.12، تكون استدعاء النظام هذه متاحة أيضًا إذا كانت النواة مُهيأة بـ CONFIG_KCMP.

ملاحظات
انظر clone(2) للحصول على بعض المعلومات الأساسية حول الموارد المشتركة المُشار إليها في هذه الصفحة.

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

    $ ./a.out;
    Parent PID is 1144
    Parent opened file on FD 3

    PID of child of fork() is 1145
    	Compare duplicate FDs from different processes:
    		kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> same
    Child opened file on FD 4
    	Compare FDs from distinct open()s in same process:
    		kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> different
    Child duplicated FD 3 to create FD 5
    	Compare duplicated FDs in same process:
    		kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> same

  مصدر البرنامج
    #define _GNU_SOURCE
    #include <err.h>
    #include <fcntl.h>
    #include <linux/kcmp.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>

    static int
    kcmp(pid_t pid1, pid_t pid2, int type,
         unsigned long idx1, unsigned long idx2)
    {
        return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2);
    }

    static void
    test_kcmp(char *msg, pid_t pid1, pid_t pid2, int fd_a, int fd_b)
    {
        printf("\t%s\n", msg);
        printf("\t\tkcmp(%jd, %jd, KCMP_FILE, %d, %d) ==> %s\n",
               (intmax_t) pid1, (intmax_t) pid2, fd_a, fd_b,
               (kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ?
                            "same" : "different");
    }

    int
    main(void)
    {
        int                fd1, fd2, fd3;
        static const char  pathname[] = "/tmp/kcmp.test";

        fd1 = open(pathname, O_CREAT | O_RDWR, 0600);
        if (fd1 == -1)
            err(EXIT_FAILURE, "open");

        printf("Parent PID is %jd\n", (intmax_t) getpid());
        printf("Parent opened file on FD %d\n\n", fd1);

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

        case 0:
            printf("PID of child of fork() is %jd\n", (intmax_t) getpid());

            test_kcmp("Compare duplicate FDs from different processes:",
                      getpid(), getppid(), fd1, fd1);

            fd2 = open(pathname, O_CREAT | O_RDWR, 0600);
            if (fd2 == -1)
                err(EXIT_FAILURE, "open");
            printf("Child opened file on FD %d\n", fd2);

            test_kcmp("Compare FDs from distinct open()s in same process:",
                      getpid(), getpid(), fd1, fd2);

            fd3 = dup(fd1);
            if (fd3 == -1)
                err(EXIT_FAILURE, "dup");
            printf("Child duplicated FD %d to create FD %d\n", fd1, fd3);

            test_kcmp("Compare duplicated FDs in same process:",
                      getpid(), getpid(), fd1, fd3);
            break;

        default:
            wait(NULL);
        }

        exit(EXIT_SUCCESS);
    }

انظر أيضًا
clone(2), unshare(2)

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

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

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