pipe(2)

الاسم
pipe, pipe2 - إنشاء أنبوب

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

موجز
#include <unistd.h>

int pipe(int pipefd[2]);

#define _GNU_SOURCE             /* انظر feature_test_macros(7) */
#include <fcntl.h>              /* تعريف ثوابت O_* */
#include <unistd.h>

int pipe2(int pipefd[2], int flags);

/* في أنظمة Alpha وIA-64 وMIPS وSuperH وSPARC/SPARC64، يكون للوظيفة pipe() النموذج الأولي التالي؛ انظر VERSIONS */

#include <unistd.h>

struct fd_pair {
long fd[2];
};
struct fd_pair pipe(void);

الوصف
pipe() ينشئ أنبوبًا، قناة بيانات أحادية الاتجاه يمكن استخدامها للتواصل بين العمليات. المصفوفة pipefd تُستخدم لإرجاع واصفي ملف يشيران إلى طرفي الأنبوب. pipefd[0] يشير إلى طرف القراءة للأنبوب. pipefd[1] يشير إلى طرف الكتابة للأنبوب. البيانات المكتوبة في طرف الكتابة للأنبوب تُخزن مؤقتًا بواسطة النواة حتى تُقرأ من طرف القراءة للأنبوب. لمزيد من التفاصيل، انظر pipe(7).

إذا كانت flags تساوي 0، فإن pipe2() مماثلة لـ pipe(). يمكن إجراء عملية OR على البتات للقيم التالية في flags للحصول على سلوك مختلف:

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

O_DIRECT (منذ Linux 3.4)
    أنشئ أنبوبًا يؤدي الإدخال/الإخراج في وضع "الحزمة". كل write(2) إلى الأنبوب يُعالج كحزمة منفصلة، وقراءات read(2) من الأنبوب ستقرأ حزمة واحدة في كل مرة. لاحظ النقاط التالية:

    •   الكتابات التي تزيد عن PIPE_BUF بايت (انظر pipe(7)) ستُقسم إلى حزم متعددة. الثابت PIPE_BUF مُعرف في <limits.h>.

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

    •   الحزم ذات الطول الصفري غير مدعومة. (read(2) التي تحدد حجم مخزن مؤقت صفري هي عملية لا تفعل شيئًا، وتُرجع 0.)

    النوى الأقدم التي لا تدعم هذا العلم ستشير إلى ذلك عبر خطأ EINVAL.

    منذ Linux 4.5، من الممكن تغيير إعداد O_DIRECT لواصف ملف أنبوب باستخدام fcntl(2).

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

O_NOTIFICATION_PIPE
    منذ Linux 5.8، آلية الإشعار العامة مبنية فوق الأنبوب حيث تقوم النواة بوصل رسائل الإشعار في الأنابيب المفتوحة بواسطة مساحة المستخدم. يجب على مالك الأنبوب إخبار النواة بمصادر الأحداث التي يجب مراقبتها، ويمكن أيضًا تطبيق مرشحات لاختيار الأحداث الفرعية التي يجب وضعها في الأنبوب.

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

على Linux (وأنظمة أخرى)، pipe() لا تُعدل pipefd عند الفشل. تمت إضافة متطلب لتوحيد هذا السلوك في POSIX.1-2008 TC2. استدعاء النظام الخاص بـ Linux pipe2() بالمثل لا يُعدل pipefd عند الفشل.

الأخطاء

EFAULT
    pipefd غير صالح.

EINVAL
    (pipe2()) قيمة غير صالحة في flags.

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

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

ENFILE
    تم الوصول إلى الحد الصعب للمستخدم على الذاكرة التي يمكن تخصيصها للأنابيب والمتصل ليس له صلاحية؛ انظر pipe(7).

ENOPKG
    (pipe2()) تم تمرير O_NOTIFICATION_PIPE في flags ودعم الإشعارات (CONFIG_WATCH_QUEUE) غير مُجمّع في النواة.

الإصدارات
واجهة System V ABI على بعض البنى تسمح باستخدام أكثر من مسجل لإرجاع قيم متعددة؛ عدة بنى (وهي Alpha وIA-64 وMIPS وSuperH وSPARC/SPARC64) (تساء) استخدام هذه الميزة لتنفيذ استدعاء النظام pipe() بطريقة وظيفية: الاستدعاء لا يأخذ أي وسيطات ويُرجع زوجًا من واصفي الملف كقيمة إرجاع عند النجاح. دالة الغلاف glibc pipe() تتعامل مع هذا بشفافية. انظر syscall(2) للحصول على معلومات حول المسجلات المستخدمة لتخزين واصف الملف الثاني.

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

التاريخ

pipe()
    POSIX.1-2001.

pipe2()
    POSIX.1-2024. Linux 2.6.27, glibc 2.9.

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

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

    int
    main(int argc, char *argv[])
    {
        int    pipefd[2];
        char   buf;
        pid_t  cpid;

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

        if (pipe(pipefd) == -1)
            err(EXIT_FAILURE, "pipe");

        cpid = fork();
        if (cpid == -1)
            err(EXIT_FAILURE, "fork");

        if (cpid == 0) {    /* Child reads from pipe */
            if (close(pipefd[1]) == -1)  /* Close unused write end */
                err(EXIT_FAILURE, "close");

            while (read(pipefd[0], &buf, 1) > 0) {
                if (write(STDOUT_FILENO, &buf, 1) != 1)
                    err(EXIT_FAILURE, "write");
            }

            if (write(STDOUT_FILENO, "\n", 1) != 1)
                err(EXIT_FAILURE, "write");
            if (close(pipefd[0]) == -1)
                err(EXIT_FAILURE, "close");
            _exit(EXIT_SUCCESS);

        } else {            /* Parent writes argv[1] to pipe */
            if (close(pipefd[0]) == -1)  /* Close unused read end */
                err(EXIT_FAILURE, "close");
            if (write(pipefd[1], argv[1], strlen(argv[1])) != strlen(argv[1]))
                err(EXIT_FAILURE, "write");
            if (close(pipefd[1]) == -1)  /* Reader will see EOF */
                err(EXIT_FAILURE, "close");
            if (wait(NULL) == -1)        /* Wait for child */
                err(EXIT_FAILURE, "wait");
            exit(EXIT_SUCCESS);
        }
    }

انظر أيضًا
fork(2), read(2), socketpair(2), splice(2), tee(2), vmsplice(2), write(2), popen(3), pipe(7)

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

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

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