0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語(yǔ)言環(huán)形隊(duì)列的原理和特點(diǎn)

strongerHuang ? 來(lái)源:嵌入式Linux ? 作者:寫(xiě)代碼的籃球球癡 ? 2021-05-11 13:56 ? 次閱讀

什么是環(huán)形隊(duì)列?

環(huán)形緩沖區(qū)是一個(gè)非常典型的數(shù)據(jù)結(jié)構(gòu),這種數(shù)據(jù)結(jié)構(gòu)符合生產(chǎn)者,消費(fèi)者模型,可以理解它是一個(gè)水坑,生產(chǎn)者不斷的往里面灌水,消費(fèi)者就不斷的從里面取出水。

那就可能會(huì)有人問(wèn),既然需要灌水,又需要取出水,為什么還需要開(kāi)辟一個(gè)緩沖區(qū)內(nèi)存空間呢?直接把生產(chǎn)者水管的尾部接到消費(fèi)者水管的頭部不就好了,這樣可以省空間啊。

答案是不行的,生產(chǎn)者生產(chǎn)水的速度是不知道的,消費(fèi)者消費(fèi)水的速度也是不知道的,如果你強(qiáng)制接在一起,因?yàn)樯a(chǎn)和消費(fèi)的速度不同,就非??赡艽嬖谒鼙ǖ那闆r,你說(shuō)這樣危險(xiǎn)不危險(xiǎn)?

音頻系統(tǒng)框架下,alsa就是使用環(huán)形隊(duì)列的,在生產(chǎn)者和消費(fèi)者速度不匹配的時(shí)候,就會(huì)出現(xiàn)xrun的問(wèn)題。

環(huán)形隊(duì)列的特點(diǎn)

1、數(shù)組構(gòu)造環(huán)形緩沖區(qū)

假設(shè)我們用數(shù)組來(lái)構(gòu)造一個(gè)環(huán)形緩存區(qū),如下圖

59134ccc-b20d-11eb-bf61-12bb97331649.png

我們需要幾個(gè)東西來(lái)形容這個(gè)環(huán)形緩沖區(qū),一個(gè)的讀位置,一個(gè)是寫(xiě)位置,一個(gè)是環(huán)形緩沖區(qū)的長(zhǎng)度

5928e3fc-b20d-11eb-bf61-12bb97331649.png

從圖片看,我們知道,這個(gè)環(huán)形緩沖區(qū)的讀寫(xiě)位置是指向數(shù)組的首地址的,環(huán)形緩沖區(qū)的長(zhǎng)度是 5 。

那如何判斷環(huán)形緩沖區(qū)為空呢?

如果 R == W 就是讀寫(xiě)位置相同,則這個(gè)環(huán)形緩沖區(qū)為空

那如何判斷環(huán)形緩沖區(qū)滿了呢?

如果 (W - R )= Len ,則這個(gè)環(huán)形緩沖區(qū)已經(jīng)滿了。

2、向環(huán)形緩沖區(qū)寫(xiě)入 3個(gè)數(shù)據(jù)

寫(xiě)入 3 個(gè)數(shù)據(jù)后,W 的值等于 3 了,R 還是等于 0。

3個(gè)企鵝已經(jīng)排列

3、從環(huán)形緩沖區(qū)讀取2個(gè)數(shù)據(jù)

讀出兩個(gè)數(shù)據(jù)后,R = 2 了,這個(gè)時(shí)候,W還是等于 3,畢竟沒(méi)有再寫(xiě)過(guò)數(shù)據(jù)了。

4、再寫(xiě)入3個(gè)數(shù)據(jù)

如果 W 》 LEN 后,怎么找到最開(kāi)始的位置的呢?這個(gè)就需要進(jìn)行運(yùn)算了,W%LEN 的位置就是放入數(shù)據(jù)的位置 ,6%5 = 1。

5、再寫(xiě)入1個(gè)數(shù)據(jù)

這個(gè)時(shí)候環(huán)形隊(duì)列已經(jīng)滿了,要是想再寫(xiě)入數(shù)據(jù)的話,就不行了,(W - R) = 5 == LEN

