write(2)

الاسم
write - الكتابة إلى واصف ملف

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

موجز
#include <unistd.h>

ssize_t write(size_t count;
              int fd, const void buf[count], size_t count);

الوصف
تكتب write() حتى count بايت من المخزن المؤقت الذي يبدأ عند buf إلى الملف المشار إليه بواصف الملف fd.

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

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

تتطلب POSIX أن read(2) التي يمكن إثبات حدوثها بعد عودة write() ستعيد البيانات الجديدة. لاحظ أن ليست جميع أنظمة الملفات متوافقة مع POSIX.

وفقًا لـ POSIX.1، إذا كانت count أكبر من SSIZE_MAX، فإن النتيجة تكون محددة بواسطة التنفيذ؛ انظر «ملاحظات» للحد الأقصى في لينكس.

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

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

إذا كان count صفرًا ويشير fd إلى ملف عادي، فقد تُرجع write() حالة فشل إذا تم اكتشاف أحد الأخطاء أدناه. إذا لم يتم اكتشاف أخطاء، أو لم يتم إجراء اكتشاف الأخطاء، يُعاد 0 دون أي تأثير آخر. إذا كان count صفرًا ويشير fd إلى ملف غير عادي، فالنتائج غير محددة.

الأخطاء

EAGAIN
    يشير واصف الملف fd إلى ملف غير مقبس وتم وضع علامة عدم الحظر عليه (O_NONBLOCK)، وستحظر الكتابة. انظر open(2) لمزيد من التفاصيل حول العلم O_NONBLOCK.

EAGAIN أو EWOULDBLOCK
    يشير واصف الملف fd إلى مقبس وتم وضع علامة عدم الحظر عليه (O_NONBLOCK)، وستحظر الكتابة. تسمح POSIX.1-2001 بإعادة أي من الخطأين لهذه الحالة، ولا تتطلب أن تكون هذه الثوابت بنفس القيمة، لذا يجب على التطبيق المحمول التحقق من كلا الاحتمالين.

EBADF
    fd ليس واصف ملف صالحًا أو ليس مفتوحًا للكتابة.

EDESTADDRREQ
    يشير fd إلى مقبس بيانات مخطط لم يتم تعيين عنوان نظير له باستخدام connect(2).

EDQUOT
    تم استنفاد حصة المستخدم من كتل القرص على نظام الملفات الذي يحتوي على الملف المشار إليه بواسطة fd.

EFAULT
    buf خارج مساحة العنوان التي يمكنك الوصول إليها.

EFBIG
    تمت محاولة كتابة ملف يتجاوز الحد الأقصى لحجم الملف المحدد بالتنفيذ أو حد حجم ملف العملية، أو الكتابة في موضع يتجاوز الحد الأقصى المسموح به للإزاحة.

EINTR
    تمت مقاطعة الاستدعاء بواسطة إشارة قبل كتابة أي بيانات؛ انظر signal(7).

EINVAL
    fd مرتبط بكائن غير مناسب للكتابة؛ أو تم فتح الملف بالعلم O_DIRECT، وإما العنوان المحدد في buf، أو القيمة المحددة في count، أو إزاحة الملف غير محاذية بشكل مناسب.

EIO حدث خطأ إدخال/إخراج منخفض المستوى أثناء تعديل inode. قد يتعلق هذا الخطأ بإعادة كتابة البيانات التي كتبتها write() سابقة، والتي قد تكون صدرت لواصف ملف مختلف على نفس الملف. منذ Linux 4.13، تأتي أخطاء إعادة الكتابة مع وعد بأنها قد تُبلغ بواسطة طلبات write() لاحقة، وستُبلغ بواسطة fsync(2) لاحقة (سواء تم الإبلاغ عنها أيضًا بواسطة write() أم لا). سبب بديل لـ EIO على أنظمة الملفات الشبكية هو عندما تم أخذ قفل استشاري على واصف الملف وتم فقدان هذا القفل. انظر قسم الأقفال المفقودة من fcntl(2) لمزيد من التفاصيل.

ENOSPC
    الجهاز الذي يحتوي على الملف المشار إليه بواسطة fd ليس لديه مساحة للبيانات.

EPERM
    مُنعت العملية بواسطة ختم ملف؛ انظر fcntl(2).

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

قد تحدث أخطاء أخرى، اعتمادًا على الكائن المتصل بـ fd.

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

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

تحت SVr4، قد تتم مقاطعة كتابة وتُعيد EINTR في أي نقطة، وليس فقط قبل كتابة أي بيانات.

ملاحظات
العودة الناجحة من write() لا تضمن إيداع البيانات على القرص. على بعض أنظمة الملفات، بما في ذلك NFS، لا تضمن حتى حجز المساحة بنجاح للبيانات. في هذه الحالة، قد تتأخر بعض الأخطاء حتى write() مستقبلية، أو fsync(2)، أو حتى close(2). الطريقة الوحيدة للتأكد هي استدعاء fsync(2) بعد الانتهاء من كتابة جميع بياناتك.

إذا تمت مقاطعة write() بواسطة معالج إشارة قبل كتابة أي بايتات، يفشل الاستدعاء بالخطأ EINTR؛ إذا تمت مقاطعته بعد كتابة بايت واحد على الأقل، ينجح الاستدعاء، ويعيد عدد البايتات المكتوبة.

على Linux، ستنقل write() (واستدعاءات النظام المماثلة) على الأكثر 0x7ffff000 (2,147,479,552) بايت، مع إعادة عدد البايتات المنقولة فعليًا. (هذا صحيح على كل من الأنظمة 32-bit و 64-bit.)

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

العلل
وفقًا لـ POSIX.1-2008/SUSv4 القسم XSI 2.9.7 («تفاعلات الخيوط مع عمليات الملفات العادية»):

    يجب أن تكون جميع الوظائف التالية ذرية (atomic) بالنسبة لبعضها البعض في التأثيرات المحددة في POSIX.1-2008 عندما تعمل على ملفات عادية أو روابط رمزية: ...

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

انظر أيضًا
close(2), fcntl(2), fsync(2), ioctl(2), lseek(2), open(2), pwrite(2), read(2), select(2), writev(2), fwrite(3)

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

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

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