pipe(7)

الاسم
pipe - نظرة عامة على الأنابيب و FIFOs

الوصف
توفر الأنابيب و FIFOs (المعروفة أيضًا بالأنابيب المسماة) قناة اتصال أحادية الاتجاه بين العمليات. للأنبوب نهاية قراءة و نهاية كتابة. يمكن قراءة البيانات المكتوبة في نهاية الكتابة للأنبوب من نهاية القراءة للأنبوب.

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

FIFO (اختصار لـ First In First Out) له اسم داخل نظام الملفات (يُصنع باستخدام mkfifo(3))، ويُفتح باستخدام open(2). يمكن لأي عملية فتح FIFO، بافتراض أن أذونات الملف تسمح بذلك. تُفتح نهاية القراءة باستخدام العلم O_RDONLY؛ تُفتح نهاية الكتابة باستخدام العلم O_WRONLY. انظر fifo(7) لمزيد من التفاصيل. ملاحظة: على الرغم من أن FIFOs لها اسم مسار في نظام الملفات، فإن الإدخال/الإخراج على FIFOs لا يتضمن عمليات على الجهاز الأساسي (إن وجد).

  الإدخال/الإخراج على الأنابيب و FIFOs
الفرق الوحيد بين الأنابيب و FIFOs هو الطريقة التي تُصنع وتُفتح بها. بمجرد إنجاز هذه المهام، يكون للإدخال/الإخراج على الأنابيب و FIFOs نفس الدلالات تمامًا.

إذا حاولت عملية القراءة من أنبوب فارغ، فإن read(2) سينتظر حتى تتوفر البيانات. إذا حاولت عملية الكتابة إلى أنبوب ممتلئ (انظر أدناه)، فإن write(2) ينتظر حتى تُقرأ بيانات كافية من الأنبوب للسماح بإتمام الكتابة.

الإدخال/الإخراج غير المحظور ممكن باستخدام عملية fcntl(2) F_SETFL لتمكين علم حالة الملف المفتوح O_NONBLOCK أو بفتح fifo(7) مع O_NONBLOCK. إذا كانت أي عملية قد فتحت الأنبوب للكتابة، تفشل القراءات مع EAGAIN؛ وإلا—بدون كتاب محتملين—تنجح القراءات وتعيد فارغة.

قناة الاتصال التي يوفرها الأنبوب هي تيار بايت: لا يوجد مفهوم لحدود الرسائل.

إذا أغلقت جميع واصفات الملف التي تشير إلى نهاية الكتابة لأنبوب، فإن محاولة read(2) من الأنبوب سترى نهاية الملف (سيعيد read(2) 0). إذا أغلقت جميع واصفات الملف التي تشير إلى نهاية القراءة لأنبوب، فإن write(2) سيسبب توليد إشارة SIGPIPE للعملية المستدعية. إذا كانت العملية المستدعية تتجاهل هذه الإشارة، فإن write(2) يفشل مع الخطأ EPIPE. يجب على تطبيق يستخدم pipe(2) و fork(2) استخدام استدعاءات close(2) مناسبة لإغلاق واصفات الملف المكررة غير الضرورية؛ يضمن هذا تسليم نهاية الملف و SIGPIPE/EPIPE عند الاقتضاء.

لا يمكن تطبيق lseek(2) على أنبوب.

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

قبل Linux 2.6.11، كانت سعة الأنبوب مماثلة لحجم صفحة النظام (مثل 4096 بايت على i386). منذ Linux 2.6.11، سعة الأنبوب هي 16 صفحة (أي 65,536 بايت في نظام بحجم صفحة 4096 بايت). منذ Linux 2.6.35، السعة المبدئية للأنبوب هي 16 صفحة، ولكن يمكن الاستعلام عن السعة وضبطها باستخدام عمليات fcntl(2) F_GETPIPE_SZ و F_SETPIPE_SZ. انظر fcntl(2) لمزيد من المعلومات. منذ Linux 4.5، السعة المبدئية للأنبوب أقل من 16 صفحة عندما يتجاوز حد pipe-user-pages-soft.

عملية ioctl(2) التالية، التي يمكن تطبيقها على واصف ملف يشير إلى أي من طرفي الأنبوب، تضع عدد البايتات غير المقروءة في الأنبوب في المخزن المؤقت int المشار إليه بالوسيطة الأخيرة للاستدعاء:

    ioctl(fd, FIONREAD, &nbytes);

عملية FIONREAD غير محددة في أي معيار، ولكنها متوفرة في العديد من التطبيقات.

  ملفات /proc
