應(yīng)用

技術(shù)

物聯(lián)網(wǎng)世界 >> 物聯(lián)網(wǎng)新聞 >> 物聯(lián)網(wǎng)熱點(diǎn)新聞
企業(yè)注冊(cè)個(gè)人注冊(cè)登錄

物聯(lián)網(wǎng)安全himqtt防火墻數(shù)據(jù)結(jié)構(gòu)之ringbuffer環(huán)形緩沖區(qū)

2019-11-12 10:16 媒體投稿

導(dǎo)讀:隨著5G的普及,物聯(lián)網(wǎng)安全顯得特別重要,himqtt是首款完整源碼的高性能MQTT物聯(lián)網(wǎng)防火墻 - MQTT Application FireWall,C語(yǔ)言編寫(xiě),采用epoll模式支持IoT數(shù)十萬(wàn)的高并發(fā)連接,并且兼容ModSecurity部分規(guī)則。 代碼非常優(yōu)秀,非常值得收藏和學(xué)習(xí),今天筆者就從結(jié)合himqtt的源碼來(lái)進(jìn)行ringbuffer數(shù)據(jù)結(jié)構(gòu)分析,主要特點(diǎn)是速度快。

  

隨著5G的普及,物聯(lián)網(wǎng)安全顯得特別重要,himqtt是首款完整源碼的高性能MQTT物聯(lián)網(wǎng)防火墻 - MQTT Application FireWall,C語(yǔ)言編寫(xiě),采用epoll模式支持IoT數(shù)十萬(wàn)的高并發(fā)連接,并且兼容ModSecurity部分規(guī)則。 代碼非常優(yōu)秀,非常值得收藏和學(xué)習(xí),今天筆者就從結(jié)合himqtt的源碼來(lái)進(jìn)行ringbuffer數(shù)據(jù)結(jié)構(gòu)分析,主要特點(diǎn)是速度快。

 

一、 ringBuffer 介紹

ringBuffer 稱作環(huán)形緩沖,也有叫 circleBuffer Linux內(nèi)核也大量使用了這種數(shù)據(jù)結(jié)構(gòu)。就是取內(nèi)存中一塊連續(xù)的區(qū)域用作環(huán)形緩沖區(qū)的數(shù)據(jù)存儲(chǔ)區(qū)。這塊連續(xù)的存儲(chǔ)會(huì)被反復(fù)使用,向 ringBuffer 寫(xiě)入數(shù)據(jù)總是從寫(xiě)指針的位置開(kāi)始,如寫(xiě)到實(shí)際存儲(chǔ)區(qū)的末尾還沒(méi)有寫(xiě)完,則將剩余的數(shù)據(jù)從存儲(chǔ)區(qū)的頭開(kāi)始寫(xiě);從該 ringBuffer 讀出數(shù)據(jù)也是從讀指針的位置開(kāi)始,如讀到實(shí)際存儲(chǔ)區(qū)的末尾還沒(méi)有讀完,則從存儲(chǔ)區(qū)的頭開(kāi)始讀剩下的數(shù)據(jù)。

 

 

、 ringBuffer 優(yōu)點(diǎn)

 

1Ring Buffer 比鏈表要快,因?yàn)樗菙?shù)組,而且有一個(gè)容易預(yù)測(cè)的訪問(wèn)模式。這很不錯(cuò),對(duì) CPU 高速緩存友好 (CPU-cache-friendly)-數(shù)據(jù)可以在硬件層面預(yù)加載到高速緩存,因此 CPU 不需要經(jīng)?;氐街鲀?nèi)存 RAM 里去尋找 Ring Buffer 的下一條數(shù)據(jù)。

2、Ring Buffer 是一個(gè)數(shù)組,你可以預(yù)先分配內(nèi)存,并保持?jǐn)?shù)組元素永遠(yuǎn)有效。這意味著內(nèi)存垃圾收集(GC)在這種情況下幾乎什么也不用做。此外,也不像鏈表那樣每增加一條數(shù)據(jù)都要?jiǎng)?chuàng)建對(duì)象-當(dāng)這些數(shù)據(jù)從鏈表里刪除時(shí),這些對(duì)象都要被清理掉。

 

總之就是內(nèi)存處理速度特別快,特別適合高并發(fā)、大量的請(qǐng)求。

三、ringBuffer 代碼實(shí)現(xiàn)

首先在github上下載himqtt的源碼:https://github.com/qq4108863/himqtt

找到src目錄下的ringbuffer.cringbuffer.h文件。

 

1、ringBuffer 的結(jié)構(gòu)體

typedef struct bufent {

    char *data;

    char *ptr;

    size_t left;

    struct bufent *next;

} bufent;

 

typedef struct ringbuffer {

    bufent *slots;

    bufent *head; // reads from the head

    bufent *tail; // writes to the tail

    char   *buf;

    int used;

    int num_slots;

    int data_len;

    size_t bytes_written;

} ringbuffer;

 

 

2、創(chuàng)建 ringBuffer 函數(shù)

void

ringbuffer_init(ringbuffer *rb, int num_slots, int data_len)

{

rb->num_slots = num_slots ?: DEF_RING_SLOTS;

rb->data_len = data_len ?: DEF_RING_DATA_LEN;

rb->slots = malloc(rb->num_slots * sizeof(rb->slots[0]));

AN(rb->slots);

 

rb->head = &rb->slots[0];

rb->tail = &rb->slots[0];

int x;

for (x=0; x < rb->num_slots; x++) {

rb->slots[x].next = &(rb->slots[(x + 1) % rb->num_slots]);

rb->slots[x].data = malloc(rb->data_len);

AN(rb->slots[x].data);

}

rb->used = 0;

rb->bytes_written = 0;

}

 

3、清空 ringBuffer 函數(shù)

void

ringbuffer_cleanup(ringbuffer *rb)

{

int x;

for (x=0; x < rb->num_slots; x++) {

free(rb->slots[x].data);

}

free(rb->slots);

}

 

4、讀數(shù)據(jù)函數(shù)

char *

ringbuffer_read_next(ringbuffer *rb, int * length)

{

assert(rb->used);

*length = rb->head->left;

return rb->head->ptr;

}

 

5、寫(xiě)數(shù)據(jù)函數(shù)

void

ringbuffer_write_append(ringbuffer *rb, int length)

{

assert(rb->used < rb->num_slots);

 

rb->used++;

 

rb->tail->ptr = rb->tail->data;

rb->tail->left = length;

rb->tail = rb->tail->next;

}

 

 

如果僅僅有一個(gè)讀用戶和一個(gè)寫(xiě)用戶,那么不需要添加互斥保護(hù)機(jī)制就可以保證數(shù)據(jù)的正確性。如果有多個(gè)讀寫(xiě)用戶訪問(wèn)環(huán)形緩沖區(qū),那么必須添加互斥保護(hù)機(jī)制來(lái)確保多個(gè)用戶互斥訪問(wèn)環(huán)形緩沖區(qū)。

Ringbuffer特別適合一個(gè)讀,一個(gè)寫(xiě)的高速場(chǎng)景。5G 時(shí)代就是大量的設(shè)備會(huì)聯(lián)網(wǎng),并且持續(xù)通信,對(duì)himqtt這類物聯(lián)網(wǎng)防火墻就提出了很高的要求,所以算法和數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)就非常重要。