12.3 io uring תרגול
תרגול: io_uring - I/O אסינכרוני מתקדם¶
תרגיל 1 - קריאת קבצים עם io_uring¶
כתבו תוכנית שקוראת 10 קבצים במקביל באמצעות io_uring.
צרו 10 קבצי טקסט זמניים (כל אחד עם תוכן אחר). שלחו 10 בקשות קריאה בבת אחת ל-io_uring, ואז קראו את כל 10 התוצאות.
דרישות:
- השתמשו ב-io_uring_prep_read לכל קובץ.
- שלחו את כל 10 הבקשות עם io_uring_submit אחד.
- קראו את כל התוצאות עם לולאת io_uring_wait_cqe.
- השתמשו ב-user_data כדי לזהות איזה קובץ הושלם.
- הדפיסו את תוכן כל קובץ.
תרגיל 2 - שרת echo עם io_uring¶
ממשו שרת echo מלא עם io_uring שמטפל במספר לקוחות במקביל.
דרישות:
- השתמשו ב-io_uring_prep_accept לקבלת חיבורים.
- השתמשו ב-io_uring_prep_recv ו-io_uring_prep_send לקריאה וכתיבה.
- טפלו נכון בסגירת חיבור (כשread מחזיר 0).
- בדקו עם nc localhost <port> ממספר טרמינלים במקביל.
- הדפיסו הודעה לכל חיבור חדש, כל הודעה שנקראה, וכל חיבור שנסגר.
תרגיל 3 - העתקת קובץ אסינכרונית¶
כתבו תוכנית שמעתיקה קובץ גדול באמצעות io_uring עם שרשור פעולות (operation chaining).
דרישות:
- קראו את הקובץ בבלוקים של 4096 בתים.
- לכל בלוק, שרשרו read ואז write עם דגל IOSQE_IO_LINK.
- שלחו כמה בלוקים במקביל (batching) - לפחות 8 בלוקים בו-זמנית.
- מדדו את הזמן והשוו לפעולת cp רגילה על קובץ של 100MB.
- שימו לב: צריך לנהל offsets נכון בקריאה ובכתיבה.
תרגיל 4 - השוואת ביצועים: epoll מול io_uring¶
כתבו שתי גרסאות של שרת echo - אחת עם epoll ואחת עם io_uring - ובצעו benchmark.
דרישות:
- כל גרסה מאזינה על אותו פורט (הריצו אחת בכל פעם).
- כתבו סקריפט לקוח שפותח 100 חיבורים במקביל ושולח 1000 הודעות בכל חיבור.
- מדדו את הזמן הכולל, throughput (הודעות לשנייה), ו-latency ממוצע.
- הדפיסו טבלת השוואה בסיום.
- רמז: אפשר להשתמש בthread pool בצד הלקוח כדי לסמלץ 100 לקוחות.
תרגיל 5 - טיימר עם io_uring¶
כתבו תוכנית שמשתמשת ב-io_uring לניהול טיימרים.
צרו 5 טיימרים שמופעלים בזמנים שונים (1 שנייה, 2 שניות, ..., 5 שניות). השתמשו ב-io_uring_prep_timeout כדי להגיש את הטיימרים, ועבדו את התוצאות כשהם מגיעים.
דרישות:
- השתמשו ב-io_uring_prep_timeout עם struct __kernel_timespec.
- שלחו את כל 5 הטיימרים בבת אחת.
- כשטיימר פוקע, הדפיסו איזה טיימר פקע ומתי (שניות מתחילת התוכנית).
- השתמשו ב-user_data כדי לזהות כל טיימר.