سؤال

اعتقدت fsync() يفعل fflush() داخليا ، لذلك باستخدام fsync() على دفق على ما يرام. لكنني أحصل على نتيجة غير متوقعة عند تنفيذها بموجب الشبكة I/O.

مقتطف الرمز الخاص بي:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);
...
...
fputs(buf.c_str(), fp);
/* get fd of the FILE pointer */
fd = fileno(fp);
#ifndef WIN32
ret = fsync(fd);
#else
ret = _commit(fd);
fclose(fp);

لكن يبدو _commit() لا يتم مسح البيانات (حاولت على Windows وتم كتابة البيانات على نظام الملفات المصدر Linux).

عندما غيرت الكود ليكون:

FILE* fp = fopen(file, "wb");
/* multiple fputs() calls like: */
fputs(buf, fp);   
...   
...
fputs(buf.c_str(), fp);
/* fflush the data */
fflush(fp);
fclose(fp);

يطرد البيانات.

أنا أتساءل إذا _commit() يفعل نفس الشيء مثل fflush(). أي مدخلات؟

هل كانت مفيدة؟

المحلول

fflush() يعمل على FILE*, ، إنه يمسح المخازن المؤقتة الداخلية في FILE* من طلبك إلى نظام التشغيل.

fsync يعمل على مستوى أقل ، ويخبر نظام التشغيل بتطهير المخازن المؤقتة إلى الوسائط المادية.

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

علاوة على ذلك ، تعمل FSYNC/Commice على واصف ملف. ليس لديها معرفة بـ FILE* ولا يمكنها مسح المخازن المؤقتة. FILE* يعيش في تطبيقك ، واصفات الملفات تعيش في kernel OS ، عادة.

نصائح أخرى

وظيفة C القياسية fflush() ودعوة نظام Posix fsync() من الناحية النظرية إلى حد ما. fflush() تعمل على تدفقات ملفات C (FILE الكائنات) ، وبالتالي فهي محمولة.fsync() تعمل على واصفات ملف Posix. كلاهما يسبب إرسال البيانات المخزنة إلى وجهة.

على نظام posix ، كل دفق ملف C لديه واصف ملف مرتبط, ، وسيتم تنفيذ جميع العمليات على دفق ملف C عن طريق تفويض ، عند الضرورة ، إلى مكالمات نظام Posix التي تعمل على واصف الملف.

قد يعتقد المرء أن دعوة إلى fflush على نظام posix سوف يسبب أ write من أي بيانات في المخزن المؤقت لتيار الملف ، تليها مكالمة fsync() لوصف الملف من دفق الملف. لذلك على نظام posix لن تكون هناك حاجة لمتابعة مكالمة إلى fflush مع دعوة إلى fsync(fileno(fp)). ولكن هل هذا هو الحال: هل هناك دعوة إلى fsync من عند fflush?

لا ، الدعوة fflush على نظام posix لا يعني ذلك fsync وسوف يطلق.

معيار C fflush يقول (تم التركيز) عليه

يسبب أي بيانات غير مكتوبة لـ [الدفق] الذي سيتم تسليمه إلى بيئة المضيف أن تكون مكتوبة إلى الملف

قائلا أن البيانات ان نكون مكتوب ، بدلاً من ذلك هو مكتوبة تعني أنه يسمح بزيادة التخزين المؤقت من قبل البيئة المضيفة. يمكن أن يشمل هذا التخزين المؤقت من قبل "البيئة المضيفة" ، لبيئة Posix ، التخزين المؤقت الداخلي لذلك fsync تدفق. لذلك تشير القراءة الوثيقة لمعيار C إلى أن المعيار لا يتطلب تنفيذ POSIX للاتصال fsync.

ال الوصف القياسي لـ POSIX لـ fflush لا يعلن ، ك تمديد دلالات C, ، الذي - التي fsync يسمى.

أستطيع أن أقول ذلك من أجل البساطة:

استعمال fsync() مع عدم دفق الملفات (واصفات ملفات عدد صحيح)

استعمال fflush() مع تدفقات الملفات.

كما هنا هي مساعدة الرجل:

int fflush(FILE *stream); // flush a stream, FILE* type

int fsync(int fd); // synchronize a file's in-core state with storage device
                    // int type

fflush() و fsync() يمكن استخدامه لمحاولة التأكد من كتابة البيانات إلى وسائط التخزين (ولكن لا يكون ذلك ممكنًا دائمًا):

  1. اول استخدام fflush(fp) على دفق الإخراج (fp كونه FILE * تم الحصول عليها من fopen أو أحد الجداول القياسية stdout أو stderr) لكتابة محتويات المخزن المؤقت المرتبط بالدفق إلى نظام التشغيل.
  2. ثم استخدام fsync(fileno(fp)) لإخبار نظام التشغيل لكتابة المخازن المؤقتة الخاصة به إلى وسائط التخزين.

لاحظ ذلك fileno() و fsync() هل وظائف posix التي قد لا تكون متوفرة على جميع الأنظمة ، لا سيما أنظمة Microsoft Legacy حيث يمكن تسمية البدائل _fileno(), _fsync() أو _commit()...

لفرض التزام التغييرات الحديثة على القرص ، استخدم وظائف Sync () أو FSYNC ().

FSYNC () سيقوم بمزامنة جميع بيانات الملف وبيانات البيانات المعينة مع جهاز التخزين الدائم. يجب أن يسمى قبل إغلاق الملف المقابل.

المزامنة () سوف يرتكب جميع الملفات المعدلة إلى القرص.

أعتقد أدناه وثيقة من بيثون (https://docs.python.org/2/library/os.html) يوضح ذلك جيدا.

OS.FSYNC (FD) قوة ملف من ملف مع FileDescriptor FD إلى القرص. على UNIX ، هذا يدعو وظيفة FSYNC () الأصلية ؛ على Windows ، وظيفة ms _commit ().

إذا كنت تبدأ بكائن ملف Python F ، أولاً ، افعل f.flush () ، ثم قم بـ OS.FSync (F.Fileno ()) ، لضمان كتابة جميع المخازن المؤقتة الداخلية المرتبطة بـ F على القرص.

التوفر: UNIX ، و Windows تبدأ في 2.2.3.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top