إعداد epoll
أنشئ مجموعة epoll وسجّلها
إعداد epoll درس مجاني في C Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.
إنشاء مثيل epoll
يبدأ كل شيء بمثيل epoll، وهو في حد ذاته واصف ملف. أنشئه باستخدام epoll_create1().
المعامل عبارة عن حقل للرايات؛ مرّر 0 للسلوك الافتراضي، أو EPOLL_CLOEXEC لإغلاق الواصف تلقائيًا عبر exec(). واصف الملف المُعاد هو ما تمرّره إلى كل استدعاءات epoll الأخرى.
int epfd = epoll_create1(EPOLL_CLOEXEC);
if (epfd == -1) { perror("epoll_create1"); exit(1); }epoll_create1 مقابل epoll_create
كان epoll_create(int size) الأقدم يتلقى تلميحًا عن الحجم، لكن النواة تتجاهله الآن؛ وكان الشرط الوحيد أن تكون قيمته موجبة.
يُفضّل استخدام epoll_create1()؛ فهو يتلقى رايات بدلًا من حجم بلا معنى، ويتيح طلب EPOLL_CLOEXEC ذريًا، متجنبًا استدعاءً منفصلًا لـ fcntl().
/* legacy form, size arg ignored by kernel */
int epfd = epoll_create(1);بنية epoll_event
يُعبَّر عن كل من الأحداث محل الاهتمام والنتائج من خلال struct epoll_event. وتحتوي هذه البنية على قناع بتات events واتحاد data.
يحتوي اتحاد data على أي قيمة تريد إعادتها عند وقوع الحدث: وغالبًا ما تكون data.fd، لكن يمكن أن تكون أيضًا data.ptr تشير إلى كائن اتصال خصصته.
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listen_fd;التسجيل باستخدام EPOLL_CTL_ADD
يدير epoll_ctl() قائمة الاهتمامات. استخدم العملية EPOLL_CTL_ADD لبدء مراقبة واصف.
تمرّر واصف epoll، والعملية، والواصف المستهدف، ومؤشرًا إلى epoll_event الخاص بك. بعد ذلك، سيبلّغ epoll بأن الواصف أصبح جاهزًا.
struct epoll_event ev = { .events = EPOLLIN, .data.fd = listen_fd };
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev) == -1)
perror("epoll_ctl: add");رايات الأحداث: EPOLLIN وEPOLLOUT
يحدد قناع events ما تهتم به. تعني EPOLLIN أن الواصف قابل للقراءة، بينما تعني EPOLLOUT أنه قابل للكتابة.
تراقب عادةً EPOLLIN على مقبس الاستماع لقبول الاتصالات، وعلى مقابس العملاء للقراءة. أضف EPOLLOUT فقط عند وجود بيانات مخزنة مؤقتًا لم تُرسل بالكامل.
ev.events = EPOLLIN | EPOLLOUT;رايات الخطأ وإنهاء الاتصال
تبلّغ النواة دائمًا عن حالات معينة حتى إن لم تطلبها: EPOLLERR للأخطاء، وEPOLLHUP لانقطاع الاتصال، وEPOLLRDHUP للإغلاق الجزئي من الطرف الآخر.
تحقق من هذه الحالات في معالجك؛ فتجاهل EPOLLHUP على مقبس متوقف يؤدي إلى الدوران المستمر في حلقة الأحداث.
if (ev.events & (EPOLLERR | EPOLLHUP)) {
close(ev.data.fd);
continue;
}تعديل الاهتمام باستخدام EPOLL_CTL_MOD
بعد تسجيل واصف، يمكنك تغيير قناع الأحداث الخاص به دون إزالته. استخدم EPOLL_CTL_MOD.
من الأنماط الشائعة أن يراقب الاتصال EPOLLIN فقط عادةً، ثم يتحول إلى EPOLLIN | EPOLLOUT عندما يمتلئ مخزن الإرسال، ويعود إلى حالته السابقة بعد تفريغه.
ev.events = EPOLLIN | EPOLLOUT;
ev.data.fd = conn_fd;
epoll_ctl(epfd, EPOLL_CTL_MOD, conn_fd, &ev);الإزالة باستخدام EPOLL_CTL_DEL
عند إغلاق اتصال، أوقف مراقبته باستخدام EPOLL_CTL_DEL. يتم تجاهل وسيط epoll_event الأخير، ويمكن أن يكون NULL في النوى الحديثة.
لاحظ أن إغلاق الواصف يزيله تلقائيًا من أي قوائم اهتمام بـ epoll، لكن حذفه صراحةً قبل الإغلاق يجعل إدارة الحالات أوضح.
epoll_ctl(epfd, EPOLL_CTL_DEL, conn_fd, NULL);
close(conn_fd);التفعيل بالمستوى مقابل التفعيل بالحافة
يعمل epoll افتراضيًا بنمط التفعيل بالمستوى: ما دام الواصف قابلًا للقراءة، سيبلّغ عنه كل استدعاء لـ epoll_wait(). وهذا نمط متسامح وسهل.
أضف راية EPOLLET لاستخدام نمط التفعيل بالحافة: سيصلك إشعار فقط عند تغير الجاهزية، لذلك يجب تفريغ المقبس بالكامل داخل حلقة حتى ظهور EAGAIN.
ev.events = EPOLLIN | EPOLLET; /* edge-triggered */
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);تخزين مؤشر السياق
بدلًا من data.fd، يمكنك تخزين data.ptr الذي يشير إلى بنية خاصة بكل اتصال. عند وقوع الحدث، تحصل على هذا المؤشر مباشرةً دون الحاجة إلى جدول بحث.
تذكّر فقط أنه اتحاد: إذا عيّنت data.ptr، فلا يمكنك أيضًا قراءة data.fd من الحدث نفسه.
struct conn *c = malloc(sizeof *c);
c->fd = conn_fd;
ev.events = EPOLLIN;
ev.data.ptr = c;
epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);التنظيف
مثيل epoll ليس سوى واصف ملف، لذا تحرره باستخدام close() عند إيقاف تشغيل الخادم.
يحرر إغلاق واصف epoll قائمة الاهتمامات في النواة. أما المقابس المراقبة التي لا تزال مفتوحة فتبقى مفتوحة؛ أغلقها بشكل منفصل لتحرير مواردها.
close(epfd);تحقق سريع
اختبر مدى استيعابك لواجهة إعداد epoll.
مراجعة
تنشئ مثيلًا باستخدام epoll_create1()، ثم تدير الاهتمامات عبر epoll_ctl() باستخدام ADD وMOD وDEL. ويحمل كل struct epoll_event قناع events واتحاد data.
اختر التفعيل بالمستوى للبساطة، أو EPOLLET للحصول على أداء التفعيل بالحافة. بعد ذلك سنحرّك هذه المكونات من خلال حلقة أحداث.
الأسئلة الشائعة
هل درس «إعداد epoll» مجاني؟
نعم — نص درس «إعداد epoll» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.
ماذا ستتعلم في «إعداد epoll»؟
أنشئ مجموعة epoll وسجّلها تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟
لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «إعداد epoll»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟
نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.