国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件

這篇具有很好參考價值的文章主要介紹了基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

文件描述符處理與回調(diào)函數(shù)

一、主要概念

  1. 反應(yīng)堆模型:一種處理系統(tǒng)事件或網(wǎng)絡(luò)事件的模型,當(dāng)文件描述符被激活時,可以檢測到
  2. 文件描述符:在操作系統(tǒng)中,用于標(biāo)識打開的文件、套接字等的一種數(shù)據(jù)類型?
  3. 處理激活的文件描述符的函數(shù):當(dāng)文件描述符被激活時,需要有一個函數(shù)來處理這些事件
  4. dispatch函數(shù):用于分發(fā)或處理不同類型事件的函數(shù)
  5. channel結(jié)構(gòu)體:存儲與文件描述符相關(guān)的事件處理動作的結(jié)構(gòu)體
  6. 回調(diào)函數(shù):在初始化channel對象時指定的讀回調(diào)和寫回調(diào),用于處理不同類型的事件
  7. select函數(shù):用于檢測多個文件描述符的狀態(tài),看是否有數(shù)據(jù)可讀可寫
  8. fd_set集合:用于存儲文件描述符的集合,通過宏函數(shù)FD_ISSET判斷文件描述符是否被觸發(fā)

二、處理流程

  1. 當(dāng)反應(yīng)堆模型啟動,檢測到被激活的文件描述符
  2. 調(diào)用dispatch函數(shù),得到文件描述符fd
  3. 根據(jù)fdchannelMap中取出對應(yīng)的channel,判斷是讀事件還是寫事件
  4. 調(diào)用對應(yīng)的回調(diào)函數(shù),處理事件
  5. select函數(shù)中,通過fd_set集合判斷是否有數(shù)據(jù)可讀可寫,調(diào)用eventActivate函數(shù)處理事件
  6. epoll函數(shù)中,通過epoll_wait進(jìn)行檢測,遍歷返回的events數(shù)組,調(diào)用eventActivate函數(shù)處理事件
  7. poll函數(shù)中,通過poll進(jìn)行檢測,遍歷返回的事件列表,調(diào)用eventActivate函數(shù)處理事件

三、注意事項

  • 在調(diào)用回調(diào)函數(shù)時,需要傳入注冊時指定的參數(shù)
  • 在使用回調(diào)函數(shù)時,需要注意處理函數(shù)的參數(shù)和返回值

四、概括

  • 本文主要介紹了在EventLoop中處理被激活的文件描述符的事件和回調(diào)機(jī)制
  • 當(dāng)反應(yīng)堆模型啟動時,可以檢測到被激活的文件描述符,并使用dispatch函數(shù)獲取文件描述符。(EventLoop初始化和啟動)
  • 根據(jù)文件描述符ChannelMap中取出對應(yīng)的channel,判斷是讀事件還是寫事件,并調(diào)用相應(yīng)的回調(diào)函數(shù)處理

核心觀點:

  1. 反應(yīng)堆模型啟動后,可以檢測到被激活的文件描述符
  2. 使用dispatch函數(shù)獲取文件描述符,并根據(jù)文件描述符從ChannelMap中取出對應(yīng)的channel
  3. 根據(jù)channel判斷是讀事件還是寫事件,并調(diào)用相應(yīng)的回調(diào)函數(shù)處理
  4. select函數(shù)中,通過fd_set集合判斷是否有數(shù)據(jù)可讀可寫,調(diào)用eventActivate函數(shù)處理事件
  5. epoll函數(shù)中,通過epoll_wait進(jìn)行檢測,遍歷返回的events數(shù)組,調(diào)用eventActivate函數(shù)處理事件
  6. poll函數(shù)中,通過poll進(jìn)行檢測,遍歷返回的事件列表,調(diào)用eventActivate函數(shù)處理事件

>>回顧ChannelMap 模塊的實現(xiàn)Channel 模塊的實現(xiàn)

基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件,基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】,高并發(fā)服務(wù)器,多反應(yīng)堆,C/C++/Reactor,處理被激活的文件描述符的事件,EventLoop基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件,基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】,高并發(fā)服務(wù)器,多反應(yīng)堆,C/C++/Reactor,處理被激活的文件描述符的事件,EventLoop

  • Channel.h
// 定義函數(shù)指針
typedef int(*handleFunc)(void* arg);
 
// 定義文件描述符的讀寫事件
enum FDEvent {
    TimeOut = 0x01;
    ReadEvent = 0x02;
    WriteEvent = 0x04;
};
 