على Linux، تتحكم الملفات التالية في مقدار الذاكرة التي يمكن استخدامها للأنابيب:

/proc/sys/fs/pipe-max-pages (فقط في Linux 2.6.34)
    حد أعلى، بالصفحات، على السعة التي يمكن لمستخدم غير مميز (بدون قدرة CAP_SYS_RESOURCE) ضبطها لأنبوب.

    القيمة المبدئية لهذا الحد هي 16 ضعف السعة المبدئية للأنبوب (انظر أعلاه)؛ الحد الأدنى هو صفحتان.

    أزيلت هذه الواجهة في Linux 2.6.35، لصالح /proc/sys/fs/pipe-max-size.

/proc/sys/fs/pipe-max-size (منذ لينكس 2.6.35)
    الحجم الأقصى (بالبايت) للأنابيب الفردية التي يمكن للمستخدمين ضبطها بدون قدرة CAP_SYS_RESOURCE. قد تُقرَّب القيمة المخصصة لهذا الملف لأعلى، لتعكس القيمة المستخدمة فعليًا لتطبيق مناسب. لتحديد القيمة المقربة لأعلى، اعرض محتويات هذا الملف بعد تخصيص قيمة له.

    القيمة المبدئية لهذا الملف هي 1048576 (1 ميبايت). القيمة الدنيا التي يمكن تخصيصها لهذا الملف هي حجم صفحة النظام. تؤدي محاولات ضبط حد أقل من حجم الصفحة إلى فشل write(2) مع الخطأ EINVAL.

    منذ Linux 4.9، تعمل القيمة في هذا الملف أيضًا كسقف للسعة المبدئية لأنبوب جديد أو FIFO مفتوح حديثًا.

/proc/sys/fs/pipe-user-pages-hard (منذ لينكس 4.5)
    الحد الصارم على الحجم الإجمالي (بالصفحات) لجميع الأنابيب المنشأة أو المحددة بواسطة مستخدم واحد غير مميز (أي، شخص لا يملك صلاحية CAP_SYS_RESOURCE ولا صلاحية CAP_SYS_ADMIN). طالما أن العدد الإجمالي للصفحات المخصصة لمخازن الأنابيب لهذا المستخدم يصل إلى هذا الحد، سيُرفض إنشاء أنابيب جديدة، وسيُرفض زيادة سعة الأنبوب.

    عندما تكون قيمة هذا الحد صفرًا (وهو المبدئي)، لا يُطبق أي حد صارم.

/proc/sys/fs/pipe-user-pages-soft (منذ لينكس 4.5)
    الحد المرن على الحجم الإجمالي (بالصفحات) لجميع الأنابيب المنشأة أو المحددة بواسطة مستخدم واحد غير مميز (أي، شخص لا يملك صلاحية CAP_SYS_RESOURCE ولا صلاحية CAP_SYS_ADMIN). طالما أن العدد الإجمالي للصفحات المخصصة لمخازن الأنابيب لهذا المستخدم يصل إلى هذا الحد، ستُحدد الأنابيب الفردية المنشأة بواسطة المستخدم بصفحتين (صفحة واحدة قبل لينكس 5.14)، وسيُرفض زيادة سعة الأنبوب.

    عندما تكون قيمة هذا الحد صفرًا، لا يُطبق أي حد مرن. القيمة المبدئية لهذا الملف هي 16384، مما يسمح بإنشاء ما يصل إلى 1024 أنبوبًا بالسعة المبدئية.

قبل لينكس 4.9، أثرت بعض الأخطاء على معالجة الحدين pipe-user-pages-soft و pipe-user-pages-hard؛ انظر BUGS.

  PIPE_BUF
ينص POSIX.1 على أن عمليات الكتابة الأقل من PIPE_BUF بايت يجب أن تكون ذرية: تُكتب بيانات الإخراج إلى الأنبوب كتسلسل متصل. قد تكون عمليات الكتابة الأكبر من PIPE_BUF بايت غير ذرية: قد تخلط النواة البيانات مع البيانات المكتوبة بواسطة عمليات أخرى. يتطلب POSIX.1 أن يكون PIPE_BUF على الأقل 512 بايت. (على لينكس، PIPE_BUF هو 4096 بايت.) تعتمد الدلالات الدقيقة على ما إذا كان واصف الملف غير محظور (O_NONBLOCK)، وما إذا كان هناك عدة كتّاب للأنبوب، وعلى n، عدد البايتات المراد كتابتها:

