摘要:的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)結(jié)構(gòu)中是鏈表元素的個(gè)數(shù),是緩沖區(qū)創(chuàng)建時(shí),鏈表元素約定的大小實(shí)際大小不一定是這個(gè)值,是實(shí)際上緩沖區(qū)占用的內(nèi)存總大小。中的有三種,分別應(yīng)用于緩存數(shù)據(jù)發(fā)送文件提醒連接關(guān)閉三種情景。指的是元素的內(nèi)存大小。
前言
swoole 中數(shù)據(jù)的接受與發(fā)送(例如 reactor 線程接受客戶端消息、發(fā)送給客戶端的消息、接受到的來自 worker 的消息、要發(fā)送給 worker 的消息等等)都要涉及到緩沖區(qū),swoole 中的緩沖區(qū)實(shí)現(xiàn)是 swBuffer,實(shí)際上是一個(gè)單鏈表。
swBuffer 的數(shù)據(jù)結(jié)構(gòu)swBuffer 數(shù)據(jù)結(jié)構(gòu)中 trunk_num 是鏈表元素的個(gè)數(shù),trunk_size 是 swBuffer 緩沖區(qū)創(chuàng)建時(shí),鏈表元素約定的大小(實(shí)際大小不一定是這個(gè)值),length 是實(shí)際上緩沖區(qū)占用的內(nèi)存總大小。
swBuffer_trunk 中的 type 有三種,分別應(yīng)用于:緩存數(shù)據(jù)、發(fā)送文件、提醒連接關(guān)閉三種情景。length 指的是元素的內(nèi)存大小。
enum swBufferChunk { SW_CHUNK_DATA, SW_CHUNK_SENDFILE, SW_CHUNK_CLOSE, }; typedef struct _swBuffer_trunk { uint32_t type; uint32_t length; uint32_t offset; union { void *ptr; struct { uint32_t val1; uint32_t val2; } data; } store; uint32_t size; void (*destroy)(struct _swBuffer_trunk *chunk); struct _swBuffer_trunk *next; } swBuffer_trunk; typedef struct _swBuffer { int fd; uint8_t trunk_num; //trunk數(shù)量 uint16_t trunk_size; uint32_t length; swBuffer_trunk *head; swBuffer_trunk *tail; } swBuffer;swBuffer 的創(chuàng)建
swBuffer 的創(chuàng)建很簡(jiǎn)單,只是初始化整個(gè) swBuffer 的 header 頭元素而已:
swBuffer* swBuffer_new(int trunk_size) { swBuffer *buffer = sw_malloc(sizeof(swBuffer)); if (buffer == NULL) { swWarn("malloc for buffer failed. Error: %s[%d]", strerror(errno), errno); return NULL; } bzero(buffer, sizeof(swBuffer)); buffer->trunk_size = trunk_size; return buffer; }swBuffer 內(nèi)存的申請(qǐng)
swBuffer 內(nèi)存的申請(qǐng)邏輯也很簡(jiǎn)單,按照傳入的 size 參數(shù)為鏈表元素申請(qǐng)內(nèi)存,初始化成員變量,然后將鏈表元素放到鏈表的尾部即可:
int swBuffer_append(swBuffer *buffer, void *data, uint32_t size) { swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size); if (chunk == NULL) { return SW_ERR; } buffer->length += size; chunk->length = size; memcpy(chunk->store.ptr, data, size); swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size, chunk->length, chunk); return SW_OK; } swBuffer_trunk *swBuffer_new_trunk(swBuffer *buffer, uint32_t type, uint32_t size) { swBuffer_trunk *chunk = sw_malloc(sizeof(swBuffer_trunk)); if (chunk == NULL) { swWarn("malloc for trunk failed. Error: %s[%d]", strerror(errno), errno); return NULL; } bzero(chunk, sizeof(swBuffer_trunk)); //require alloc memory if (type == SW_CHUNK_DATA && size > 0) { void *buf = sw_malloc(size); if (buf == NULL) { swWarn("malloc(%d) for data failed. Error: %s[%d]", size, strerror(errno), errno); sw_free(chunk); return NULL; } chunk->size = size; chunk->store.ptr = buf; } chunk->type = type; buffer->trunk_num ++; if (buffer->head == NULL) { buffer->tail = buffer->head = chunk; } else { buffer->tail->next = chunk; buffer->tail = chunk; } return chunk; }獲取 swBuffer 的元素
從 swBuffer 緩沖區(qū)拿數(shù)據(jù)只能從 head 中獲取:
#define swBuffer_get_trunk(buffer) (buffer->head)swBuffer 元素的 pop
獲取了緩沖區(qū)的元素之后,就要相應(yīng)刪除 head 鏈表元素:
void swBuffer_pop_trunk(swBuffer *buffer, swBuffer_trunk *chunk) { if (chunk->next == NULL) { buffer->head = NULL; buffer->tail = NULL; buffer->length = 0; buffer->trunk_num = 0; } else { buffer->head = chunk->next; buffer->length -= chunk->length; buffer->trunk_num--; } if (chunk->type == SW_CHUNK_DATA) { sw_free(chunk->store.ptr); } if (chunk->destroy) { chunk->destroy(chunk); } sw_free(chunk); }swBuffer 緩沖區(qū)的銷毀
int swBuffer_free(swBuffer *buffer) { volatile swBuffer_trunk *chunk = buffer->head; void * *will_free_trunk; //free the point while (chunk != NULL) { if (chunk->type == SW_CHUNK_DATA) { sw_free(chunk->store.ptr); } will_free_trunk = (void *) chunk; chunk = chunk->next; sw_free(will_free_trunk); } sw_free(buffer); return SW_OK; }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29221.html
前言 作為一個(gè)網(wǎng)絡(luò)框架,最為核心的就是消息的接受與發(fā)送。高效的 reactor 模式一直是眾多網(wǎng)絡(luò)框架的首要選擇,本節(jié)主要講解 swoole 中的 reactor 模塊。 UNP 學(xué)習(xí)筆記——IO 復(fù)用 Reactor 的數(shù)據(jù)結(jié)構(gòu) Reactor 的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,首先 object 是具體 Reactor 對(duì)象的首地址,ptr 是擁有 Reactor 對(duì)象的類的指針, event_nu...
摘要:之后如果仍然有剩余未發(fā)送的數(shù)據(jù),那么就如果已經(jīng)沒有剩余數(shù)據(jù)了,繼續(xù)去取下一個(gè)數(shù)據(jù)包。拿到后,要用函數(shù)轉(zhuǎn)化為相應(yīng)的類型即可得到包長(zhǎng)值。 swPort_onRead_check_eof EOF 自動(dòng)分包 我們前面說過,swPort_onRead_raw 是最簡(jiǎn)單的向 worker 進(jìn)程發(fā)送數(shù)據(jù)包的方法,swoole 會(huì)將從客戶端接受到的數(shù)據(jù)包,立刻發(fā)送給 worker 進(jìn)程,用戶自己把...
摘要:線程在建立之時(shí),就會(huì)調(diào)用函數(shù)開啟事件循環(huán)。如果為空,那么重新設(shè)置文件描述符的監(jiān)聽事件,刪除寫就緒,只設(shè)置讀就緒。這個(gè)是水平觸發(fā)模式的必要步驟,避免無數(shù)據(jù)寫入時(shí),頻繁地調(diào)用寫就緒回調(diào)函數(shù)。 前言 經(jīng)過 php_swoole_server_before_start 調(diào)用 swReactorThread_create 創(chuàng)建了 serv->reactor_threads 對(duì)象后,swServe...
摘要:當(dāng)其就緒時(shí),會(huì)調(diào)用執(zhí)行定時(shí)函數(shù)。進(jìn)程超時(shí)停止進(jìn)程將要停止時(shí),并不會(huì)立刻停止,而是會(huì)等待事件循環(huán)結(jié)束后停止,這時(shí)為了防止進(jìn)程不退出,還設(shè)置了的延遲,超過就會(huì)停止該進(jìn)程。當(dāng)允許空閑時(shí)間小于時(shí),統(tǒng)一每隔檢測(cè)空閑連接。 前言 swoole 的 timer 模塊功能有三個(gè):用戶定時(shí)任務(wù)、剔除空閑連接、更新 server 時(shí)間。timer 模塊的底層有兩種,一種是基于 alarm 信號(hào),一種是基于...
摘要:前言我們知道,由于沒有多線程模型,所以更多的使用多進(jìn)程模型,因此代碼相對(duì)來說更加簡(jiǎn)潔,減少了各種線程鎖的阻塞與同步,但是也帶來了新的問題數(shù)據(jù)同步。相比多線程之前可以直接共享進(jìn)程的內(nèi)存,進(jìn)程之間數(shù)據(jù)的相互同步依賴于共享內(nèi)存。 前言 我們知道,由于 PHP 沒有多線程模型,所以 swoole 更多的使用多進(jìn)程模型,因此代碼相對(duì)來說更加簡(jiǎn)潔,減少了各種線程鎖的阻塞與同步,但是也帶來了新的問題...
閱讀 771·2023-04-25 20:47
閱讀 2534·2019-08-30 15:53
閱讀 947·2019-08-26 14:05
閱讀 894·2019-08-26 11:59
閱讀 1679·2019-08-26 11:43
閱讀 1679·2019-08-26 10:57
閱讀 1355·2019-08-23 18:23
閱讀 2639·2019-08-23 12:57