dup(2)

الاسم
dup, dup2, dup3 - نسخ واصف ملف

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

موجز
#include <unistd.h>

int dup(int oldfd);
int dup2(int oldfd, int newfd);

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

int dup3(int oldfd, int newfd, int flags);

الوصف
نداء النظام dup() يخصص واصف ملف جديد يشير إلى نفس وصف الملف المفتوح مثل الواصف oldfd. (لشرح وصف الملف المفتوح، انظر open(2).) رقم واصف الملف الجديد مضمون ليكون أقل واصف ملف مرقم غير مستخدم في العملية المستدعية.

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

واصفا الملف لا يشاركان أعلام واصف الملف (علم الإغلاق عند التنفيذ). علم الإغلاق عند التنفيذ (FD_CLOEXEC؛ انظر fcntl(2)) للواصف المكرر يكون مغلقًا.

  dup2()
نداء النظام dup2() يؤدي نفس مهمة dup()، ولكن بدلاً من استخدام أقل واصف ملف غير مستخدم مرقم، فإنه يستخدم رقم واصف الملف المحدد في newfd. بمعنى آخر، يتم ضبط واصف الملف newfd بحيث يشير الآن إلى نفس وصف الملف المفتوح مثل oldfd.

إذا كان واصف الملف newfd مفتوحًا سابقًا، فإنه يُغلق قبل إعادة استخدامه؛ يتم الإغلاق بصمت (أي، أي أخطاء أثناء الإغلاق لا تُبلغ عنها dup2()).

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

لاحظ النقاط التالية:

•   إذا كان oldfd ليس واصف ملف صالحًا، فإن النداء يفشل، ولا يُغلق newfd.

•   إذا كان oldfd واصف ملف صالحًا، وكان newfd له نفس قيمة oldfd، فإن dup2() لا يفعل شيئًا، ويعيد newfd.

  dup3()
dup3() هو نفسه dup2()، باستثناء أن:

•   يمكن للمستدعي فرض تعيين علم الإغلاق عند التنفيذ لواصف الملف الجديد بتحديد O_CLOEXEC في flags. انظر وصف نفس العلم في open(2) لأسباب قد تكون مفيدة.

•   إذا كان oldfd يساوي newfd، فإن dup3() يفشل مع الخطأ EINVAL.

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

الأخطاء

EBADF
    oldfd ليس واصف ملف مفتوح.

EBADF
    newfd خارج النطاق المسموح لواصفات الملف (انظر مناقشة RLIMIT_NOFILE في getrlimit(2)).

EBUSY
    (لينكس فقط) قد يُعاد هذا بواسطة dup2() أو dup3() أثناء حالة سباق مع open(2) و dup().

EINTR
    نداء dup2() أو dup3() قُطع بواسطة إشارة؛ انظر signal(7).

EINVAL
    (dup3()) flags يحتوي على قيمة غير صالحة.

EINVAL
    (dup3()) oldfd كان مساويًا لـ newfd.

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

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

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

التاريخ

dup()
dup2()
    4.3BSD، SVr4، POSIX.1-1988.

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

ملاحظات
الخطأ الذي تعيده dup2() يختلف عن ذلك الذي تعيده fcntl(..., F_DUPFD, ...) عندما يكون newfd خارج النطاق. على بعض الأنظمة، dup2() أيضًا يعيد أحيانًا EINVAL مثل F_DUPFD.

إذا كان newfd مفتوحًا، فإن أي أخطاء كان سيُبلغ عنها في وقت close(2) تُفقد. إذا كان هذا مقلقًا، فإن—ما لم يكن البرنامج أحادي الخيط ولا يخصص واصفات ملف في معالجات الإشارات—النهج الصحيح هو عدم إغلاق newfd قبل استدعاء dup2()، بسبب حالة السباق الموصوفة أعلاه. بدلاً من ذلك، يمكن استخدام كود مثل التالي:

    /* Obtain a duplicate of 'newfd' that can subsequently
       be used to check for close() errors; an EBADF error
       means that 'newfd' was not open.  */

    tmpfd = dup(newfd);
    if (tmpfd == -1 && errno != EBADF) {
        /* Handle unexpected dup() error.  */
    }

    /* Atomically duplicate 'oldfd' on 'newfd'.  */

    if (dup2(oldfd, newfd) == -1) {
        /* Handle dup2() error.  */
    }

    /* Now check for close() errors on the file originally
       referred to by 'newfd'.  */

    if (tmpfd != -1) {
        if (close(tmpfd) == -1) {
            /* Handle errors from close.  */
        }
    }

انظر أيضًا
close(2), fcntl(2), open(2), pidfd_getfd(2)

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

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

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