O_NONBLOCK معطل، n <= PIPE_BUF
    تُكتب جميع بايتات n بشكل ذري؛ قد يحجب write(2) إذا لم تكن هناك مساحة كافية لكتابة n بايت فورًا

O_NONBLOCK مفعل، n <= PIPE_BUF
    إذا كانت هناك مساحة لكتابة n بايت إلى الأنبوب، فإن write(2) ينجح فورًا، كاتبًا جميع بايتات n؛ وإلا يفشل write(2)، مع تعيين errno إلى EAGAIN.

O_NONBLOCK معطل، n > PIPE_BUF
    الكتابة غير ذرية: قد تُخلط البيانات المعطاة لـ write(2) مع عمليات write(2) بواسطة عمليات أخرى؛ يحجب write(2) حتى تُكتب n بايت.

O_NONBLOCK مفعل، n > PIPE_BUF
    إذا كان الأنبوب ممتلئًا، فإن write(2) يفشل، مع تعيين errno إلى EAGAIN. وإلا، قد تُكتب من 1 إلى n بايت (أي، قد تحدث "كتابة جزئية"؛ يجب على المستدعي التحقق من القيمة المعادة من write(2) لمعرفة عدد البايتات التي كُتبت فعليًا)، وقد تُخلط هذه البايتات مع كتابات بواسطة عمليات أخرى.

  أعلام حالة الملف المفتوح
أعلام حالة الملف المفتوح الوحيدة التي يمكن تطبيقها بشكل ذي معنى على أنبوب أو FIFO هي O_NONBLOCK و O_ASYNC.

تعيين علم O_ASYNC لنهاية القراءة لأنبوب يتسبب في توليد إشارة (SIGIO مبدئيًا) عندما يصبح إدخال جديد متاحًا على الأنبوب. يجب تعيين الهدف لتسليم الإشارات باستخدام أمر fcntl(2) F_SETOWN. على لينكس، يُدعم O_ASYNC للأنابيب و FIFOs فقط منذ لينكس 2.6.

  ملاحظات حول قابلية النقل
على بعض الأنظمة (ولكن ليس لينكس)، الأنابيب ثنائية الاتجاه: يمكن نقل البيانات في كلا الاتجاهين بين نهايتي الأنبوب. يتطلب POSIX.1 أنابيب أحادية الاتجاه فقط. يجب على التطبيقات المحمولة تجنب الاعتماد على دلالات الأنابيب ثنائية الاتجاه.

  العلل
قبل لينكس 4.9، أثرت بعض الأخطاء على معالجة الحدين pipe-user-pages-soft و pipe-user-pages-hard عند استخدام عملية fcntl(2) F_SETPIPE_SZ لتغيير سعة الأنبوب:

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

    بدءًا من لينكس 4.9، يتضمن فحص الحد الذاكرة المطلوبة لسعة الأنبوب الجديدة.

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

    بدءًا من لينكس 4.9، تُجرى فحوصات ضد الحدود فقط عند زيادة سعة الأنبوب؛ يمكن للمستخدم غير المميز دائمًا تقليل سعة الأنبوب.

(ج) كانت المحاسبة والفحص ضد الحدود تُجرى على النحو التالي:

    (1) اختبار ما إذا كان المستخدم قد تجاوز الحد.
    (2) إجراء تخصيص وسادة الأنبوب الجديدة.
    (3) احتساب التخصيص الجديد مقابل الحدود.

    كان هذا سباقيًا. يمكن لعمليات متعددة اجتياز النقطة (1) في وقت واحد، ثم تخصيص وسائد أنبوب تم احتسابها فقط في الخطوة (3)، مما يؤدي إلى تجاوز تخصيص وسادة الأنبوب للمستخدم للحد.

    بدءًا من لينكس 4.9، تُنفّذ خطوة الاحتساب قبل إجراء التخصيص، وتفشل العملية إذا تجاوز الحد.

قبل لينكس 4.9، قد تحدث أخطاء مشابهة للنقطتين (أ) و(ج) أيضًا عندما يخصص النواة ذاكرة لوسادة أنبوب جديدة؛ أي عند استدعاء pipe(2) وعند فتح FIFO لم يُفتح سابقًا.

انظر أيضًا
mkfifo(1), dup(2), fcntl(2), open(2), pipe(2), poll(2), select(2), socketpair(2), splice(2), stat(2), tee(2), vmsplice(2), mkfifo(3), epoll(7), fifo(7)

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

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

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