epoll in epollet mode report 2 epollin قبل القراءة من المقبس
-
28-09-2019 - |
سؤال
يقول ManPage EPOLL أن FD المسجل لدى Epollet (Edge الذي تم تشغيله) لا ينبغي أن يخطر مرتين Epollin إذا لم يتم قراءة أي قراءة.
لذلك بعد Epollin ، تحتاج إلى تفريغ المخزن المؤقت قبل أن تتمكن Epoll_Wait من إعادة Epollin جديدة على بيانات جديدة.
ومع ذلك ، أواجه مشاكل في هذا النهج لأنني أرى أحداث Epollin المكررة ل FDS لم تمسها.
هذا هو إخراج Strace ، 0x200 هو epollrdhup لم يتم تعريفه بعد في رؤوس glibc الخاصة بي ولكن محددة في kernel.
30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011
لذلك ، بعد إضافة رقم FD رقم 9 ، أتلقى أحداث Epollin متتالية قبل أن أتخلى عن واصف الملف ، يوضح Trace Syscall كيف أقوم بحذف FD قبل القراءة ولكن يجب أن يحدث مرة واحدة فقط ، واحد لكل حدث.
لذا ، فأنا لا أقرأ Manpage بشكل صحيح أو شيء يعمل الآن هنا.
المحلول
أعتقد أنك فاتتك هذا الجزء من epoll
صفحة الرجل:
نظرًا لأنه حتى مع وجود أحداث متعددة من الأحداث التي يتم تشغيلها على الحافة ، يمكن إنشاء أحداث متعددة عند استلام أجزاء متعددة من البيانات ، فإن المتصل لديه خيار لتحديد
EPOLLONESHOT
العلم ، لإخبار Epoll لتعطيل واصف الملف المرتبط بعد استلام حدث معepoll_wait(2)
. عندماEPOLLONESHOT
تم تحديد العلم ، إنها مسؤولية المتصل بتعديل واصف الملف باستخدامepoll_ctl(2)
معEPOLL_CTL_MOD
.
هذا هو: لقد حصلت على قطعتين من البيانات التي تصل في قائمة انتظار تلقيك قبل الأول read()
حدث ، مما يعني أنك حصلت على حدثين EPOLL. انها تبدو مثل EPOLLONESHOT
هو ما تتبعه ، والذي سيقوم بإزالة واصف الملف من مجموعة الاستطلاع عندما يحدث حدث على ذلك (لذلك لن تحتاج إلى القيام EPOLL_CTL_DEL
).
نصائح أخرى
يعني TEDER TRIGGER (ما لم تكن قد استخدمت Epolloneshot) أنك ستحصل على حدث واحد عندما يدخل شيء ما في المخزن المؤقت (kernel).
وبالتالي ، إذا حصلت على حدث واحد من Epollin ولم تفعل شيئًا حيال ذلك ، فستحصل على Epollin آخر في المرة القادمة التي تصل فيها بعض البيانات إلى هذا الواصف - إذا لم تصل بيانات جديدة ، فلن تحصل على حدث رغم ذلك ، حتى لو لم تقم بذلك اقرأ أي بيانات كما هو موضح في الحدث الأول.
حسنًا ، بعبارة إيجاز ، يعني Epolloneshot أنه إذا لم تقرأ البيانات التي من المفترض أن تقرأها ، فسيتم تجاهلها.
عادة ، سيتم إخطارك بحدث لنفس البيانات إذا لم تقرأها. مع Epolloneshot ، ومع ذلك ، فإن عدم قراءة البيانات قانونية تمامًا وسيتم تجاهلها للتو. وبالتالي ، لن يتم إنشاء أي أحداث أخرى.