على خادم Windows ، تكتب أداة التسجيل ملفات .log إلى القرص باستمرار وتقوم بتدوير ملفات السجل يوميًا في منتصف الليل. يتم إنشاء ملف السجل الجديد كل يوم ، ولكن كل يوم تقريبًا لا يتم تحديث بيانات المحتوى / البيانات الوصفية الخاصة به بعد ذلك في Windows Explorer و Powershell.

مثال: تم إنشاء ملف في 17 مايو 2022 الساعة 0:00. يبلغ حجمه 24 كيلو بايت تقريبًا في مستكشف Windows ولديه وقت كتابة أخير في حوالي منتصف الليل (لم أتحقق من الوقت المحدد حتى الثانية). إذا كنت أستخدم Powershell

(Get-Item).Length

أحصل على حجم 24401.

الآن عندما أنقر بزر الماوس الأيمن على نفس الملف ، فإن مستكشف Windows وفحص خصائصه ، يقوم بتحديث الحجم إلى 4593 كيلو بايت وآخر وقت للكتابة حتى 17 مايو 2022 09:34. لا يهم الحجم والوقت الدقيقين حقًا ، ولكن المشكلة هي: لماذا يكون مستكشف Windows و Windows Powershell غير متزامنين تمامًا مع نظام الملفات الأساسي مثل هذا؟ ما الذي يمكن أن يسبب تناقضًا كهذا؟

مرة أخرى استخدمت هذا لاختبار ما إذا كان الملف قد تم نسخه خارج المزامنة أو مع المحتوى الصحيح:

Copy-Item ".. source file .." -Destination ".. somewhere .."

يتم تحديث سمات الملف الأصلي حتى أتمكن من استخدام ذلك كحل بديل سيئ حقًا للحصول دائمًا على أحدث إصدار من الملف متاحًا بالفعل في Powershell حيث أقوم بتحليل الملف باستخدام برنامج نصي من Powershell وأحتاج حقًا إلى كل محتوياته و ليس فقط محتوى الملف عندما تم إنشاؤه قبل 9 ساعات.

هل شاهد أي شخص هذا النوع من السلوك في Windows؟

  • نظام الملفات: NTFS
  • نظام التشغيل: Windows Server 2019 الإصدار 1809 النسخة 17763.2803
  • "الأجهزة": خادم افتراضي على خادم VMware ESXi
answer

نعم ، هذا لأن العملية لا تزال تكتب إلى الملف ولا يتم مسح المخازن المؤقتة.

عادةً ، عندما تريد الكتابة إلى ملف ، يمكنك (تقريبًا) القيام بشيء من هذا القبيل:

1. Create/Open a file and retrieve a "channel" (a handle) towards the file
2. Write something
3. Flush the buffer/Close the file "channel" (handle) (=commit to disk)
(then, repeat 1, 2 and 3 when you want to write something again)

ومع ذلك ، فإن القيام بشيء من هذا القبيل لا بأس به إذا كنت ترغب في كتابة شيء ما بين حين وآخر ، لأن "فتح المقبض للملف" و "مسح المخازن المؤقتة" ليس "مجانيًا" عندما يتعلق الأمر بالأداء.

هذا يعني أنه إذا كنت تخطط للكتابة بشكل متكرر إلى ملف ، فمن الأفضل أن تكتب فقط Create/Open a file، ثم Writeعدة مرات ، حسب الحاجة ، وعند الانتهاء Flushأو إغلاق المقبض (في المثال أعلاه يعني 1، 2[كرر الخطوة 2حسب الحاجة] ، ثم لاحقًا 3)

وعلى الرغم من عدم تدفق البيانات إلى القرص / الالتزام: لا يمكنك الاعتماد عليها!

توفر Microsoft مزيدًا من التفاصيل حول ذلك:

تدفق بيانات الإدخال / الإخراج المخزنة بواسطة النظام إلى القرص

[...]Windows stores the data in file read and write operations in system-maintained data buffers to optimize disk performance. When an application writes to a file, the system usually buffers the data and writes the data to the disk on a regular basis[...]

يقول مستند FlushFileBuffers Windows API:

[...]Typically the WriteFile and WriteFileEx functions write data to an internal buffer that the operating system writes to a disk or communication pipe on a regular basis. The FlushFileBuffers function writes all the buffered information for a specified file to the device or pipe.

Due to disk caching interactions within the system, the FlushFileBuffers function can be inefficient when used after every write to a disk drive device when many writes are being performed separately.[...]

وثائق CreateFile :

[...]When an application is finished using the object handle returned by CreateFile, use the CloseHandle function to close the handle. This not only frees up system resources, but can have wider influence on things like sharing the file or device and committing data to disk. Specifics are noted within this topic as appropriate.[...]

يتوفر المزيد من المعلومات حول التخزين المؤقت للملفات هنا ، لاحظ ما يلي:

File system metadata is always cached. Therefore, to store any metadata changes to disk, the file must either be flushed or be opened with FILE_FLAG_WRITE_THROUGH.

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