0Pricing
C++ Academy · บทเรียน

IO แบบอะซิงโครนัสด้วย epoll และ kqueue

รองรับการเชื่อมต่อจำนวนมากด้วย epoll บน Linux และ kqueue บน BSD หรือ macOS

IO แบบอะซิงโครนัสด้วย epoll และ kqueue เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงใช้ I/O แบบอะซิงโครนัส

การใช้เธรดหนึ่งเธรดต่อการเชื่อมต่อไม่สามารถรองรับไคลเอ็นต์หลายพันหรือหลายล้านรายได้ดี I/O แบบอะซิงโครนัสทำให้เธรดเดียวจัดการซ็อกเก็ตจำนวนมากได้ โดยรอให้ซ็อกเก็ตใดก็ตามพร้อมอ่านหรือพร้อมเขียน

Linux: epoll

Linux มีส่วนติดต่อเหตุการณ์ที่ปรับขนาดได้ เพิ่มตัวระบุไฟล์ลงในอินสแตนซ์ของ epoll แล้วรอเหตุการณ์จากตัวระบุใดก็ตาม

#include <sys/epoll.h>
int epfd = epoll_create1(0);
epoll_event ev{};
ev.events = EPOLLIN;
ev.data.fd = sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);

การรอเหตุการณ์

epoll_wait จะบล็อกจนกว่าจะมีเหตุการณ์ จากนั้นส่งคืนตัวระบุที่พร้อมทำงาน

epoll_event events[64];
int n = epoll_wait(epfd, events, 64, -1);
for (int i = 0; i < n; ++i) {
    int fd = events[i].data.fd;
    handle_io(fd);
}

แบบทำงานเมื่อระดับเปลี่ยนเทียบกับแบบทำงานเมื่อขอบเปลี่ยน

มีสองโหมด:

  • แบบทำงานเมื่อระดับเปลี่ยน (ค่าเริ่มต้น) — epoll ยังคงรายงานตราบใดที่เงื่อนไขยังเป็นจริง
  • แบบทำงานเมื่อขอบเปลี่ยน (EPOLLET) — รายงานเฉพาะเมื่อสถานะเปลี่ยน คุณต้องอ่านข้อมูลจากซ็อกเก็ตจนหมดทุกครั้ง

macOS และ BSD: kqueue

kqueue เป็นสิ่งเทียบเท่า epoll ของ BSD และมีให้ใช้บน macOS ด้วย แนวคิดคล้ายกัน แต่ส่วนติดต่อแตกต่างกัน

#include <sys/event.h>
int kq = kqueue();
struct kevent ev;
EV_SET(&ev, sock, EVFILT_READ, EV_ADD, 0, 0, nullptr);
kevent(kq, &ev, 1, nullptr, 0, nullptr);

Windows: IOCP

Windows ใช้พอร์ตเสร็จสิ้นการทำงานของ I/O (IOCP) ซึ่งเป็นแบบจำลองที่อิงการเสร็จสิ้น (แจ้งเตือนเมื่อเสร็จแล้ว) แทนแบบจำลองความพร้อมของ epoll/kqueue

ซ็อกเก็ตแบบไม่บล็อก

ตั้งค่าซ็อกเก็ตให้ไม่บล็อกด้วย fcntl(fd, F_SETFL, O_NONBLOCK) มิฉะนั้นการอ่านและการเขียนอาจบล็อกลูปเหตุการณ์ทั้งหมด

รูปแบบลูปเหตุการณ์

ลูปที่ทำงานตลอดไป:

  1. รอเหตุการณ์ที่พร้อมทำงาน
  2. สำหรับแต่ละเหตุการณ์ ให้ทำ I/O จนกว่าการทำงานจะบล็อก
  3. ทำซ้ำ

การจัดการไคลเอ็นต์จำนวนมาก

เธรด epoll เดียวสามารถจัดการการเชื่อมต่อพร้อมกันได้หลายหมื่นรายการ ซึ่งเป็นปัญหา C10K ระบบสมัยใหม่รองรับได้ถึงหลายล้านรายการ

ข้อผิดพลาดที่พบบ่อย

โปรดระวัง:

  • ลืมตั้งโหมดไม่บล็อก
  • ใช้แบบทำงานเมื่อขอบเปลี่ยนโดยไม่อ่านข้อมูลจากซ็อกเก็ตจนหมด
  • ไม่ลบตัวระบุไฟล์ที่ปิดแล้วออกจากชุด epoll
  • บัฟเฟอร์รั่วไหลต่อการเชื่อมต่อ

ตัวห่อหุ้มระดับสูง

การเขียนลูป epoll ด้วยตนเองมีโอกาสเกิดข้อผิดพลาดสูง สำหรับโค้ดใช้งานจริงให้ใช้ libuv, libevent หรือ Boost.Asio ซึ่งซ่อนความแตกต่างระหว่างแพลตฟอร์มและมีลูป I/O ที่ผ่านการทดสอบแล้ว

อะซิงโครนัสเทียบกับเธรด

I/O แบบอะซิงโครนัสรองรับการขยายขนาดได้ดีกว่า แต่เขียนได้ยากกว่า สำหรับเซิร์ฟเวอร์ที่มีการเชื่อมต่อระดับหลักพัน การใช้เธรดต่อการเชื่อมต่อจะเรียบง่ายกว่า ให้เลือกตามปริมาณงานที่คาดว่าจะเกิดขึ้น

ตรวจสอบอย่างรวดเร็ว

โหมดแบบทำงานเมื่อขอบเปลี่ยนและแบบทำงานเมื่อระดับเปลี่ยนใน epoll แตกต่างกันอย่างไร

สรุปทบทวน

I/O แบบอะซิงโครนัสรองรับการทำงานพร้อมกันจำนวนมหาศาลได้ด้วยการจัดการซ็อกเก็ตจำนวนมากในเธรดเดียว Linux ใช้ epoll, BSD/macOS ใช้ kqueue และ Windows ใช้ IOCP ตั้งค่าซ็อกเก็ตให้ไม่บล็อก สำหรับการใช้งานจริง ให้ใช้ไลบรารี (Asio, libuv, libevent) แทนการเขียนลูปเหตุการณ์ด้วยตนเอง

คำถามที่พบบ่อย

บทเรียน “IO แบบอะซิงโครนัสด้วย epoll และ kqueue” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “IO แบบอะซิงโครนัสด้วย epoll และ kqueue” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “IO แบบอะซิงโครนัสด้วย epoll และ kqueue”

รองรับการเชื่อมต่อจำนวนมากด้วย epoll บน Linux และ kqueue บน BSD หรือ macOS คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “IO แบบอะซิงโครนัสด้วย epoll และ kqueue” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. API ซ็อกเก็ต BSD ใน C++
  2. การสร้างเซิร์ฟเวอร์สะท้อน TCP
  3. IO แบบอะซิงโครนัสด้วย epoll และ kqueue
  4. การใช้ Boost Asio สำหรับ IO แบบอะซิงโครนัสสมัยใหม่
← กลับไปที่ C++ Academy