struct Channel {
    // 文件描述符
    int fd;
    // 事件
    int events;
    // 回調(diào)函數(shù)
    handleFunc readCallback;// 讀回調(diào)
    handleFunc writeCallback;// 寫回調(diào)
    // 回調(diào)函數(shù)的參數(shù)
    void* arg;
};

?>>在EventLoop中處理被激活的文件描述符的事件

  • EpollLoop.h?
// 處理被激活的文件描述符fd
int eventActivate(struct EventLoop* evLoop,int fd,int event);
  • ?EpollLoop.c??
// 處理被激活的文件描述符fd
int eventActivate(struct EventLoop* evLoop,int fd,int event) {
    if(fd < 0 || evLoop == NULL) {+
        return -1;
    }
    // 取出channel
    struct Channel* channel = evLoop->channelMap->list[fd];
    assert(channel->fd == fd);
    if(event & ReadEvent && channel->readCallback) {
        channel->readCallback(channel->arg);
    }
    if(event & WriteEvent && channel->writeCallback) {
        channel->writeCallback(channel->arg);
    }
    return 0;
}

>>回顧Dispatcher模塊,Dispatcher模塊的實現(xiàn)思路和定義?,補(bǔ)充代碼

  • SelectDispatcher.c??
static int selectDispatch(struct EventLoop* evLoop,int timeout) {
    struct SelectData* data = (struct SelectData*)evLoop->dispatcherData;
    struct timeval val;
    val.tv_sec = timeout;
    val.tv_usec = 0;
    fd_set rdtmp = data->readSet;
    fd_set wrtmp = data->writeSet;
    int count = select(Max,&rdtmp,&wrtmp,NULL,&val);
    if(count == -1) {
        perror("select");
        exit(0);
    }
    for(int i=0;i<Max;++i) { 
        if(FD_ISSET(i,&rdtmp)) {
            // 已續(xù)寫...
            eventActivate(evLoop,i,ReadEvent);
        }
        if(FD_ISSET(i,&wrtmp)) {
            // 已續(xù)寫...
            eventActivate(evLoop,i,WriteEvent);
        }
    }
    return 0;
}
  • PollDispatcher.c??
static int pollDispatch(struct EventLoop* evLoop,int timeout) {
    struct PollData* data = (struct PollData*)evLoop->dispatcherData;
    int count = poll(data->fds,data->maxfd + 1,timeout * 1000);
    if(count == -1) {
        perror("poll");
        exit(0);
    }
    for(int i=0;i<=data->maxfd;++i) {
        if(data->fds[i].fd == -1) {
            continue;
        }
        if(data->fds[i].revents & POLLIN) {
            // 已續(xù)寫...
            eventActivate(evLoop,data->fds[i].fd,ReadEvent);
        }
        if(data->fds[i].revents & POLLOUT) {
            // 已續(xù)寫...
            eventActivate(evLoop,data->fds[i].fd,WriteEvent);
        }
    }
    return 0;
}
  • EpollDispatcher.c??
static int epollDispatch(struct EventLoop* evLoop,int timeout) {
    struct EpollData* data = (struct EpollData*)evLoop->dispatcherData;
    int count = epoll_wait(data->epfd,data->events,Max,timeout * 1000);
    for(int i=0;i<count;++i) {
        int events = data->events[i].events;
        int fd = data->events[i].data.fd;
        if(events & EPOLLERR || events & EPOLLHUP) {
            // 對方斷開了連接,刪除 fd
            // epollRemove(&evLoop->channels[fd],evLoop);
            continue;
        }
        if(events & EPOLLIN) {
            // 已續(xù)寫...
            eventActivate(evLoop,fd,ReadEvent);
        }
        if(events & EPOLLOUT) {
            // 已續(xù)寫...
            eventActivate(evLoop,fd,WriteEvent);
        }
    }
    return 0;
}

五、回顧select函數(shù)、poll函數(shù)、epoll_wait函數(shù)(CodeGeex生成)

基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件,基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】,高并發(fā)服務(wù)器,多反應(yīng)堆,C/C++/Reactor,處理被激活的文件描述符的事件,EventLoop

  • select函數(shù)

Linux 中的 select 函數(shù)主要用于等待多個文件描述符(fd)就緒,從而可以一次性處理多個文件描述符。select 函數(shù)會檢查指定的文件描述符是否就緒,如果其中任何一個是就緒的,則 select 函數(shù)返回。select 函數(shù)的原型為:

#include <sys/select.h>
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,const struct timeval *timeout);

其中,nfds 表示要檢查的文件描述符數(shù)量,readfds、writefds 和 exceptfds 分別表示要檢查的讀、寫和異常文件描述符集合,timeout 表示等待的時間限制。

