對於redis底層架構的理解(五)

來源:互聯網
上載者:User

標籤:

之前總結了redis的通訊流程,基本架構,epoll的封裝等等,這次介紹下

redis對於select模型的封裝

//select 模型typedef struct aeApiState {    //讀檔案描述符集合,寫檔案描述符集合    fd_set rfds, wfds;    /* We need to have a copy of the fd sets as it‘s not safe to reuse     * FD sets after select(). */     //讀寫集合的副本    fd_set _rfds, _wfds;} aeApiState;

_rfds和_wfds是讀寫結合的副本,因為select調用後會將讀寫集合中未就緒的檔案描述符

清除,所以每次用_rfds和_wfds傳入,就不用擔心原讀寫集合描述符被清除。

 

封裝的基於select的初始化函數

static int aeApiCreate(aeEventLoop *eventLoop) {    //開闢aeApiState空間    aeApiState *state = zmalloc(sizeof(aeApiState));        if (!state) return -1;    //讀寫集合清零    FD_ZERO(&state->rfds);    FD_ZERO(&state->wfds);    eventLoop->apidata = state;    return 0;}

函數將讀寫集合清零,並且將state回傳給eventloop的apidata部分。

記憶體回收功能

//釋放空間static void aeApiFree(aeEventLoop *eventLoop) {    zfree(eventLoop->apidata);}

 

封裝的添加和刪除事件

//select 添加事件static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {    aeApiState *state = eventLoop->apidata;    if (mask & AE_READABLE) FD_SET(fd,&state->rfds);    if (mask & AE_WRITABLE) FD_SET(fd,&state->wfds);    return 0;}//select 刪除事件static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) {    aeApiState *state = eventLoop->apidata;    if (mask & AE_READABLE) FD_CLR(fd,&state->rfds);    if (mask & AE_WRITABLE) FD_CLR(fd,&state->wfds);}

添加事件函數將檔案描述根據mask是讀事件還是寫事件放入不同的set

刪除事件根據檔案描述符mask是讀事件還是寫事件從不同的set中清除

 

下面是核心功能,事件派發

//select 觸發事件static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {    aeApiState *state = eventLoop->apidata;    int retval, j, numevents = 0;    //將select讀集合的資料拷貝到_rfds    memcpy(&state->_rfds,&state->rfds,sizeof(fd_set));       //將select寫集合資料拷貝到_wfds    memcpy(&state->_wfds,&state->wfds,sizeof(fd_set));    //從讀和寫的copy集合裡選出就緒的檔案描述符     retval = select(eventLoop->maxfd+1,                &state->_rfds,&state->_wfds,NULL,tvp);    //大於零表示有就緒的檔案描述符        if (retval > 0) {        //select的弊端所在,每次都要將所有的檔案描述符輪詢一遍        for (j = 0; j <= eventLoop->maxfd; j++) {                        int mask = 0;            aeFileEvent *fe = &eventLoop->events[j];            if (fe->mask == AE_NONE) continue;            //aeFileEvent 事件可讀            if (fe->mask & AE_READABLE && FD_ISSET(j,&state->_rfds))                mask |= AE_READABLE;            //aeFileEvent 事件可寫            if (fe->mask & AE_WRITABLE && FD_ISSET(j,&state->_wfds))                mask |= AE_WRITABLE;            eventLoop->fired[numevents].fd = j;            eventLoop->fired[numevents].mask = mask;            numevents++;        }    }    return numevents;}

先將讀寫集合中的內容copy的_rfds和_wfds中,分別傳入select函數中,

這樣select後返回的_rfds中只有就緒的讀socket

_wfds中只有就緒的寫socket

通過FD_ISSET判斷讀寫事件之後放到eventloop的fire隊列裡。

基本的封裝就是這個樣子,select模型相對容易理解

我的公眾號:

 

對於redis底層架構的理解(五)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.