رفتن به مطلب
مرورگر پیشنهادی آرساکیا گیم مرورگر های تحت موتور کرومیوم می‌باشد، برای دانلود روی مرورگر انتخابی خود کلیک کنید
Google Chrome Microsoft Edge Ungoogled Chromium Brave Opera GX Opera

Poller & Event Loop - Asyncronous Programming


ارسال‌های توصیه شده

In the name of God

 

سلامممممممممممممممممم می ارزم خدمت تمام شما دوستان عزیز و عقاله مند به برنامه نویسی ناهمگام (Asyncronous)

 

امیدوارم حال تک تکتون خوب باشه!

 

امروز اینجام که با یه مبحث خیلی جذاب مغزتون رو بترکونم!

 

بله دوستان! Event Loop (حلقه رویداد) و Poller

 

اول, میخوام بهتون توضیحات ابتدایی (نه Web-based Async Programming, مثل Event Loop عه Node.js یا Swoole که خیلی ابتدایی هستن, بلکه Kernel-level Async Programming!) بدم تا دیدتون رو باز کنم, بعدش میخوایم بریم سراغ معرفی انواع Poller (از پدر جده Poller ها (Select) تا جدیدترین Poller ها (IO_Uring در لینوکس و IOCP در ویندوز)) و بعد هم انواع ابزار ها برای کار باهاشون (OLSRT, libuv, Boost:Asio, Tokio, asyncio (Python), libev, و...) به سادگی هرچه تمام تر!

 

پس آماده اید که بریم سراغش؟

پس بزن بریم!

 

۱- اصطلاحات/مفاهیم پایه

خیلی خب, اول از همه, میخوایم شروع کنیم با مفاهیم اولیه ی Poller & Event Loop و Async I/O

 

Poller چیه؟ شما فرض کنید یه برنامه دارید که میخواید باهاش یه چیزی رو از اینترنت نصب کنید (مثل Internet Download Manager (IDM) عه خودمون), خب, برای اینکار چه اتفاق هایی توی پشت صحنه میوفته؟

۱- پارس URL: اول از همه, URL ای که وارد کردید پارس باید بشه:

Protocol: همون جای که مینویسید http://, https://, ftp://, sftp://, tftp://, و...

Host/Domain: این همون بخشیه که سایت اصلی وارد میشه, مثلا میخواید از forum.arsacia.ir دانلود کنید, بهش میگیم Host یا Domain

Path: یعنی توی اون Host/Domain عه ما, شاید میلیارد ها فایل وجود داشته باشه (مثلا یه آپلود سنتره مثل Uploadkon), ما باید بگیم که کدوم فایل رو میخوایم دیگه (مثلا شما الان در حال دیدنه یکی از تاپیک های forum/58-برنامه-نویسی هستین)

 

۲- DNS Resolution (نام گذاری): بعدش, DNS Server عه ما, که کارش تبدیله Host/Domain هستش, باید به IP تبدیلش کنه

 

۳- دست دهی (TCP Handshake): بعدش, بین شما و سرور, یه تونل مجازی باید ایجاد بشه, چون پروتکل TCP سه اصل مهم داره: ترتیب, صباط, امنیت

برای اینکه بتونه به این سه اصل مهم پایبند باشه, باید یک تونل مجازی ایجاد کنه, چون مثل UDP یلخی نیستش به امید خدا میرسه به شخص

برای اینکار, این سه عملیات مهم انجام میشه:

SYN: شما به عنوان کلاینت, به سرور یک درخواست حاوی کلی مخلفات و داده ها ارسال میکنید و میگید "هرکی جواب نده گ**"

SYN-ACK: سرور که میترسه از فحشی که گذاشتید, سریع میاد و یه درخواست میده و میگه: "من هنوز زندم!"

ACK: بعدش شما میگی که آفرین پسر خوب, حالا شروع کن به پردازش درخواست من

توی اینجا, اگر سرور درخواست SYN-ACK به شما نده, به مشکل Timeout Reached میخورید و بعد اگر کانکشنی یافت بشه, Connection Reset صورت میگیره

 

