標籤:des style blog 使用 strong 資料
最近一直在研究redis的源碼,redis的高效率令人佩服。
在我們的linux機器上,cpu型號為,
Intel(R) Pentium(R) CPU G630 @ 2.70GHz
Intel(R) Pentium(R) CPU G630 @ 2.70GHz
上 set,get 都能達到每秒鐘15W的請求處理量,真是佩服這代碼的效率。
前幾篇文章,主要是介紹了基本的代碼,比如字串處理,鏈表處理,hash等。這篇文章介紹網路的核心,基於事件反映的非同步網路架構。
非同步網路處理,是基於epoll的。epoll的分為兩種模式,水平觸發和邊緣觸發。ae使用了水平觸發,就是一旦有資料,epoll會一直通知,直到就讀取完成。而邊緣觸發則只通知一次。等到狀態改變才會去通知。具體可以到網上查閱。
1.結構體源碼解析
1.1讀寫事件結構體
/* File event structure */typedef struct aeFileEvent { int mask; /* one of AE_(READABLE|WRITABLE) */ aeFileProc *rfileProc; aeFileProc *wfileProc; void *clientData;} aeFileEvent;
該結構體表示一個fd對應的事件處理函數和私人資料。當我們要註冊一個fd時間時,就會填充該結構體。
1.2 時間事件狗狗提
/* Time event structure */typedef struct aeTimeEvent { long long id; /* time event identifier. */ long when_sec; /* seconds */ long when_ms; /* milliseconds */ aeTimeProc *timeProc; aeEventFinalizerProc *finalizerProc; void *clientData; struct aeTimeEvent *next;} aeTimeEvent;
當我們註冊定時處理事件,會填充相應結構體,添加到數組裡
1.3 觸發的fd
/* A fired event */typedef struct aeFiredEvent { int fd; int mask;} aeFiredEvent;
該結構體表示一個fd對應的可讀可寫事件
1.4 ae事件的總結構體
/* State of an event based program */typedef struct aeEventLoop { int maxfd; /* highest file descriptor currently registered */ int setsize; /* max number of file descriptors tracked */ long long timeEventNextId; time_t lastTime; /* Used to detect system clock skew */ aeFileEvent *events; /* Registered events */ aeFiredEvent *fired; /* Fired events */ aeTimeEvent *timeEventHead; int stop; void *apidata; /* This is used for polling API specific data */ aeBeforeSleepProc *beforesleep;} aeEventLoop;
該結構體儲存了ae非同步事件的基本資料,比如fd大小,時間事件id,註冊的時間指標等。
2.ae_epoll 介面
2.1 epoll 結構體
typedef struct aeApiState { int epfd; struct epoll_event *events;} aeApiState;
提供epoll的變數定義,
epfd是通過epoll_create 建立。events表示epoll_wait允許監聽的數量。
填充aeApiState結構體。
static int aeApiCreate(aeEventLoop *eventLoop)
調用epoll_wait ,擷取我們關心的事件,
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)
2、api介面
1,建立eventloop
aeEventLoop *aeCreateEventLoop(int setsize)
2.添加事件
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData)
3。刪除事件,
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
4。建立時間事件
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds, aeTimeProc *proc, void *clientData, aeEventFinalizerProc *finalizerProc)
5.刪除時間事件
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id)
使用樣本
//建立loop
proxy.eventLoop = aeCreateEventLoop(DEFAULT_LOOP_SIZE);
//建立事件事件
if(aeCreateTimeEvent(proxy.eventLoop, 1, serverCron, NULL, NULL) == AE_ERR)
{
printf("Can‘t create the serverCron time event\n");
exit(1);
}
/* 伺服器監聽redis用戶端的串連 */
aeCreateFileEvent(proxy.eventLoop, proxy.server_fd, AE_READABLE, on_client_connected, NULL);
aeCreateFileEvent(proxy.eventLoop, proxy.evfd, AE_READABLE, reconnect_redis, NULL);
以上就是一個簡單的樣本。
我寫了一個類redisprox的東西,待我上傳給大家看看。