close(2)

الاسم
close - إغلاق واصف ملف

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

موجز
#include <unistd.h>

int close(int fd);

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

إذا كان fd هو آخر واصف ملف يشير إلى وصف الملف المفتوح الأساسي (انظر open(2))، فتُحرر الموارد المرتبطة بوصف الملف المفتوح؛ إذا كان واصف الملف هو المرجع الأخير لملف أُزيل باستخدام unlink(2)، فسيُحذف الملف.

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

الأخطاء

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

EINTR
    قوطعت استدعاء close() بإشارة؛ انظر signal(7).

EIO حدث خطأ إدخال/إخراج.

ENOSPC
EDQUOT
    في NFS، لا تُبلغ هذه الأخطاء عادةً ضد أول كتابة تتجاوز مساحة التخزين المتاحة، بل ضد write(2) أو fsync(2) أو close() لاحقة.

انظر الملاحظات لمناقشة لماذا لا ينبغي إعادة محاولة close() بعد خطأ.

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

التاريخ
4.3BSD، SVr4، POSIX.1-1988.

ملاحظات
يمكن استخدام علم واصف الملف close-on-exec لضمان إغلاق واصف الملف آليًا عند نجاح execve(2)؛ انظر fcntl(2) للتفاصيل.

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

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

علاوة على ذلك، اعتبر السيناريو التالي حيث يؤدي خيطان عمليات على نفس واصف الملف:

(1) خيط واحد محظور في استدعاء نظام إدخال/إخراج على واصف الملف. على سبيل المثال، يحاول write(2) إلى أنبوب ممتلئ بالفعل، أو يحاول read(2) من مقبس دفق لا يحتوي حاليًا على بيانات متاحة.

(2) يغلق خيط آخر واصف الملف.

يختلف السلوك في هذه الحالة عبر الأنظمة. في بعض الأنظمة، عند إغلاق واصف الملف، يعود استدعاء النظام المحظور فورًا بخطأ.

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

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

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

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

تغلق العديد من التطبيقات الأخرى بالمثل واصف الملف دائمًا (باستثناء حالة EBADF، مما يعني أن واصف الملف كان غير صالح) حتى لو أبلغت لاحقًا عن خطأ عند العودة من close(). كان POSIX.1-2008 صامتًا بشأن هذه النقطة.

يمكن للمبرمج الحذر الذي يريد معرفة أخطاء الإدخال/الإخراج أن يسبق close() باستدعاء fsync(2).

خطأ EINTR هو حالة خاصة إلى حد ما. بخصوص خطأ EINTR، قال POSIX.1-2008:

    إذا قوطعت close() بإشارة سيتم التقاطها، فيجب أن تُرجع -1 مع ضبط errno على EINTR وحالة fd غير محددة.

يسمح هذا بالسلوك الذي يحدث في لينكس والعديد من التطبيقات الأخرى، حيث، كما هو الحال مع الأخطاء الأخرى التي قد تُبلغ عنها close()، يُضمن إغلاق واصف الملف. ومع ذلك، يسمح أيضًا بإمكانية أخرى: أن يُرجع التطبيق خطأ EINTR ويبقي واصف الملف مفتوحًا. (وفقًا لوثائقه، يفعل close() في HP-UX هذا.) يجب على المستدعي بعد ذلك استخدام close() مرة أخرى لإغلاق واصف الملف، لتجنب تسرب واصفات الملفات. يوفر هذا الاختلاف في سلوكيات التطبيق عقبة صعبة للتطبيقات المحمولة، لأنه في العديد من التطبيقات، لا يجب استدعاء close() مرة أخرى بعد خطأ EINTR، وفي تطبيق واحد على الأقل، يجب استدعاء close() مرة أخرى.

وحد POSIX.1-2024 سلوك HP-UX، مما جعل لينكس والعديد من التطبيقات الأخرى غير متوافقة. لا توجد خطط لتغيير السلوك في لينكس.

انظر أيضًا
close_range(2), fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)

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

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

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