例如,下面代碼等待兩個文件描述符(fd)就緒,最多等待 5 秒鐘:

int fd1 = open("file1", O_RDONLY);
int fd2 = open("file2", O_RDONLY);

fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd1, &readfds);
FD_SET(fd2, &readfds);

struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;

int ret = select(2, &readfds, NULL, NULL, &timeout);

if (ret > 0) {
   if (FD_ISSET(fd1, &readfds)) {
       // fd1 is ready to read
   }
   if (FD_ISSET(fd2, &readfds)) {
       // fd2 is ready to read
   }
}
  • poll函數(shù)

Linux 中的 poll 函數(shù)與 select 函數(shù)類似,用于等待多個文件描述符就緒,但是 poll 函數(shù)返回的是一個事件列表,不是像 select 函數(shù)那樣返回就緒的文件描述符數(shù)量。poll 函數(shù)的原型為:

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

其中,fds 是一個 pollfd 結(jié)構(gòu)數(shù)組,每個結(jié)構(gòu)中包含一個文件描述符和一個事件掩碼,timeout 表示等待的時間限制。

例如,下面代碼使用 poll 函數(shù)等待兩個文件描述符(FD)就緒,最多等待 5 秒鐘:

int fd1 = open("file1", O_RDONLY);
int fd2 = open("file2", O_RDONLY);

struct pollfd fds[2];
fds[0].fd = fd1;
fds[0].events = POLLIN;
fds[1].fd = fd2;
fds[1].events = POLLIN;

int timeout = 5000; // 5 秒

int ret = poll(fds, 2, timeout);

if (ret > 0) {
  if (fds[0].revents & POLLIN) {
      // fd1 is ready to read
  }
  if (fds[1].revents & POLLIN) {
      // fd2 is ready to read
  }
}

如果 poll 函數(shù)返回 0,則表示超時,如果返回值大于 0,則表示有文件描述符就緒。與 select 函數(shù)不同的是,poll 函數(shù)返回的是一個事件列表,而不是具體的文件描述符。

  • epoll函數(shù)

Linux 中的 epoll 函數(shù)是 Linux 2.6.8 引入的一個新的 I/O 模型,它提供了高效的 I/O 事件通知機(jī)制,能夠處理大量文件描述符,并且具有低延遲和高吞吐量的優(yōu)點。

epoll 函數(shù)的原型為:

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epoll_fd, int op, int fd, int event);
int epoll_wait(int epoll_fd, struct epoll_event *events, int maxevents, int timeout);

其中,epoll_create 函數(shù)用于創(chuàng)建一個 epoll 實例,size 參數(shù)指定要創(chuàng)建的 epoll 實例可以容納的最大文件描述符數(shù)量。epoll_ctl 函數(shù)用于控制 epoll 實例,op 參數(shù)指定要進(jìn)行的操作(例如,添加修改刪除文件描述符),fd 參數(shù)指定要操作的文件描述符,event 參數(shù)指定要設(shè)置的事件掩碼。epoll_wait 函數(shù)用于等待 epoll 實例中的文件描述符就緒,events 參數(shù)指向一個 epoll_event 結(jié)構(gòu)數(shù)組,用于存儲就緒的文件描述符和事件信息,maxevents 參數(shù)指定最多等待的文件描述符數(shù)量,timeout 參數(shù)指定等待的時間限制。

例如,下面代碼使用 epoll 函數(shù)等待兩個文件描述符(fd)就緒,最多等待 5 秒鐘:

int fd1 = open("file1", O_RDONLY);
int fd2 = open("file2", O_RDONLY);

int epoll_fd = epoll_create(10);

struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = fd1;

int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd1, &event);

event.data.fd = fd2;
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd2, &event);

struct epoll_event events[2];
int timeout = 5000; // 5 秒

int num = epoll_wait(epoll_fd, events, 2, timeout);

if (num > 0) {
 if (events[0].data.fd == fd1 && events[0].events & EPOLLIN) {
     // fd1 is ready to read
 }
 if (events[1].data.fd == fd2 && events[1].events & EPOLLIN) {
     // fd2 is ready to read
 }
}

如果 epoll 函數(shù)返回 0,則表示超時,如果返回值大于 0,則表示有文件描述符就緒。與 select poll 函數(shù)不同的是,epoll 函數(shù)能夠處理大量的文件描述符,并且具有低延遲和高吞吐量的優(yōu)點文章來源地址http://www.zghlxwxcb.cn/news/detail-777311.html

到了這里,關(guān)于基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在EventLoop中處理被激活的文件描述符的事件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包