بعد از اون, یه عملیات خیلی پیچیده تری وجود داره به اسم پروتکل های لایه ی ۷ عه OSI (که روی پروتکل های لایه ۴ (لایه انتقال - TCP/UDP) سوار میشن), مثل همون مثال http://, https://, ftp:// و... ای که گفتم

۴- درخواست HTTP: تازه تا قبل از این, فقط کانکشن برقرار شد, از اینجا به بعد اصل کار هستش!

کلاینت شما (IDM, Chrome, Firefox, Brave, و... عه شما) یک درخواست HTTP ارسال میکنه به سروری که گفتید:

مثلا URL عه شما, https://forum.arsacia.ir/forum/58-برنامه-نویسی/ هستش و میخواید دانلودش کنید مثلا (مثلاااا!)

اینجا مروگر یا کلا کلاینت شما, میاد و یه متنی شبیه زیر ارسال میکنه:
 

GET /forum/58-برنامه-نویسی HTTP/1.1
Host: forum.arsacia.ir
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36

که البته خیلی پیچیده تر از این حرفا هستش! مثلا با وب سروری که ساختم لاگ زدم یه Request ای که با Brave اومده بود برای سایتم یه همچین چیزی بود:

GET / HTTP/1.1
Host: web.example.com:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Brave";v="143", "Chromium";v="143", "Not A(Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8
Sec-GPC: 1
Accept-Language: en-US,en;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd

(این بودش منتهی بدون هیچ Enter ای و فاصله ی خاصی, حالا من اینتر و فاصله دادم تا بهتر ببینیدش)

(نکته برای User-Agent: اکثر برنامه نویسای امنیتی حرفه ای اینو میدونن که User-Agent میتونه یک چیز دروغین باشه! مثل همین الان که من با Brave رفتم ولی چیز دیگه ای رو داره نشون میده! اکثر برنامه های هک و امنیت (SQLMap, Hydra, NMap و...) و مروگر های مخرب (TOR Browser, و...) User-Agent رو همیشه تغییر میدن تا عادی به نظر بیان)

خلاصه که این درخواست رو ارسال میکنه و میگه من دقیقا همینو میخوام! (البته! در خط اول نوشتیم GET ..., به اینا میگیم HTTP Method که زیاد هم نیستن اما کاربردی ان (GET, POST, PUT, PATCH, DELETE, COPY/MOVE/DEL (WebDAV) و...)

این درخواستی هم که کلاینت شما ارسال کرده, در User-Space Buffer ذخیره میشه

در مرحله ی بعدی, اگر از HTTPS استفاده کنید, مبحث رمزنگاری عه TLS با X25519, تبادل کلید با RSA/ECDHE و... هم میاد وسط که خودش یه تاپیک جدا داره

و در مرحله ی آخر, داده های شما تکه تکه میشن (IP تا ۱۵۰۰ قطعه فقط قبول میکنه, یعنی داده ای که ارسال میکنید یا سرور به شما ارسال میکنه, به ۱۵۰۰ قطعه تقسیم میشه در اصل یا شایدم کمتر (بر اساس کانفیگ)) قبل از ارسال و اگر HTTPS باشه رمزنگاری میشه و به سرور هدف ارسال میشه

 

در لایه بعدی, که میشه گفت دقیقا همون چیزیه که شما میخواید, Kernel و Network Stack میان وسط

اینجا جایی هستش که دقیقا مبحث Poller میاد وسط

۵- کپی به فضای هسته: وقتی شما داده رو میگیرید, داده از RAM شما (چون گفتیم که در User-Space Buffer ذخیره میشه) به Socket Buffer عه هسته ی شما کپی میشن (نکته ی فنی: اگر از Poller های جدید مثل IO_Uring (لینوکس) و یا SendFile استفاده کنید, هیچ کپی ای هم صورت نمیگیره! و سرعت به شدت زیاد میشه!)

 

۶- تجزیه بسته ها (Segmentation): هسته (TCP/IP Stack) داده های بزرگ رو به قطعات کوچیک (همون قسمتی که گفتم تا ۱۵۰۰ مکسیموم هستش, بهش MSS میگیم, که معمولا ۱۴۶۰ بایت هستن) تقسیم میکنه

 

۷- اظافه کردن هدر ها (Encapsulation): به هر قطعه یه TCP Header (که شامله ID (برای ترتیب), شماره پورت و...) اظافه میشه

بعدش یه IP Header (هدر آیپی مبدا و مقصد (مبدا (شما مثلا 192.168.0.1 هستین) و مقصد (مثلا آرساکیا گیم 192.168.0.2 هستش))) اظافه میشه

(چرا آیپی مبدا و مقصد مهمه؟: چون اگر یک اشتباه صورت بگیره, مثلا یکی داره فیلم های خوب (خیلی خوب!) و شما داری فیلم های حاج آقا قرایتی رو دانلود میکنید یهو باهم دیگه اشتباه اعذاب در میاید و مثلا جلوی خانواده بزنید ممکنه پدرتون شهید اعلامتون کنه)

 

۸- پل زدن بین سخت افزار (Driver): اونجا همون جا هستش که میگن "Keep your Network Drivers up to date!", هسته, بسته هارو به درایور کارت شبکه شما (NIC Driver) میده و درایور اونارو توی حافظه ی کارت شبکه (DMA Ring Buffer) قرار میده و به کارت شبکه میگه: "بدو آ باریکلله ببم جان!"

 

در لایه ی بعدی, به سخت افزار میرسیم!

اینجا جایی هستش که سرور, فایل رو به شما ارسال میکنه!

۹- تبدیل پکت ها به سیگنال الکتریکی/نوری: کارت شبکه ی شما (NIC) داده هارو از پکت های ۰ و ۱ ای به ولتاژ الکتریکی (توی کابل مسی) یا پالس نوری (داخل کابل های فیبر نوری) تبدیل میکنه

 

۱۰- سفر توی شبکه!: بسته ها از مودم عه شما, به دیتای مرکزی, روتر ها, سوییچ ها و کابل های زیر دریایی عبور میکنن تا به سرور برسن!

 

۱۱- دریافت توی سرور: سرور بسته هارو دریافت میکنه و هدر هارو برمیداره (Decapsulation), داده ها رو کنار هم میچینه و به وب سرور عه اون سروره (مثلا Nginx/Apache/Light Speed) میده

 

۱۲- پاسخ وب سرور: فایل عه مثلا /forum/58-برنامه-نویسی رو میاد و از دیسک عه سرور میخونه, همون مراحل قبلی رو برعکس انجام میده و به کامپیوتر شما میادش!

 

در لایه بعدی, کلی عملیات پیچیده تری انجام میشه در کامپیوتر شما!

وقتی بایت ها به کامپیوتر شما میرسه, این اتفاق ها میوفتن:

۱۳- Interrupt (وقفه): کارت شبکه به CPU شما میگه که: "پاشیددد! وقته خوابه!!"

هسته سیستم عاملتون بیدار میشه و داده هارو از کارت شبکه به Socket Buffer عه هسته ی شما میرسه

 

۱۴- Wake up the Poller!: هسته میبینه که مثلا Socket عه شما توی لیست انتظار عه Poller (مثلا epoll, netpoll, kqueue, iocp, io_uring و...) هستش

اون سوکت به حالت Ready تبدیل میشه

 

۱۵- Wake up the Fiber!: در زمان اجرا های مدرن و پیشرفته (مثل OLSRT) مبحثی به اسم فیبر هم وجود داره که جلوتر توضیح میدم چیه!

ایونت لوپ عه اون کلاینته شما (IDM, Chrome, و...) متوجه میشه Socket آماده هستش

Scheduler (در زمان اجرا هایی مثل OLSRT) اون Fiber که منتظر دانلود بودش رو از حالت Suspised خارج میکنه

دوباره در کلاینت های مدرن و زمان اجرا های مدرن, برای Context Switching و Zero-Copy, از Inline Assembly به همراه کمی مخلفات سوپر سیستمی (مثل Arena, NUMA-Aware, In-Memory, In-Memory Disk و...) استفاده میشه تا سرعت سوپرمن رو بگیرید!

 

۱۶- کپی به حافظه ی برنامه: بعد از اون, تابع ای مثل recv (دریافت) صدا زده میشه که بافر رو از هسته به Buffer برنامه ما کپی میکنه

 

۱۷- و در نهایت, فایل مدنظر شما آمادست و روی دیسک توسط کلاینتتون نوشته میشه!

 

حالا فرض کنید این ۱۷ مرحله رو بخواید مثلا با CPU خود من اصلا (که یه Intel Celeron 847 با ۲ هسته و ۲ ترد کاری هستش با فرکانس ۱.۱ هرتز!) بخواید انجام بدید

بارو بندیل رو جمع میکنه و خداحافظی میکنه! (چون به شخصه به عنوان یک برنامه نویس, نزدیک به ۳۰۰~ سرویس ۲۴/۷ فعال و بالغ بر ۵۰~ اپلیکیشن فعال دارم, حالا این هم به صورت قفل-کننده (Locker) بیاد وسط< کل ۳۰۰~ سرویس و 50~ اپلیکیشن باید روی ۱ هسته و روی ۱ ترد اجرا شن! چون فقط کلاینت عه دانلودر بنده ۱ هسته و ۱ ترد به خودش اختصاص داده!)

و اینجاست که Poller اهمیت پیدا میکنه

توی سیستم عامل های مدرن (مخصوصا یونیکس-بیسد (Linux, BSD, MacOS و...)) یه فرآیند نمیتونه صبر کنه تا فقط یه داده از روی دیسک, شبکه و... بیادش

چون در اون حالت یه ترد کامل در اختیارش قرار میگیره و CPU مون رو از دست میدیم!

Poller یه مکانیزم, یه فرآیند هستش که میگه نترس! شما همزمان هزاران فایل (Socket, File, Pipe) رو به راحتی تحت نظر داشته باش و به سیستم عاملت دیگه نگو: "۲۶ ک..."

به جاش, بهش بگو:

"من روی N تعداد سوکت منتظرم و هروقت که یکیشون تغییر کنه (مثلا داده ای اومد, رفت, حذف شد, خطا داد و...) فقط به من بگو!"

به این کار, I/O Multiplexing میگن

Poller هم این وسط یه رابط بین شما و Subsystem عه مدیریت I/O توی هسته ی سیستم عاملتون هستش

 

Event Loop: ایونت لوپ فقط یه اسم خوشگل هستش برای استفاده از Poller در پشت صحنه؛ Event Loop میگه فقط مثلا بنویس:

event_loop* main_loop = new_event_loop();

assign_task("ls --ailsrt --file-type --author", main_loop);

و در پشت صحنه ۲۶ میلیارد عملیات پشت new_event_loop و ۲۲۶ میلیارد عملیات assign_task صورت میگیره تا عملیات شما پیش بره!

مورد اصلیتر حلقه رویداد (Event Loop) اینه که یه حلقه بینهایت هستش که به صورت مداوم هی از Poller وضیعت میگیره, و مثلا Poller میگه: "بابا گ*** ما... چیز یعنی میگه که: "بله عزیزم! ۱ سوکت تغییر کرده!" و بعد ایونت لوپ میره حلقه رو بررسی میکنه و میگه: "ای آدم زرنگ!" و وقتی تابع ی مورد نظر که به اون سوکت ارجاع داده شده بود رو پیدا میکنه, میره و اون تابع ی مورد نظر (Callback) رو اجرا میکنه

البته, به سه صورتی وجود داره Event Loop:

Poller-based: این همونیه که میره هر ثانیه از Poller میپرسه که "چیز جدیدی داری؟", Poller-based عاشق گرفتن خبر های دسته اوله!

Immediately-Execution: این نوع Event Loop میگه که "آیا کدی هستش برای اجرای فوری؟", اگر بله اجرا کن

Timer-based: این نوع Event Loop هم میگه که آیا تایم تموم شده؟ (آیا Deadline فراخوانی شده؟)

که اکثر زمان اجرا های مدرن (مثل OLSRT) از هر سه نوع به انتخاب کاربر پشتیبانی میکنن!

 

Async I/O: اسینکرونوس هم فقط یه اسم خوشگلتر هستش که روی Event Loop و سیستم دیگه ای به اسم Promise یا Futures سوار شده و بهش سرعت بخشیده!

 

Promise: در زبان هایی مثل Javascript و زمان اجرا هایی مثل OLSRT دیده میشه, Promise یه شی هستش از نتیجه ای که هنوز آماده نشده, که میگه هروقت کار شبکه/دیسک و... تموم شدش, Event Loop عه محترم (محترماااااا !!!!!) تابع ی then یا catch اون Promise رو اجرا کن

 

Futures: در زبان هایی مثل C++, Java, Rust, Dlang و زمان اجرا هایی مثل OLSRT وجود داره! مثل Promise, میاد یک مقداری که در آینده محاسبه میشه رو نگه داری میکنه

مثلا فرض کنید من میخوام همزمان از روی دیسک بخونم, عملیات ۲+۲ رو انجام بدم و بعد اون ۲+۲ رو تقسیم بر ۴ کنم

Future بهتون میگه دیسک به من هیچ ربطی نداره! ولی ۲+۲ ماله خودمه!

۲+۲ رو میاد و یه جواب حدسی (مثلا ۳.۹۹۹۹ یا مثلا خوده ۴ و...) رو میگیره و پیش بینی میکنه, بعد بدون فوت وقت میره سراغ تقسیم ۲+۲ با ۴

اینجا ما هنوز جواب قطعی عه ۲+۲ رو نمیدونیم, پس مجبوریم بیایم و از اون پیشبینیه استفاده کنیم! ۲+۲ رو ۴ مثلا بدست آوردیم, میایم و تقسیم بر ۴ میکنیم, و بعد تموم میشه میره پی کارش!

وقتی جواب نهایی هم حاظر بشه (۲+۲), بهتون برمیگردونه و همه چیز اوکی میشه

 

اما در زمان اجرا های مدرنی مثل OLSRT, Node.js و Swoole, سیستم Promise & Futures باهم کار میکنن!

Futures پیش بینی میکنه و Promise وعده میده و میگه فعلا برو پی کارت!

وقتی حاظر بشه خودم برات انجام میدم!

 

حالا شما رسما معماری Poller, Event Loop, Async I/O, Promise, و Futures رو به خوبی درک میکنید! پس میریم سراغ انواع Poller ها!

 

۲- انواع Poller ها

خب ببینید, ما تعداد Poller هایی که داریم, ۱ ای و ۲ تا نیستن (ولی به ۲۶ نمیرسن!)

ما چندین Poller داریم که خب الان میخوام بهتون معرفی کنمشون!

 

۱- select (پدر جدن در جدن در جد Poller ها!):

این اولین استاندارد Poller ها بود که ریشش به POSIX (Linux, Unix, BSD, MacOS و...) میرسه!

مکانیزم: شما ۳ تا

fd_set

(fd_set: مجموعه توصیف گر فایل) میسازید:

یکی برای خوندن, یکی برای نوشتن, و یکی دیگه برای خطا ها

اشاره گری اون ۳ تا رو هم به هسته میدید

کارکرد: O(n)

بزرگترین مشکل: الگوریتم O(n) یعنی به ازای تمام فایل ها, سوکت ها, و... (که همون n میشن) کل لیست پیشمایش میشه!

یعنی کابوس محض!

فرض کنید! کل دیسکتون رو فقط برای اینکه ۱ فایل رو پیدا کنید و ببینید که آمادست یا نه باید پیمایش کنید!

محدودیت: تعداد فایل ها محدود به ۱۰۲۴ (یا FD_SETSIZE) هستش

Copy Memory (کپی کردن حافظه): هر بار که از "select" استفاده میکنید, آرایه ی (n) از فضای کاربر به هسته کپی میشه!

اگر ۱۰۰۰۰ تا سوکت داشته باشیم, هر بار کپی شدن حجم زیادی از CPU و پهنای باند حافظه رو هدر میده

 

۲- poll (بهتر, اما هنوز select!):

مکانیزم: به جای fd_set, یه آرایه از ساختار pollfd میفرستید

دیگه محدودیت ۱۰۲۴ تا رو نداره

کارکرد: O(n)

بزرگترین مشکل: الگوریتم O(n) یعنی به ازای تمام فایل ها, سوکت ها, و... (که همون n میشن) کل لیست پیشمایش میشه!

یعنی کابوس محض!

فرض کنید! کل دیسکتون رو فقط برای اینکه ۱ فایل رو پیدا کنید و ببینید که آمادست یا نه باید پیمایش کنید!

 

۳- epoll (انقلاب لینوکس!):

همونطوری که میدونید یا نمیدونید, قلب تپنده ی معماری های مدرن, همیشه از دو چیز اومده:

یا کرنله لینوکس, یا BSD

انقلاب لینوکس هم با epoll شروع شدش, با قابلیت Zero-Copy Memory!

epoll گفت چرا Poller باید توی Userspace باشه وقتی در هر صورت بازگشت همه به سوی هستست؟

مکانیزم:

epoll_create

یک فضای داخلی توی هسته میسازه (Red-Black Tree)

epoll_ctl

سوکت هارو یکبار اظافه/حذف میکنه

epoll_wait

هسته فقط لیست اونایی رو برمیگردونه که اتفاقی براشون افتاده باشه (Ready List)

کارکرد: O(1) یا O(k)

مشکل بزرگ: مهم نیست ۱۰ سوکت داشته باشید, ۲۶ تا, ۲۲۶ تا یا حتی ۲۶ تریلیارد سوکت, هزینه سربار epoll_wait برای همه ثابته!

 

۴- kqueue (انقلاب BSD!):

همونطوری که گفتم, خورشید (معماری های مدرن) از مشرق طلوع (لینوکس) و از مغرب غروب (BSD) میکنه!

BSD هم یه شاهکاری که انجام داد, kqueue بود که هنوز توی macOS (که یه سیستم عامل مبتنی بر Darwin (که خود Darwin یک سیستم عامل BSD-based هستش)) و iOS (مثل macOS اما برای موبایل با معماری ARM & ARM64) استفاده میشه!

kqueue فقط برای سوکت نبود؛ برای Event Queue عمومی هستش!

مکانیزم: شما یه فیلتر تعریف میکنی:

EVFILT_READ

وقتی داده اومد

EVFILT_TIMER

وقتی زمان تموم شد

EVFILT_SIGNAL

وقتی سیگنال اومد

EVFILT_PROC

وقتی پروسه مردش

شاهکار: توی لینوکس باید برای تایمر یه timerfd بسازین و اون رو به epoll اظافه کنین

توی kqueue تایمر قلبه Poller هستش

خیلی هم سبکه و کم هزینه (Low Overhead), ساختار داده ها توی هسته BSD برای همین کار بهینه سازی شدن

 

۵- IOCP (ورود ویندوز!):

ویندوز کلا متفاوت فکر میکردش

مکانیزم: شما درخواست I/O رو میدین و میرید دنبال ادامه ی ماجرا, وقتی کار تموم بشه هسته یه Completion Packet رو توی Queue قرار میده

شاهکار: Asyncronous واقعی بود, نه کیک

توی epoll و kqueue باید بپرسید: "هوییی, آمادست یا نه؟" (Reactive)

و توی IOCP, هسته بهت سیگنال میده میگه: "/bieh برای تو!" (Proactive)

مشکل بزرگ: پیچیدگی زیادی داره, اما سریعترین روش روی ویندوزه!

 

۶- IO_Uring (بازگشت همه به سوی لینوکس است!):

اما خب لینوکس همین شکلی دست بردار نیست!

لینوکس با IO_Uring که ترکیبی از IOCP و Kqueue بودش برمیگرده!

مکانیزم: دو صف (Queue), حافظه مشترک (Shared Memory) بین کاربر و هسته:

Submission Queue: شما درخواست هارو مینویسی

Completion Queue: هسته نتایج رو بهت میده

شاهکار: حتی نیاز به System Call هم نیست (مثل epoll_wait) و تا حد زیادی (با استفاده از mmap و ring buffer) اتوماتیک وار هستش!

قدرتمند ترین روش توی لینوکس, همینه!

 

مابقی Poller ها: استفاده از این Poller ها پیشنهاد نمیشه, اما بدونید کفایت میکنه (البته بعضی هاشون پیشنهاد میشه برای کار های خاص):

۱- /dev/poll (منسوخ شده؛ پدره epoll قبل از به وجود اومدنش؛ توسط Sun Microsystems (سازنده ی زبان برنامه نویسی Java و سیستم عامل Solaris)):

قبل از اینکه epoll بیادش, Sun Microsystems یه Poller ساخته بود به اسم /dev/poll

شما یه فایل دستگاه (Device (/dev/poll)) باز میکنین و با دستور write, روی اون لیست fd ها رو مینویسید و با ioctl یا read وضیعت رو میخونید

 

۲- Event Ports (نوآوری جدید Sun Microsystems برای سیستم عامل Solaris):

وقتی Solaris متوجه شد که دیگه /dev/poll بدرد نمیخوره, مکانیزم Event Ports رو جایگزین کرد که بسیار شبیه epoll / kqueue هستش

 

۳- WSAPoll

این همون poll در لینوکس هستش اما در دنیای ویندوز

POV: آخرین تلاش مایکروسافت برای اینکه بتونه بگه "چرا باید از ویندوز استفاده کنیم؟" LOL

 

۴- FIONREAD / SIOCATMARK

این یه Poller نیست به معنای واقعی, اما یه تکنیک هستش برای چک کردن وضیعت

 

۵- Signal Driven I/O (منسوخ)

این یه روش عجیب و قدیمی برای مدیریت I/O ها هستش

 

۶- AIO (POSIX AIO) - Asyncronous عه واقعی!

این تلاشی برای آوردن نوآوری های IOCP بود به دنیای یونیکس

اما خب در لینوکس فقط روی فایل ها خوب کار میکنه و روی سوکت ها کمتر

اما روی BSD خیلی بهتر کار میکنه ولی خب همچنان kqueue محبوب تره

 

۷- WaitSet / WaitOnAddress

این نرم افزاری نیست!‌ این برای سخت افزار ها و Hypervisor ها هستش

 

۸- DPDK (Data Plane Development Kit)

این حقش بود بره توی اصلی ها! DPDK سریعترین (سریعترین!) روش حال حاظر هستش برای I/O شبکه

نه یک Poller, بلکه یه انقلابه!

"چرا باید به هسته اجازه ی کنترل Poller رو بدیم, وقتی میتونیم کاری کنیم خود کارت شبکه مستقیم با برنامش ارتباط برقرار کنه؟!"

و اینجا بود DPDK با سرعت فعلی ۱۰۰ میلیون پکت در ثانیه ساخته شد!

 

و خب هم اکنون هم شما یه انیشتین در حوزه ی Poller ها هستین و میتونید Poller هارو توصیف کنید!

حالا بریم سراغ فریم ورک ها/لایبرری ها و زمان اجرا هایی که استفاده از Poller, Event Loop و Async I/O رو برای ما ساده تر میکنه!

 

۳- فریم ورک ها/لایبرری ها و زمان اجرا های استفاده از Poller, Event Loop و Async I/O

NetPoller (Golang): NetPoller به صورت پیشفرض در زبان Golang وجود داره

ویژگی: استفاده از Goroutines و CHannels, شما کد رو همزمان (Syncrnous) مینویسید, اما NetPoll به صورت خودکار اونارو Asyncronous اجرا میکنه

 

Project Loom (Java): جاوا قبلا از Thread های سنگین سیستم عامل استفاده میکرد, اما الان با Project Loom, ترد های سبز (Green Threads (نخ های سبکی که روی Userspace اجرا میشن)) رو اظافه کرد که روی Poller های بومی سوار میشن

 

ThreadPool (.NET): کلمات کلیدی async و await رو در خودش داره< در پشت صحنه با IOCP ویندوز و epoll عه لینوکس صحبت میکنه

 

libuv (C/C++): لیب یو وی قلب تپنده ی Node.js هستش, قدیمی, سنگین و به شدت کند

ولی یه لایه یکپارچه هستش روی epoll, kqueue, IOCP و WSAPoll

 

Boost:AsIO (Boost Async I/O) (C++ Only): کتابخونه ی قدرتمند اما سنگین برای C++, مدل Proactor هستش, بسیار پیچیده و انعطاف پذیر, پایه بسیاری از سرور های C++

 

libev (C/C++): قدیمی تر از libuv اما سبک تر و ساده تر

در TOR (The Onion Routing) و Memcached (یک دیتابیس In-Memory) استفاده شده

 

Tokio (Rust): استاندارد غیر رسمی Rust برای Async, استفاده از mio (Poller) و async-std (Rust), از IOCP, epoll و kqueue پشتیبانی میکنه

 

OLSRT (تمام زبان های برنامه نویسی!): OLSRT جدیدترین زمان اجرا هستش برای استفاده از Modern Concurrency (Async, Await, Actor, Coroutines, ORoutines, Fibers), Syncronization (Locks, Mutexes, Semaphores, Supervisors), Reactive/Dataflow (Stream-based Programming, Pipelines), I/O Scheduling (Event Loop, Poller (epoll, select, kqueue), Deadlines), Composability (Futures, Promises, Parallel Execution) به صورت All-in-ONE!

در حال حاظر, شما میتونید از GitHub دانلود و ازش استفاده کنید! (استار یادتون نره بلا ها!)

 

خلاصه ی ماجرا هم همین بودش! تقدیم به علاقه مندان به Modern Concurrency!

امیدوارم لذت برده باشید و شب و روز بر شما خوش باشه!

خدایار, و نگهدارتون باشه!

 

Just Programming

لینک به دیدگاه
https://forum.arsacia.ir/topic/107266-poller-event-loop-asyncronous-programming/
به اشتراک گذاری در سایت های دیگر

مشتی اینقدر طولانی مینویسی هیچکس حوصلش نمیکشه بخونه ولی دمت گرم که انقدر وقت میذاری سر اینجوری چیزا واقعا دستت درد نکنه😂❤️

  DrunkeN.png

 

Desimon.png

لینک به دیدگاه
https://forum.arsacia.ir/topic/107266-poller-event-loop-asyncronous-programming/#findComment-1111670
به اشتراک گذاری در سایت های دیگر

هم اکنون، AmirMamad گفته است:

مشتی اینقدر طولانی مینویسی هیچکس حوصلش نمیکشه بخونه ولی دمت گرم که انقدر وقت میذاری سر اینجوری چیزا واقعا دستت درد نکنه😂❤️

عشقی عمو امیر  ❤️

دیگه والا گفتیم یا شروع نکنیم یا شروع میکنیم کامل توضیح بدیم دیگه که نتیجشم شدش این تاپیک دیگه  😂❤️

Just Programming

لینک به دیدگاه
https://forum.arsacia.ir/topic/107266-poller-event-loop-asyncronous-programming/#findComment-1111772
به اشتراک گذاری در سایت های دیگر

اسم Async رو نیار که دلم خونه 💔

The only things making you unhappy are your own thoughts

لینک به دیدگاه
https://forum.arsacia.ir/topic/107266-poller-event-loop-asyncronous-programming/#findComment-1114578
به اشتراک گذاری در سایت های دیگر

5 ساعت قبل، MohammadAli گفته است:

اسم Async رو نیار که دلم خونه 💔

ای بابا یه دیتابیس بود دیگه حالا 😂

Just Programming

لینک به دیدگاه
https://forum.arsacia.ir/topic/107266-poller-event-loop-asyncronous-programming/#findComment-1115067
به اشتراک گذاری در سایت های دیگر

برای ارسال دیدگاه یک حساب کاربری ایجاد کنید یا وارد حساب خود شوید

برای اینکه بتوانید دیدگاهی ارسال کنید نیاز دارید که کاربر سایت شوید

ایجاد یک حساب کاربری

برای حساب کاربری جدید در سایت ما ثبت نام کنید. عضویت خیلی ساده است!

ثبت نام یک حساب کاربری جدید

ورود به حساب کاربری

دارای حساب کاربری هستید؟ از اینجا وارد شوید

ورود به حساب کاربری
  • کاربران آنلاین در این صفحه   0 کاربر

    • هیچ کاربر عضوی، در حال مشاهده این صفحه نیست.
×
×
  • اضافه کردن...