代碼實(shí)現(xiàn)

/* 實(shí)現(xiàn)的最簡(jiǎn)單的ringbuff 有更多提升空間,可以留言說(shuō)明 */

#include “stdio.h”

#include “stdlib.h”

#define LEN 10

/*環(huán)形隊(duì)列結(jié)構(gòu)體*/

typedef struct ring_buff{

int array[LEN];

int W;

int R;

}*ring;

/*環(huán)形隊(duì)列初始化*/

struct ring_buff * fifo_init(void)

{

struct ring_buff * p = NULL;

p = (struct ring_buff *)malloc(sizeof(struct ring_buff));

if(p == NULL)

{

printf(“fifo_init malloc error

”);

return NULL;

}

p-》W = 0;

p-》R = 0;

return p;

}

/*判斷環(huán)形隊(duì)列是否已經(jīng)滿了*/

int get_ring_buff_fullstate(struct ring_buff * p_ring_buff)

{

/*如果寫(xiě)位置減去讀位置等于隊(duì)列長(zhǎng)度,就說(shuō)明這個(gè)環(huán)形隊(duì)列已經(jīng)滿*/

if((p_ring_buff-》W - p_ring_buff-》R) == LEN)

{

return (1);

}

else

{

return (0);

}

}

/*判斷環(huán)形隊(duì)列為空*/

int get_ring_buff_emptystate(struct ring_buff * p_ring_buff)

{

/*如果寫(xiě)位置和讀的位置相等,就說(shuō)明這個(gè)環(huán)形隊(duì)列為空*/

if(p_ring_buff-》W == p_ring_buff-》R)

{

return (1);

}

else

{

return (0);

}

}

/*插入數(shù)據(jù)*/

int ring_buff_insert(struct ring_buff * p_ring_buff,int data)

{

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

if(get_ring_buff_fullstate(p_ring_buff) == 1)

{

printf(“buff is full

”);

return (-2);

}

p_ring_buff-》array[p_ring_buff-》W%LEN] = data;

p_ring_buff-》W ++;

//printf(“inset:%d %d

”,data,p_ring_buff-》W);

return (0);

}

/*讀取環(huán)形隊(duì)列數(shù)據(jù)*/

int ring_buff_get(struct ring_buff * p_ring_buff)

{

int data = 0;

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

if(get_ring_buff_emptystate(p_ring_buff) == 1)

{

printf(“buff is empty

”);

return (-2);

}

data = p_ring_buff-》array[p_ring_buff-》R%LEN];

p_ring_buff-》R++;

return data;

}

/*銷毀*/

int ring_buff_destory(struct ring_buff * p_ring_buff)

{

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

free(p_ring_buff);

return (0);

}

int main()

{

int i = 0;

/*定義一個(gè)環(huán)形緩沖區(qū)*/

ring pt_ring_buff = fifo_init();

/*向環(huán)形緩沖區(qū)中寫(xiě)入數(shù)據(jù)*/

for(i = 0;i《10;i++)

{

ring_buff_insert(pt_ring_buff,i);

}

/*從環(huán)形緩沖區(qū)中讀出數(shù)據(jù)*/

for(i = 0;i《10;i++)

{

printf(“%d ”,ring_buff_get(pt_ring_buff));

}

/*銷毀一個(gè)環(huán)形緩沖區(qū)*/

ring_buff_destory(pt_ring_buff);

return (1);

}

599cb322-b20d-11eb-bf61-12bb97331649.png

換一個(gè)寫(xiě)法,這個(gè)寫(xiě)法是各種大神級(jí)別的

/* 實(shí)現(xiàn)的最簡(jiǎn)單的ringbuff 有更多提升空間,可以留言說(shuō)明 */

#include “stdio.h”

#include “stdlib.h”

#define LEN 64

/*環(huán)形隊(duì)列結(jié)構(gòu)體*/

typedef struct ring_buff{

int array[LEN];

int W;

int R;

}*ring;

