More  

小編的世界 優質文選 主機

Linux高並發服務器的架構簡介


2020年12月01日 - 主機小編  
   

閑聊代碼

工作進程的主循環代碼大概這樣:

while(!exit) { //如果沒有退出標志則循環

int ret = epoll_wait(epfd, events, max events, timeout);

if (ret < 0) {

//出錯處理

break;

}

//正常返回時的ret返回值是觸發的事件個數

int i;

for (i =0; i < ret; i ++) {

//遍曆處理所有的觸發事件

}

//處理到時間的定時器事件

}

像http之類的具體協議的處理,都是在事件的回調函數裏做的。

epoll_event的結構分兩個部分,一個是具體的epoll事件的標志,例如EPOLLIN表示讀,EPOLLOUT表示寫。

另一部分是用戶自定義的上下文數據的指針。各模塊的數據結構可以放在這個指針裏。

如下圖,可以把自定義數據結構掛在e->data.ptr裏,其中e為struct epoll_event類型的指針。

假設自定義的連接上下文結構是:

struct connection {

int fd; // socket文件描述符

int (*read)(struct connnection* c);

//讀數據的函數指針

int (*write)(struct connection* c);

//寫數據的函數指針

uint8_t* readbuf; //讀緩沖區

int readbuf_size; //當前讀緩沖區大小

uint8_t* writebuf; //寫緩沖區

int writebuf_size; //寫緩沖區大小

void* data; //下一級模塊的結構體

};

那麼工作進程worker的主循環while()裏,遍曆觸發的事件的for循環的處理就是:

for (i =0; i < ret; i++) {

struct epoll_event* e = &events;

struct connection * c = e->data.ptr;

int ret2 = c->read(c);

}

這只是示例代碼,nginx的這部分代碼還是比較複雜的。

最精簡的事件框架記得是redis自帶的libae,大概幾百行。

libevent框架則特別的複雜。