




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
的。希望能給學(xué)習(xí)和使用libevent的朋友們有所幫助。 序 前 小 三基本使用場景和流 前 實(shí)例代 4處理流 5小 四libevent源代碼文件組 前 小 五libevent的: 3設(shè)置的接口函 4小 六初見處理框 1處理框架- 接口函 小 七主循 2處理主循 I/O和Timer的統(tǒng) I/O和Signal的統(tǒng) 小 八集成信號處 集成策略——使用socket 5、注銷signal................................................................................................小 九集成定時器....................................................................................................................... 小 十支持I/O多路復(fù)用技 小 十一時間管 時間緩 時間校 小 十二讓libevent支持多線 例子—— 小 前Libevent是一個輕量級的開源高性能網(wǎng)絡(luò)庫,使用者眾多,研究者更甚,相關(guān)文章也不不函數(shù)指針,學(xué)習(xí)其源代碼也需要相當(dāng)?shù)腸語言基礎(chǔ)。上來當(dāng)然要先夸獎啦,Libevent有幾個顯著的亮點(diǎn):drivenI/Oepoll、poll、dev/poll、selectkqueue等;支持I/O,定時器和信號等;libevent有助于提升程序設(shè)計(jì)功力,除了網(wǎng)絡(luò)程序設(shè)計(jì)方面外,Libevent的代碼里libevent本身的框架大概了解,那或許僅僅是一知半解,不深入代碼分析,就難以了解其設(shè)LibeventReactorReactorLibevent:前面講到,整libevent本身就是一Reactor,因此本節(jié)將專Reactor模式進(jìn)行必要libevnetReactor的對應(yīng)關(guān)系,在后面的章節(jié)中可能還 的處理機(jī)序不是主動的調(diào)用某個API完成處理,而是恰恰相反,Reactor逆置了處理流程,應(yīng)用用程序的接口,這些接口又稱為“回調(diào)函數(shù)”。使用Libevent也是想Libevent框架相應(yīng)的和回調(diào)函數(shù);當(dāng)這些時間時,Libevent會調(diào)用這些回調(diào)函數(shù)處理相應(yīng)的(I/O讀寫、定時和信號程序,先來看看Reactor模型的整體框架,接下來再對每個組件做逐一說明。源Linux上是文件描述符,WindowsSocketHandle了,這里統(tǒng)一稱為“句柄當(dāng)有到達(dá)時,eventdemultiplexer會發(fā)出通知“在已經(jīng)的句柄集中,一個或多Reactor,是管理的接口,eventdemultiplexer、注銷;并運(yùn)行事class{ intregister_handler(Event_Handler*pHandler,int intremove_handler(Event_Handler*pHandler,int voidhandle_events(timeval //classclass{ virtualvoidhandle_read()= virtualvoidhandle_write()= virtualvoidhandle_timeout()=virtualvirtualvoidhandle_close()=0;virtualHANDLEget_handle()= //class{ //eventsmayberead/write/timeout/close virtualvoidhandle_events(intevents)= virtualHANDLEget_handle()= //前面Reactor將流“逆置”了,那么使用Reactor模式后,控制流是什么小Pattern-OrientedSoftwareArchitecture,PatternsforConcurrentandNetworkedObjects,Volume三基本使用場景和流前是個不錯的方法,至少從個人的經(jīng)驗(yàn)上講,用此方法分析libevent是比較有效的?;緫?yīng)用場景基本應(yīng)用場景也是使用 structevent_base*base=evtimer_set(&ev,timer_cb,NULL);voidevent_set(structeventvoidevent_set(structevent*ev,intfd,shortevent,voidshort,void*),voidfd:該event綁定的“句柄”,對于信號,它就是關(guān)注的信號event:在該fd上關(guān)注的類型,它可以是EV_READ,EV_WRITE,EV_SIGNAL;調(diào)用時由event_base負(fù)責(zé)傳入,按順序,實(shí)際上就是event_set時的fd,eventarg;arg:傳遞給cb函數(shù)指針的參數(shù);由于定件不需要fd,并且定件是根據(jù)添加時(event_add)的超時值設(shè)定的,因此這里event也不需要設(shè)置。注意:libevent并不會管理event集合,這需要應(yīng)用程序自行管理;event_base_set(base,&ev);event_add(&ev,voidtime_cb(voidtime_cb(intfd,shortevent,void{printf("timerstructeventstructeventev;structtimevaltv;event_add(&ev,&tv);event_add(&ev,&tv);//reschedule}int{ structevent_base*base= tv.tv_sec=10;//10s tv.tv_usec= evtimer_set(&ev,time_cb, event_add(&ev, }4處理流當(dāng)應(yīng)用程序向libevent一個后,libevent內(nèi)部是怎么樣進(jìn)行處理的呢?下面的2向libevent添加該event。對于定件,libevent使用一個小根堆管理,key為超時時間;對于Signal和I/O,libevent將其放入到等待鏈表(waitlist)中,這是一每次循環(huán)前l(fā)ibevent會檢查定件的最小超時時間tv,根據(jù)tv設(shè)置select()的最大等5本節(jié)介紹了libevent的簡單實(shí)用場景,并旋風(fēng)般的介紹了libevent的處理流程,讀式中的Reactor框架)做詳細(xì)的介紹,在此之前會對源代碼文件做簡單的分類。libevent源代碼文件前源代碼組織結(jié)構(gòu)頭文件、的頭文件、輔助功能函數(shù)、日志、libevent框架、對系統(tǒng)I/O多路復(fù)用機(jī)3)libevent框架event.c:event整體框架的代碼實(shí)現(xiàn);4)對系統(tǒng)I/O多路復(fù)用機(jī)制的封裝epoll.c:對epoll的封裝;select.c:對select的封裝;devpoll.c:對dev/poll的封裝;kqueue.c:對kqueue的封裝;evutil.hevutil.csocketpair和一些時間操作函數(shù):加、減小五libevent的:libevent對event的管理。event就是Reactor框架中的處理程序組件;它提供了函數(shù)接口,供Reactor在發(fā)生structevent TAILQ_ENTRY(event)TAILQ_ENTRYTAILQ_ENTRY(event)ev_active_next;TAILQ_ENTRY(event) unsignedintmin_heap_idx;/*formanagingtimeouts structevent_base intshortshortev_events;short short /*Allowsdeletesincallbackvoid(*ev_callback)(intvoid(*ev_callback)(int,short,voidint /*smallernumbersarehigherpriority void int /*resultpassedtoeventcallback intevent關(guān)注的類型,它可以是以下3種類型:I/O: 輔助選項(xiàng):EV_PERSIST,表明是一個永久#defineEV_WRITE#defineEV_WRITE0x04#defineEV_SIGNAL#defineEV_TIMEOUT #define #define /*Persistantevent可以看出類型可以使用“|”運(yùn)算符進(jìn)行組合,需要說明的是,信號和I/O不能同還可以看出libevent使用event結(jié)構(gòu)體將這3種的處理統(tǒng)一起來;2)ev_next,ev_active_next和ev_signal_next都是雙向鏈表節(jié)點(diǎn)指針;它們是libevent對不同類型和libevent使向鏈表保存所有的I/O和Signal,ev_next就是該I/O在鏈表中ev_active_next:libevent將所有的激活放入到鏈表activelist中,然后遍歷activelist執(zhí)行調(diào)度,ev_active_next就指明了eventactivelist中的位置;2)min_heap_idx和ev_timeout,如果是timeout,它們是event在小根堆中的索引和超時值,libevent使用小根堆來管理定件,這將在后面定件處理時專門講解3)ev_base該所屬的反應(yīng)堆實(shí)例,這是一個event_base結(jié)構(gòu)體,下一節(jié)將會詳細(xì)講解;4)ev_fd,對于I/O,是綁定的文件描述符;對于signal,是綁定的信號;5)ev_callback,event的回調(diào)函數(shù),被ev_base調(diào)用,執(zhí)行處理程序,這是一個函數(shù)指void(*ev_callback)(intfd,shortevents,void其中參數(shù)fd對應(yīng)于ev_fd;events對應(yīng)于ev_events;arg對應(yīng)于ev_arg;6)ev_arg:void*,表明可以是任意類型的數(shù)據(jù),在設(shè)置event時指定;7)eb_flags:libevent用于標(biāo)記event信息的字段,表明其當(dāng)前的狀態(tài),可能的值有:#define 0x01//event在time堆中#defineEVLIST_INSERTED0x02//event在 鏈表#define 0x04#defineEVLIST_ACTIVE 0x08//event在激活鏈表中#defineEVLIST_INTERNAL0x10// #defineEVLIST_INIT 0x80//event已被初始化9)ev_pncalls:指針,通常指向ev_ncalls或者為NULL;10)libeventevent處理;并根據(jù)就緒的句柄和類型填充cb_callback函數(shù)的參數(shù)。3設(shè)置的接口函voidevent_set(structevent*ev,intfd,shortevents,void(*callback)(int,short,void*),voidevent_set(structevent*ev,intfd,shortevents,void(*callback)(int,short,void*),void intevent_base_set(structevent_base*base,structevent設(shè)置eventev將要到的libevent有一個全局event_base指針current_base,默認(rèn)情況下置不同的event_base;intevent_priority_set(structevent*ev,int小六初見處理框刪除的具體流程,可結(jié)合前一節(jié)libevent對event的管理。1處理框架-structevent_basestructevent_base conststructeventop void int /*countsnumberoftotalevents intevent_count_active;/*countsnumberofactiveevents int /*Settoterminateloop/*Settoterminateloopinty/*Settoterminateloopint /*activeeventmanagement structevent_list int /*signalhandlinginfo structevsignal_info structevent_list structtimeval structmin_heap structtimevalevsel和evbase這兩個字段的設(shè)置可能會讓人有些迷惑,這里你可以把evsel和evbase看作是類和靜態(tài)函數(shù)的關(guān)系,比如添加時的調(diào)用行為:evsel->add(evbase,ev),evbase;這相當(dāng)class::add(instance,ev),instanceclass的一個對象實(shí)例。evsel指向了全局變量staticconststructeventop*eventops[]中的一個;evbase實(shí)際上是一個eventop實(shí)例對象,structeventopconstcharvoid*(*init)(structevent_base*); int int(*add)(void*,structevent*);int(*del)(void*,structevent*);int(*dispatch)(structevent_base*,void*,structtimeval*); void(*dealloc)(structevent_base*,void*); /*setifweneedtoreinitializetheeventbase intepoll,libevent5eventop55epollI/Odemultiplex機(jī)制了,這個看作是數(shù)組,其中的元素activequeues[priority]是一個鏈表,鏈表的每個節(jié)點(diǎn)指向一個優(yōu)先級為priority的就緒event。timeheap是管理定件的小根堆,將在后面定件處理時專門講解;6)event_tv和tv_cache是libevent用于時間管理的變量,將在后面講到;創(chuàng)建和初始化創(chuàng)建一個event_base對象也既是創(chuàng)建了一個新的libevent實(shí)例,程序需要通過調(diào)用event_init()(event_base_new函數(shù)執(zhí)行具體操作)函數(shù)來創(chuàng)建,該函數(shù)同時還對新生成的libevent實(shí)例進(jìn)行了初始化。該函數(shù)event_base實(shí)例申請空間,然后初timermini-heap,選擇并初始化合適的系統(tǒng)I/O的demultiplexer機(jī)制,初始化各鏈表;。intevent_add(structevent*ev,conststructtimeval*timeout);intevent_del(structevent*ev);intevent_base_loop(structevent_base*base,intloops);voidevent_active(structevent*event,intres,shortevents);voidevent_process_active(structevent_base*base);本節(jié)將按介紹和刪除的代碼流程,libevent的循環(huán)框架將在下一節(jié)再具體1)intevent_add(structevent*ev,conststructtimeval函數(shù)將ev到ev->ev_base上,類型由ev->ev_events指明,如果成功,ev將入到已鏈表中;如果tv不是NULL,則會同時定件,將ev添加到timerintevent_add(structevent*ev,conststructtimeval{structevent_base*base=ev->ev_base;// 到的conststructeventop*evsel=base-void*evbasebase->evbase;base使用的系統(tǒng)I/O//新的 ,調(diào)用timerheap接口在堆上預(yù)留一個位//向系統(tǒng)I/O機(jī) // if(tv!=NULL&&!(ev->ev_flags&EVLIST_TIMEOUT)) if(min_heap_reserve(&base- 1+min_heap_size(&base->timeheap))==- return(-1);/*ENOMEM==errno//如 ev不在 或者激活鏈表中,則調(diào)用if((ev->ev_events&(EV_READ|EV_WRITE|EV_SIGNAL)) !(ev->ev_flags&(EVLIST_INSERTED|EVLIST_ACTIVE))) res=evsel->add(evbase, if(res!=-1)// event_queue_insert(base,ev,//準(zhǔn)備添加 if(res!=-1&&tv!=NULL){structtimevalnow; EVLIST_TIMEOUT表明event if(ev->ev_flags& event_queue_remove(base,ev,evutil_timeraddevutil_timeradd(&now,tv,&ev-event_queue_insert(base,ev,if((ev->ev_flags&EVLIST_ACTIVE)&&(ev->ev_res&EV_TIMEOUT)){//將ev_callback調(diào)用次數(shù)設(shè)置為if(ev->ev_ncalls&&ev->ev_pncalls)*ev->ev_pncalls=}event_queue_remove(base,ev,}gettime(base, return} voidevent_queue_insert(structevent_base*base,structevent*ev,intqueue){evif(ev->ev_flags&queue) if(queue& //ev->ev_flags|=queue;queueswitch(queue)caseEVLIST_INSERTED://I/O或 ,加入 鏈 TAILQ_INSERT_TAIL(&base->eventqueue,ev, caseEVLIST_ACTIVE://就 base- TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],ev, caseEVLIST_TIMEOUT:// 件,加入 min_heap_push(&base->timeheap, }2)刪除函數(shù)原型為:intevent_del(structeventintevent_del(structevent{structevent_baseconststructeventopvoid//ev_base為NULL,表明ev沒有 if(ev->ev_base== return(-//取得 base=ev-evsel=base-evbase=base-ev_callbackif(ev->ev_ncalls&&ev->ev_pncalls) *ev->ev_pncalls=if(ev->ev_flags& event_queue_remove(base,ev,if(ev->ev_flags& event_queue_remove(base,ev,if(ev->ev_flags&EVLIST_INSERTED) event_queue_remove(base,ev, //EVLIST_INSERTED表明是I/O或者 I/Odemultiplexer return(evsel->del(evbase,return}小裝event_op結(jié)構(gòu),并結(jié)合源代碼分析了的和刪除處理,下面將會接著分析管理框架中的主循環(huán)部分。七主循階段性的勝利Libevent將I/O、定時器和信號處理很好的結(jié)合到了一起,本節(jié)也會介在看完本節(jié)的內(nèi)容后,讀者應(yīng)該會對Libevent的基本框架:管理和主循環(huán)有比較2處理主循圖所示,event_base_loop所作的就是持續(xù)執(zhí)行下面的循環(huán)。intevent_base_loop(structevent_baseintevent_base_loop(structevent_base*base,int{conststructeventop*evsel=base-structstructtimevalstructtimevalvoid*evbase=base-intres, base->tv_cache.tv_sec= evsignal_base是全局變量,在處理signal時,用于指名signal所屬的 if(base-done=done=while(!done) event_base_loopbreak()設(shè)置event_break if(base->event_gotterm) base->event_gotterm= if(base->event_break) base->event_break= MONOTONIC時間,用戶可能會向 timeout_correct函數(shù)里,比較lastwaittime和當(dāng)前時間,如果當(dāng)前時間<lastwaittime //表明時間有問題,這是需要更新timer_heap中所有定 timeout_correct(base, //根據(jù)timer //根據(jù)timerheap tv_p= if(!base->event_count_active&&!(flags&EVLOOP_NONBLOCK)) timeout_next(base, }else I/Odemultiplexer //下面會提到,在libevent中,低優(yōu)先級的就緒 if(!event_haveevents(base)) event_debug(("%s:noeventsregistered.",func return lastwaittime,并清空timecachegettime(base,&base->event_tv); base->tv_cache.tv_sec= I/Odemultiplexer等待就緒I/Oevents, res=evsel->dispatch(base,evbase, if(res==- return(- timecache gettime(base,&base- heap中的timerevents,將就緒的timerevent從heap上刪除, //該函數(shù)會尋找最高優(yōu)先級(priority值越小優(yōu)先級越高)的激活 //然后處理鏈表中的所有就 //因此低優(yōu)先級的就 if(base->event_count_active) if(!base->event_count_active&&(flags& done= }elseif(flags& done=base->tv_cache.tv_sec=I/O和Timer的統(tǒng)Libevent將Timer和Signal都統(tǒng)一到了系統(tǒng)的I/O的demultiplex機(jī)制中了,相信首先將Timer融合到系統(tǒng)I/O多路復(fù)用機(jī)制中,還是相當(dāng)清晰的,因?yàn)橄到y(tǒng)的I/O機(jī)制像select()和epoll_wait()都允許程序制定一個最大等待時間(也稱為最大超時時間)timeout,即使沒有I/O發(fā)生,它們也保證能在timeout時間內(nèi)返回。那么根據(jù)所有Timer的最小超時時間來設(shè)置系統(tǒng)I/O的timeout時間;當(dāng)系統(tǒng)I/O返回時,再激活所有就緒的Timer就可以了,這樣就能將Timer完美的融合到系統(tǒng)的I/O機(jī)制中了。這是ReactorProactor模式(主動器模式WindowsIOCP)中Timer的經(jīng)典方法了,ACE采用的也是這種方法,大家可以參考POSAvol2ReactorO(lgN),N為堆中元素的個數(shù),而獲取最小key值(小根堆)的復(fù)雜度為O(1);因此變成了管理Timer的絕佳人選(當(dāng)然是非唯一的,libevent就是采用的堆結(jié)構(gòu)。I/O和Signal的統(tǒng)Signal是異步的經(jīng)典事例,將Signal統(tǒng)一到系統(tǒng)的I/O多路復(fù)用中就不像Timer那么自然了,Signal的出現(xiàn)對于進(jìn)程來講是完全隨機(jī)的,進(jìn)程不能只是測試一個變Signalevent的callback函數(shù)處理信號,而是設(shè)法通知系統(tǒng)的I/O機(jī)制,讓其返回,然后再統(tǒng)一和I/O以及Timer一起處理,不就可以了嘛。是的,這也是libevent中使用的方法。問題的在于,當(dāng)Signal發(fā)生時,如何通知系統(tǒng)的I/O多路復(fù)用機(jī)制,這里先買個小小介紹了libevent的主循環(huán),描述了libevent是如何處理就緒的I/O、定時器和信號,以及如何將它們無縫的融合到一起。成信號處現(xiàn)在我們已經(jīng)了解了libevent的基本框架:管理框架和主循環(huán)。上節(jié)提到了libevent中I/O和Signal以及Timer的集成,這一節(jié)將分析如何將Signal集成到事集成策略——使用socket通過socketpair完成的,下面就來詳細(xì)分析一下。Socketpairsocketsocketsocketsocket。工作集成到主循環(huán)——通知Socketpair創(chuàng)建好了,可是libevent的主循環(huán)還是不知道Signal是否發(fā)生了啊,看來我們還差了最后一步,那就是:為socketpair的讀socketlibeventevent_base實(shí)例上一個persist的讀。前面提到過,Libevent會在主循環(huán)中檢查標(biāo)記,來確定是否有觸發(fā)的signal,如果標(biāo)記被設(shè)置就處理這些signal,這段代碼在各個具體的I/O機(jī)制中,以Epoll為例,在 if(res==-1) if(errno!=EINTR) evsignal_process(base); evsignal_process(base); return }elseif(base->sig.evsignal_caught){evsignal_process(base); 注1:libevent中,初始化階段并不讀socket的讀,而是在信號階段才會測試并注2:libevent中,檢查I/O是在各系統(tǒng)I/O機(jī)制的dispatch()函數(shù)中完成的,該dispatch()函數(shù)在volatilesig_atomic_tvolatilesig_atomic_tintintstructeventstructevsignal_info structevent_list #ifdefHAVE_SIGACTION structsigaction**sh_old; ev_sighandler_t intev_signal_added,記錄ev_signal是否已經(jīng)了evsignal_caughtvolatile類型,因?yàn)樗鼤诹硗獾木€程中被evsigvents[NSIG],數(shù)組,evsigevents[signo]表示到信號signo的鏈表;6)sh_old記錄了原來的signal處理函數(shù)指針,當(dāng)信號signo的event被清空時,需要重是等到有信號時才檢查并,并將所有標(biāo)記置零,初始化信號的鏈表指針5、注銷signalsignal是通過evsignal_add(structevent*ev)函數(shù)完成的,libevent對所有的信號同一個處理函數(shù)evsignal_handler(),該函數(shù)將在下一段介紹,過程如下:取得ev要到的信號如果ev_signal還沒喲,就ev_signal將ev添加到signo的event鏈表中staticvoidstaticvoidevsignal_handler(int{intsave_errnoerrno;func,event_warn("%s:receivedsignal%d,buthavenobaseif(evsignal_base==NULL) sig的觸發(fā)次數(shù),并設(shè)置eventevsignal_base-evsignal_base->sig.evsignal_caught=1;#ifndefHAVE_SIGACTIONsignal(sig,evsignal_handler);//重 send(evsignal_base->sig.ev_signal_pair[0],"a",1,errnosave_errno;}小成定時現(xiàn)在再來詳細(xì)分析libevent中I/O和Timer的集成,與Signal相比,Timer事集成到主循為最大超時時間)timeout,即使沒有I/O發(fā)生,它們也保證能在timeout時間內(nèi)返回。那么根據(jù)所有Timer的最小超時時間來設(shè)置系統(tǒng)I/O的timeout時間;當(dāng)系統(tǒng)I/O的I/O機(jī)制中了。if(!base->event_count_active&&!(flags&EVLOOP_NONBLOCK))//根據(jù)//根據(jù) timeout_next(base, }else // ////調(diào)用select()orepoll_wait()等待就緒 res=evsel->dispatch(base,evbase, // {structtimevalstructeventstructtimeval*tv= if((ev=min_heap_top(&base->timeheap))==NULL) *tv_p=returnreturnif(evutil_timercmp(&ev->ev_timeout,&now,<=))gettime(base,}return return evutil_timersub(&ev->ev_timeout,&now,Libevent使用堆來管理Timer,其key值就是的超時時間,源代碼位于文O(lgN),N為堆中元素的個數(shù),而獲取最小key值(小根堆)的復(fù)雜度為O(1)。堆是一個完全Libevent實(shí)現(xiàn)的堆還是比較輕巧的,雖然我不喜歡這種編碼方式(搞一些復(fù)雜的表達(dá)Heap[size++]Heap[size++]new;//先放到數(shù)組末尾,元素個數(shù)//_child=size;while(_child>0循環(huán){_parent(_child-1)/2;//計(jì)算parentif(Heap[_parent].keyHeap[_child].key)break;//調(diào)整結(jié)束,跳出循環(huán)swap(_parent,_child//parent}libeventheap代碼對這一過程做了優(yōu)化,在插入新元素時,只是為新元素預(yù)留了一個位置hole(初始時hole位于數(shù)組尾部),但并不立刻將新元素插入到hole上,而是不斷向holehole就是新元素的所在位置時,才會真正hole上,因此在調(diào)整過程中就比上面的代碼少了一次賦值的操作,代碼while(_hole>0//{_parent_hole-1)/2;parentif(Heap[_parent].key<new.key)break;_hole_parent;//將_hole調(diào)整到}//size++;//元素個數(shù)數(shù)是min_heap_shift_down_()。3,5,8,7,122,使用第一中典型的代碼邏輯,小十支持I/O多路復(fù)用提到過,它的成員是一系列的函數(shù)指針,定義在event-internal.h文件中:intint(*add)(void*,structevent*);int(*del)(void*,structevent*);void*(*init)(structevent_base*);constcharstructeventopint(*dispatch)(structevent_base*,void*,structint(*dispatch)(structevent_base*,void*,structtimeval*); /*setifweneedtoreinitializetheeventbase int/*Inorderofpreferencestaticconststructeventop*eventops[]{#ifdef&evportops,#ifdef&kqops,#ifdef#ifdef#ifdef#ifdef#ifdef #ifdefWIN32 在函數(shù)event_base_new()中: base->evbase= for(i=0;eventops[i]&&!base->evbase;i++) base->evsel= base->evbase=base->evsel- 可以看出,libeventI/Odemultiplex機(jī)制,而不支持在運(yùn)行階段conststructeventopepollops=1/*needreinitstaticvoid*epoll_init(structevent_basestaticstaticintepoll_add(void*,structevent*);staticintepoll_del(void*,structeventstaticintepoll_dispatch(structevent_base*,void*,structtimevalstaticvoid (structevent_base*,void那么如果選擇的是epoll,那么調(diào)用結(jié)構(gòu)體eventop的init和dispatch函數(shù)指針時,實(shí)際調(diào)用的函數(shù)就是epoll的初始化函數(shù)epoll_init()和分發(fā)函數(shù)epoll_dispatch()了;.aspx.aspx同樣的epollopsepoll的各種函數(shù)都直接定義在epoll.c源文件中,對外都是libeventepoll的使用也是通過eventop來完成的,達(dá)到了信息隱藏的目的。小間管staticvoid{staticvoid{#ifdefined(HAVE_CLOCK_GETTIME)&&struct if(clock_gettime(CLOCK_MONOTONIC,&ts)== use_monotonic1;monotonic時間}Monotonic時間指示的是系boot后到現(xiàn)在所經(jīng)過的時間,如果Monotonic時間就將全局變量use_monotonic設(shè)置為1,設(shè)置use_monotonic到底有什么用,這個在后面說結(jié)構(gòu)event_basetv_cache,用來記錄時間緩存。這個還要從函gettime()說起,先
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 分手賠償合同樣本
- 基于同態(tài)加密的數(shù)據(jù)安全檢索技術(shù)研究
- 公司 兼職會計(jì) 合同標(biāo)準(zhǔn)文本
- 個人分贓合同標(biāo)準(zhǔn)文本
- 東莞危化品貨運(yùn)合同樣本
- 做快遞員合同樣本
- 保安銷售賣房合同范例
- 個人介紹合同標(biāo)準(zhǔn)文本標(biāo)準(zhǔn)文本
- 倉庫作業(yè)合同標(biāo)準(zhǔn)文本
- 專升本自考試題及答案
- GB/T 13452.2-2008色漆和清漆漆膜厚度的測定
- 醫(yī)療器械經(jīng)營公司-年度培訓(xùn)計(jì)劃表
- 校園青年志愿者培訓(xùn)(服務(wù)禮儀講解)
- 【泉州南音傳承與發(fā)展研究(論文7200字)】
- 教練員教學(xué)質(zhì)量信譽(yù)考核表
- 《馬克思主義發(fā)展史》第五章 馬克思列寧主義在蘇聯(lián)的發(fā)展及曲折
- 現(xiàn)代漢語詞匯學(xué)精選課件
- 酒店工程部維修工作單
- 軍考哲學(xué)知識點(diǎn)
- 2023版北京協(xié)和醫(yī)院重癥醫(yī)學(xué)科診療常規(guī)
- 化學(xué)實(shí)驗(yàn)熔點(diǎn)測定
評論
0/150
提交評論