/*環(huán)形隊(duì)列初始化*/

struct ring_buff * fifo_init(void)

{

struct ring_buff * p = NULL;

p = (struct ring_buff *)malloc(sizeof(struct ring_buff));

if(p == NULL)

{

printf(“fifo_init malloc error

”);

return NULL;

}

p-》W = 0;

p-》R = 0;

return p;

}

/*判斷環(huán)形隊(duì)列是否已經(jīng)滿了*/

int get_ring_buff_fullstate(struct ring_buff * p_ring_buff)

{

/*如果寫(xiě)位置減去讀位置等于隊(duì)列長(zhǎng)度,就說(shuō)明這個(gè)環(huán)形隊(duì)列已經(jīng)滿*/

if((p_ring_buff-》W - p_ring_buff-》R) == LEN)

{

return (1);

}

else

{

return (0);

}

}

/*判斷環(huán)形隊(duì)列為空*/

int get_ring_buff_emptystate(struct ring_buff * p_ring_buff)

{

/*如果寫(xiě)位置和讀的位置相等,就說(shuō)明這個(gè)環(huán)形隊(duì)列為空*/

if(p_ring_buff-》W == p_ring_buff-》R)

{

return (1);

}

else

{

return (0);

}

}

/*插入數(shù)據(jù)*/

int ring_buff_insert(struct ring_buff * p_ring_buff,int data)

{

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

if(get_ring_buff_fullstate(p_ring_buff) == 1)

{

printf(“buff is full

”);

return (-2);

}

//p_ring_buff-》array[p_ring_buff-》W%LEN] = data;

p_ring_buff-》array[p_ring_buff-》W&(LEN -1)] = data;

p_ring_buff-》W ++;

//printf(“inset:%d %d

”,data,p_ring_buff-》W);

return (0);

}

/*讀取環(huán)形隊(duì)列數(shù)據(jù)*/

int ring_buff_get(struct ring_buff * p_ring_buff)

{

int data = 0;

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

if(get_ring_buff_emptystate(p_ring_buff) == 1)

{

printf(“buff is empty

”);

return (-2);

}

//data = p_ring_buff-》array[p_ring_buff-》R%LEN];

data = p_ring_buff-》array[p_ring_buff-》R&(LEN -1)];

p_ring_buff-》R++;

return data;

}

/*銷毀*/

int ring_buff_destory(struct ring_buff * p_ring_buff)

{

if(p_ring_buff == NULL)

{

printf(“p null

”);

return (-1);

}

free(p_ring_buff);

return (0);

}

int main()

{

int i = 0;

/*定義一個(gè)環(huán)形緩沖區(qū)*/

ring pt_ring_buff = fifo_init();

/*向環(huán)形緩沖區(qū)中寫(xiě)入數(shù)據(jù)*/

for(i = 0;i《10;i++)

{

ring_buff_insert(pt_ring_buff,i);

}

/*從環(huán)形緩沖區(qū)中讀出數(shù)據(jù)*/

for(i = 0;i《10;i++)

{

printf(“%d ”,ring_buff_get(pt_ring_buff));

}

/*銷毀一個(gè)環(huán)形緩沖區(qū)*/

ring_buff_destory(pt_ring_buff);

return (1);

}

總結(jié)

環(huán)形隊(duì)列的使用場(chǎng)景非常多,安卓的音頻數(shù)據(jù)讀寫(xiě),很多都用到環(huán)形隊(duì)列,我們?cè)陂_(kāi)發(fā)過(guò)程中使用的環(huán)形隊(duì)列肯定比我上面的那個(gè)例子要復(fù)雜的多,我這里演示的是比較簡(jiǎn)單的功能,但是麻雀雖小,五臟俱全,希望這個(gè)麻雀讓你們了解這個(gè)數(shù)據(jù)結(jié)構(gòu)。在實(shí)際項(xiàng)目中大展身手。

原文標(biāo)題:C語(yǔ)言實(shí)現(xiàn)環(huán)形隊(duì)列的原理和方法

