متى يتم إرسال حزم منفذ إكمال IO ومتى لا؟
-
01-10-2019 - |
سؤال
أنا أعمل حاليًا على آلية IPC استنادًا إلى الأنابيب المسماة باستخدام منفذ إكمال IO.
لسوء الحظ ، لدي بعض المشاكل في وثائق MSDN لأنه من غير الواضح تمامًا بالنسبة لي أن الحالات التي تستدعيها إلى READFILE/WRITEFILE تؤدي إلى حزمة إكمال.
الحالة عندما يتم إرجاع خطأ مع error_io_pending تكون واضحة ، ولكن ماذا عن الحالة الممكنة على ما يبدو ، عند إرجاع error_more_data؟ هل ستكون هناك حزمة إكمال في هذه الحالة؟ علاوة على ذلك ، ماذا لو تم إرجاع أخطاء أخرى؟ في أي حالات يجب أن أتعامل مع النتيجة والموارد المجانية مباشرة وليس في معالج الانتهاء؟
ستكون هناك حالة أخرى إذا نجحت ReadFile/WriteFile ، وهو أمر ممكن على ما يبدو أيضًا. MSDN هو لحسن الحظ واضح جدا حول هذا هنا:
علاوة على ذلك ، ستعود وظيفة WriteFile في بعض الأحيان بشكل صحيح مع قيمة getLasterror لـ error_success ، على الرغم من أنها تستخدم مقبضًا غير متزامن (والذي يمكن أن يعود أيضًا مع error_io_pending). ... في هذا المثال ، ستكون التوصية هي السماح لروتين منفذ الإكمال بأن يكون مسؤولاً فقط عن جميع عمليات تحرير هذه الموارد.
هل هذه التوصية صحيحة في جميع الحالات ، ويمكن أن يتم تجاهل (وينبغي) في الواقع نتيجة لعملية إعادة القراءة/الكتابة للمقابض المخصصة لمنفذ الإنجاز؟
المحلول
سيكون هناك عنصر إكمال IO في قائمة انتظار لعملية IO كلما كانت عملية IO قادرة على البدء. بغض النظر عما إذا كان قد تمت مواجهة خطأ أم لا بعد بدء تشغيل IO ، سيتم وضع عنصر إكمال في منفذ الانتهاء.
هناك مشكلة رسم الخرائط بين NTSTATUS
الرموز التي يتم إرجاعها بواسطة نظام IO ورموز الأخطاء Win32 التي تجعل من الصعب معرفة الحالات التي هي الأخطاء والتي هي فقط إعلامية. NTSTATUS
, ، والتي تستخدمها kernel و API الأصلي ، لديها أربعة مستويات من الشدة: النجاح والمعلومات والتحذير والخطأ. أي شيء سوى رمز الخطأ يشير إلى أن عملية IO كانت قادرة على البدء. Win32 لديه شدة واحدة فقط (ERROR_*
) ، لذلك كان لا بد من تعيين النجاح والمعلومات ورموز التحذير إلى جانب رموز الخطأ.
ERROR_IO_PENDING
-STATUS_PENDING
هي حالة النجاحERROR_MORE_DATA
-STATUS_BUFFER_OVERFLOW
تحذير أوSTATUS_MORE_ENTRIES
حالة النجاح
يمكنك تجاهل أي رموز غير رموز التي يعود إليها أو تكتبها وتتوقع عنصر إكمال في قائمة الانتظار ، ولكن تحديد أي شيء يمكن أن يكون جزءًا من الألم. سيكون من الرائع إذا تم تنظيم رموز الخطأ Win32 بشكل أفضل ، لكن Microsoft تقدم رسم خرائط من NTSTATUS
إلى رموز الخطأ WIN32: http://support.microsoft.com/kb/113996. نرى ntstatus.h
في النظام الأساسي SDK أو التثبيت VS الخاص بك لتحديد شدة أ NTSTATUS
الرمز هو.
من الممكن إكمال عملية IO عند إرجاع مكالمة API الأصلية ، على سبيل المثال طلب قراءة تم نسخه للتو من ذاكرة التخزين المؤقت (لا شيء للانتظار بشكل غير متزامن). ستظل رسالة الانتهاء في قائمة الانتظار في مثل هذه الحالات من أجل الاتساق.
نصائح أخرى
نعم ، من الممكن تمامًا ذلك
ERROR_MORE_DATA
يمكن أن تأتي في حزمة الانتهاء. يجب أن تكون دائمًا مستعدًا للتعامل مع أي أخطاء محتملة. في الوثائقGetQueuedCompletionStatus
من الواضح أنه عندما تعودFALSE
, ، يجب عليك التحقق مما إذا كانlpOverlapped
المعلمة هيNULL
. إذا لم يكن كذلكNULL
, ، تحتوي حزمة إكمال I/O على خطأ.السلوك الافتراضي هو أن يتم وضع حزمة إكمال في قائمة الانتظار حتى منفذ الانتهاء حتى عندما تكون عندما
ReadFile
أوWriteFile
إرجاعTRUE
. بدءًا من Windows Vista ، يمكن تغيير هذه السياسة. انظر الوثائق علىSetFileCompletionNotificationModes
.