手寫代碼-epoll的內(nèi)核實(shí)現(xiàn)
一、內(nèi)核實(shí)現(xiàn)基礎(chǔ)
和之前的select相比,epoll是一個(gè)目標(biāo)性更強(qiáng)的實(shí)現(xiàn)。在epoll等待的時(shí)候,它會把每個(gè)poll的喚醒函數(shù)注冊為自己特有的函數(shù),在該回調(diào)函數(shù)中,它將自己(被喚醒的fd)添加到readylist中,然后在poll到底是什么事件的時(shí)候只檢測在readylist中的描述符即可,而不是像select一樣遍歷所有的描述符集合進(jìn)行遍歷。大致原理即是如此
二、代碼中實(shí)現(xiàn)簡單說明
這里最為莫名其妙的就是這個(gè)ep_reinject_items,把事件返回給用戶態(tài)之后,此時(shí)它會把所有的已經(jīng)發(fā)送的事件再次放入readylist,此時(shí)是不是不太符合常規(guī)呢?而這一點(diǎn)也是之前比較讓我費(fèi)解的一個(gè)地方。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)??


三、為什么再次注入
這個(gè)要和最開始說的epoll實(shí)現(xiàn)來看。對于select來說,它每次執(zhí)行的時(shí)候都會進(jìn)行一次遍歷,這樣假設(shè)說select返回之后,用戶態(tài)對這個(gè)事件充耳不聞,或者其它異常情況沒有處理這個(gè)事件,那么沒關(guān)系,再次進(jìn)入select的時(shí)候內(nèi)核不辭勞苦的又poll了一遍,如果沒有處理,狀態(tài)依然存在。 而對于epoll來說,它的此次狀態(tài)變化事件執(zhí)行機(jī)會在于事件發(fā)生的時(shí)候,如果epoll只是簡單的將事件發(fā)送給用戶態(tài)之后就從ready隊(duì)列中刪除該項(xiàng),如果用戶態(tài)沒有處理該event事件,那么再次執(zhí)行epoll_wait的時(shí)候?qū)G失這次事件,直到有下一個(gè)事件發(fā)生并再次執(zhí)行喚醒檢查時(shí)才會喚醒用戶態(tài)進(jìn)程。這也是和select優(yōu)化的代價(jià)。
四、再次進(jìn)入內(nèi)核wait
五、文件等待隊(duì)列
和select的等待隊(duì)列每次進(jìn)入時(shí)創(chuàng)建并添加不同,epoll的等待事件創(chuàng)建之后一直不會被刪除,直到epoll_create返回的主文件被刪除
或者epoll_ctl中EPOLL_CTL_DEL命令刪除該關(guān)注項(xiàng)。
六、TODO
內(nèi)核調(diào)試態(tài)驗(yàn)證以上描述。