文章出處:【微信公眾號(hào):strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    6715

    瀏覽量

    88311
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7575

    瀏覽量

    134086

原文標(biāo)題:C語(yǔ)言實(shí)現(xiàn)環(huán)形隊(duì)列的原理和方法

文章出處:【微信號(hào):strongerHuang,微信公眾號(hào):strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式環(huán)形隊(duì)列與消息隊(duì)列的實(shí)現(xiàn)原理

    嵌入式環(huán)形隊(duì)列,也稱為環(huán)形緩沖區(qū)或循環(huán)隊(duì)列,是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),用于在固定大小的存儲(chǔ)區(qū)域中高效地存儲(chǔ)和訪問(wèn)數(shù)據(jù)。其主要特點(diǎn)
    的頭像 發(fā)表于 09-02 15:29 ?144次閱讀

    PLC編程語(yǔ)言C語(yǔ)言的區(qū)別

    在工業(yè)自動(dòng)化和計(jì)算機(jī)編程領(lǐng)域中,PLC(可編程邏輯控制器)編程語(yǔ)言C語(yǔ)言各自扮演著重要的角色。盡管兩者都是編程語(yǔ)言,但它們?cè)诙鄠€(gè)方面存在顯著的區(qū)別。本文將從多個(gè)維度深入探討PLC編程
    的頭像 發(fā)表于 06-14 17:11 ?1586次閱讀

    c語(yǔ)言,c++,java,python區(qū)別

    C語(yǔ)言、C++、Java和Python是四種常見(jiàn)的編程語(yǔ)言,各有優(yōu)點(diǎn)和特點(diǎn)C
    的頭像 發(fā)表于 02-05 14:11 ?1366次閱讀

    vb語(yǔ)言c++語(yǔ)言的區(qū)別

    VB語(yǔ)言C++語(yǔ)言是兩種不同的編程語(yǔ)言,雖然它們都屬于高級(jí)編程語(yǔ)言,但在設(shè)計(jì)和用途上有很多區(qū)別。下面將詳細(xì)比較VB
    的頭像 發(fā)表于 02-01 10:20 ?1523次閱讀

    裸機(jī)中環(huán)形隊(duì)列與RTOS中消息隊(duì)列有何區(qū)別呢?

    環(huán)形隊(duì)列”和“消息隊(duì)列”在嵌入式領(lǐng)域有應(yīng)用非常廣泛,相信有經(jīng)驗(yàn)的嵌入式軟件工程師對(duì)它們都不陌生。
    的頭像 發(fā)表于 01-26 09:38 ?577次閱讀
    裸機(jī)中<b class='flag-5'>環(huán)形</b><b class='flag-5'>隊(duì)列</b>與RTOS中消息<b class='flag-5'>隊(duì)列</b>有何區(qū)別呢?

    javascript語(yǔ)言特點(diǎn)

    JavaScript是一種廣泛應(yīng)用于Web開(kāi)發(fā)的腳本語(yǔ)言,具有許多獨(dú)特的特點(diǎn)和優(yōu)勢(shì)。在本篇文章中,我將詳盡、詳實(shí)、細(xì)致地解釋JavaScript的特點(diǎn),讓你全面了解這門(mén)語(yǔ)言。 強(qiáng)大且靈
    的頭像 發(fā)表于 12-03 11:31 ?747次閱讀

    C語(yǔ)言運(yùn)行環(huán)境是什么

    C語(yǔ)言運(yùn)行環(huán)境(C language runtime environment)是指在執(zhí)行C語(yǔ)言程序時(shí)所需的軟件及硬件環(huán)境。
    的頭像 發(fā)表于 11-27 16:13 ?2856次閱讀

    如何選擇創(chuàng)建c語(yǔ)言c++

    選擇創(chuàng)建 C 語(yǔ)言C++ 都需要綜合考慮多個(gè)因素。在決定使用哪種語(yǔ)言之前,我們需要對(duì)這兩種語(yǔ)言特點(diǎn)
    的頭像 發(fā)表于 11-27 15:58 ?455次閱讀

    嵌入式C語(yǔ)言的結(jié)構(gòu)特點(diǎn)

    嵌入式開(kāi)發(fā)中既有底層硬件的開(kāi)發(fā)又涉及上層應(yīng)用的開(kāi)發(fā),即涉及系統(tǒng)的硬件和軟件,C語(yǔ)言既具有匯編語(yǔ)言操作底層的優(yōu)勢(shì),又具有高級(jí)語(yǔ)言功能性強(qiáng)的特點(diǎn)
    的頭像 發(fā)表于 11-24 16:16 ?521次閱讀
    嵌入式<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>的結(jié)構(gòu)<b class='flag-5'>特點(diǎn)</b>

    \0在c語(yǔ)言中怎么用

    C語(yǔ)言是一種廣泛使用的程序設(shè)計(jì)語(yǔ)言,具有高效、簡(jiǎn)潔和可移植等特點(diǎn)。本文將詳盡介紹C語(yǔ)言的基本語(yǔ)法
    的頭像 發(fā)表于 11-24 09:59 ?2707次閱讀

    什么是C語(yǔ)言?單片機(jī)有什么特點(diǎn)?為什么要用C語(yǔ)言編程?

    隨著技術(shù)的發(fā)展,電子產(chǎn)品越來(lái)越多,方便了我們的日常生活,大多數(shù)電子產(chǎn)品上都有單片機(jī),而單片機(jī)是通過(guò)執(zhí)行軟件邏輯來(lái)實(shí)現(xiàn)功能的。而單片機(jī)編程最合適的編程語(yǔ)言是匯編語(yǔ)言,但是最常用、最普及的卻是C語(yǔ)
    的頭像 發(fā)表于 11-21 10:06 ?1318次閱讀
    什么是<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>?單片機(jī)有什么<b class='flag-5'>特點(diǎn)</b>?為什么要用<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>編程?

    C語(yǔ)言for循環(huán)的用法和注意事項(xiàng)

    C 語(yǔ)言是一種廣泛使用的編程語(yǔ)言,它具有簡(jiǎn)潔、高效、靈活的特點(diǎn)。C 語(yǔ)言中有很多控制流程的語(yǔ)句,
    的頭像 發(fā)表于 11-20 18:27 ?1689次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>for循環(huán)的用法和注意事項(xiàng)

    C++環(huán)形緩沖區(qū)設(shè)計(jì)與實(shí)現(xiàn)

    Buffer) 環(huán)形緩沖區(qū)(Circular Buffer),也被稱為循環(huán)緩沖區(qū)(Cyclic Buffer)或者環(huán)形隊(duì)列(Ring Buffer),是一種數(shù)據(jù)結(jié)構(gòu)類型,它在內(nèi)存中形成一個(gè)環(huán)
    的頭像 發(fā)表于 11-09 11:21 ?1273次閱讀
    <b class='flag-5'>C</b>++<b class='flag-5'>環(huán)形</b>緩沖區(qū)設(shè)計(jì)與實(shí)現(xiàn)

    無(wú)鎖隊(duì)列的潛在優(yōu)勢(shì)

    無(wú)鎖隊(duì)列 先大致介紹一下無(wú)鎖隊(duì)列。無(wú)鎖隊(duì)列的根本是CAS函數(shù)——CompareAndSwap,即比較并交換,函數(shù)功能可以用C++函數(shù)來(lái)說(shuō)明: int compare_and_swap
    的頭像 發(fā)表于 11-09 09:23 ?438次閱讀
    無(wú)鎖<b class='flag-5'>隊(duì)列</b>的潛在優(yōu)勢(shì)

    消息隊(duì)列的發(fā)展歷史

    上一篇我們用一個(gè)秒殺案例探討了我們?yōu)槭裁葱枰?b class='flag-5'>隊(duì)列。今天我們來(lái)回顧一下消息隊(duì)列的發(fā)展歷史。
    的頭像 發(fā)表于 10-30 10:49 ?866次閱讀
    消息<b class='flag-5'>隊(duì)列</b>的發(fā)展歷史