Co je kroužková vyrovnávací paměť?

Kruhová vyrovnávací paměť je také známá jako fronta nebo cyklická vyrovnávací paměť a je běžnou formou fronty. Jedná se o populární, snadno implementovaný standard a ačkoli je reprezentován jako kruh, je v základním kódu lineární. Prstenová fronta existuje jako pole pevných délek s dvěma ukazateli: jedna představuje začátek fronty a druhá - ocas. Nevýhodou metody je její pevná velikost. Pro fronty, kde musí být elementy přidány nebo odebrány uprostřed, a nikoliv pouze na začátku a na konci vyrovnávací paměti, implementace jako propojeného seznamu je nejlepším přístupem.

Teoretický základ vyrovnávací paměti

Uživatel je snadněji vybrán účinnou strukturu polí po pochopení základní teorie. Cyklus vyrovnávací paměti je datová struktura, kde je pole zpracováno a vizualizováno ve formě smyček, tj. Indexy se vrátí na 0 po dosažení délky pole. To se děje se dvěma ukazateli na poli: "hlava" a "ocas". Když jsou data přidána do vyrovnávací paměti, index záhlaví se posune nahoru. Podobně, když jsou odstraněny, ocas se také pohybuje nahoru. Definice hlavy, ocasu, směru pohybu, místa záznamu a čtení závisí na realizaci schématu.


Kruhové nárazníky jsou příliš efektivně použity k řešení spotřebitelských problémů. To znamená, že jeden inkrementální výkon je zodpovědný za tvorbu dat a druhý za spotřebu. Ve vestavěných zařízeních s velmi nízkou a střední úrovní je výrobce prezentován ve formátu ISR (informace získané od snímačů) a spotřebitel - ve forměhlavní cyklus událostí. Vlastností cyklických vyrovnávacích pamětí je to, že jsou implementovány bez nutnosti zámků v prostředí jednoho výrobce a jednoho zákazníka. To z nich činí ideální strukturu informací pro vestavěné aplikace. Dalším rozdílem je, že neexistuje přesný způsob rozlišování vyplněného sektoru od prázdného. Je to proto, že v obou případech se hlava spojuje s ocasem. Existuje mnoho způsobů a způsobů, jak s tím vypořádat, aby se s tím vyrovnali, ale většina z nich způsobuje, že je více matoucí a komplikuje čitelnost.


Další otázka, která vzniká ve vztahu k cyklickému bufferu. Potřebujete obnovit nová data nebo znovu nahrát existující data, když je plná? Odborníci se domnívají, že neexistuje zjevná výhoda nad sebou a její implementace závisí na konkrétní situaci. Pokud jsou pro aplikaci relevantnější, použijte metodu přepisu. Na druhou stranu, pokud jsou zpracovávány v režimu "první příjezd - nejprve podávaný", pak je nové, když je vyplněn prstencový vyrovnávací paměť.

Realizace cyklické fronty

Pokud jde o implementaci, jsou definovány datové typy a pak jsou metody jádro, push a pop. V postupech "push" a "pop" vypočítejte "takové" body posunu pro místo, ve kterém probíhá aktuální nahrávání a čtení. Pokud toto místo ukazuje na ocas, je vyrovnávací paměť plná a data nejsou zaznamenána. Podobně, když se "hlava" rovná "ocasu", je prázdná a z ní se nic nečíst.

Standardní verze použití

Pomocný postup nazývá programový procesk extrahování dat z vyrovnávací paměti Java. Měl by být zahrnut v kritických částech, pokud kontejner přečte více než jeden podproces. Chvost se přesune na další posun před čtením informací, protože každý blok je jeden byte a rezervuje stejné množství v vyrovnávací paměti, když je objem plně načten. V pokročilejších provedeních cyklického pohonu však nemusí být samostatné části nutně stejné velikosti. V takových případech se pokoušejí zachránit i poslední bajt, přidání dalších kontrol a hranic. V takových schématech, pokud se ocas pohybuje před čtením, informace, které je třeba číst, mohou být potenciálně přepsány nově přenášenými daty. Obecně se doporučuje číst nejprve a pak posunout ukazatel ocasu. Nejdříve určete délku vyrovnávací paměti a vytvořte instanci "circ_bbuf_t" a přiřaďte ukazatel na "maxlen". V takovém případě musí být kontejner celosvětový nebo skládaný. Například pokud potřebujete 32bajtový vyzváněcí tón, proveďte v přílohě následující (viz obrázek níže).
Specifikace funkčních požadavků
Typ dat "ring_t" bude typ dat, který obsahuje ukazatel na vyrovnávací paměť, její velikost, hlavičku a index ocasu a počítadlo dat. Funkce inicializace "ring_init ()" inicializuje vyrovnávací paměť na základě získání ukazatele na strukturu kontejneru vytvořené funkcí volání s určenou velikostí. Funkce ring_add () přidá bajt do dalšího volného místa v vyrovnávací paměti.Funkce odstranění ring_remove () vymaže bajt z nejstaršího dostupného místa v kontejneru. Ring nahlédnout na funkci «ring_peek () bude číst počet bajtů«uint8_t ‚count‘»s novým kruhového bufferu poskytnuté jako parametr, ale neodstraní žádná hodnoty přečtené z kontejneru. Vrátí počet skutečně čtených bajtů.
Funkce čištění kroužků „ring_clear ()“ instalace „ocas“ rovný „hlavy“ a zatížení „0“ ve všech polohách vyrovnávací paměti.

Vytvoření vyrovnávací paměti v C /C ++

Vzhledem k omezeným zdrojům vestavěných systémů datových struktur s cyklické vyrovnávací paměti nachází ve většině pevné velikosti projektů, které působí jako v případě, že paměť byla od přírody a kontinuální cyklické Tyto nemusí se pohybovat, protože paměť je generována a použita, upravené indexy hlava /ocas. Při vytváření knihovny cyklických vyrovnávacích pamětí musí uživatelé pracovat s API knihovny spíše než přímo měnit strukturu. Proto se používá zapouzdření kruhového pufru na "C". Tak se developer bude chránit knihovní implementaci, mění ji podle potřeby, aniž by bylo nutné pro koncové uživatele a aktualizovat.

Uživatelé mohou pracovat s «circular_but_t» typu ukazatel popisovač je vytvořen, které lze použít místo. To eliminuje potřebu řídit kurzor na implementaci funkcí «.typedefcbuf_handle_t». Vývojáři potřebují pro knihovnu vytvořit rozhraní API. Interakci s knihovnou cyklické vyrovnávací paměti «c», za použití neprůhledného typu deskriptorkterý je vytvořen během inicializace. Obvykle zvolte jako základní typ dat "uint8_t". Ale můžete použít jakýkoli konkrétní typ, dbát na to, aby správně zpracoval základní vyrovnávací paměť a počet bajtů. Uživatelé spolupracují s kontejnerem podle požadovaných postupů:
  • Inicializujte kontejner a jeho velikost.
  • Obnovte kruhový kontejner.
  • Přidejte data do vyrovnávací paměti kroužku na "C".
  • Z kontejneru získáte následující hodnotu.
  • Požádejte o informace o aktuálním počtu položek a maximální kapacitě.
  • A "plné" a "prázdné" případy vypadají stejně: "hlava" a "ocas", ukazatele jsou stejné. Existují dva přístupy, které rozlišují mezi plným a prázdným:
  • Kompletní stav konce + 1 == hlava.
  • Vyprázdněte stavovou hlavu == ocas.
  • Implementace funkcí knihovny

    Chcete-li vytvořit kruhový kontejner, použijte jeho strukturu pro ovládání stavu. Chcete-li uložit zapouzdření, je struktura definována v souboru knihovny .c a ne v záhlaví. Při instalaci je třeba sledovat:
  • Základní vyrovnávací paměť dat.
  • Maximální velikost.
  • Aktuální pozice hlavy se zvyšuje s přidáním.
  • Aktuální ocas, zvyšuje se po odstranění.
  • Vlajka označující naplněnou nádobu nebo ne.
  • Nyní, když je kontejner navržen, implementuje funkce knihovny. Každá rozhraní API vyžaduje inicializovaný deskriptor vyrovnávací paměti. Namísto zanesení kódu podmíněnými prohlášeními požádejte o schválení, abyste vynucovali požadavkyAPI ve velkém stylu.
    Implementace nebude orientována na proud, pokud do základní knihovny cyklických úložišť nebyla přidána žádná zámek. Pro inicializaci rozhraní API klienty, které poskytují velikost vyrovnávací paměti základny, je proto vytvořte na straně knihovny, například pro zjednodušení "malloc". Systémy, které nemohou používat dynamickou paměť, by měly změnit funkci "init" pro použití jiné metody, například výběru ze statického fondu kontejnerů. Dalším přístupem je přerušení zapouzdření, které umožňuje uživatelům staticky deklarovat kontejnerové struktury. V takovém případě je třeba aktualizovat "circular_buf_init" tak, aby získal ukazatel nebo "init", vytvořil strukturu zásobníku a vrátil ho. Avšak vzhledem k tomu, že zapouzdření je narušeno, uživatelé jej mohou upravit bez knihovních postupů. Po vytvoření kontejneru vyplňte hodnotu a způsobí "reset". Před návratováním z "init" systém zajistí, že kontejner je prázdný.

    Přidávání a mazání dat

    Přidávání a odstraňování dat z vyrovnávací paměti vyžaduje manipulaci z indikátorů "head" a "tail". Když je do kontejneru přidán, vložte novou hodnotu do aktuálních "head" -sites a propagujte je. Když jsou odstraněny, obdrží hodnotu současného "ocasního" indikátoru a propagují "ocas". Pokud chcete přesunout index "tail" a také "head", je třeba zkontrolovat, zda vkládání způsobí hodnotu "full". Když je vyrovnávací paměť již plná, přesuňte "ocas" o krok dopředu "hlava".
    Po pokročilém ukazateli zadejte "úplné" publikování,kontrola rovnosti "head == tail". Modulární použití operátora způsobí, že se při dosažení maximální velikosti vrátí "hlava" a "ocas" na hodnotu "0". To zajišťuje, že "head" a "tail" budou vždy platnými databázemi kontejneru pro základní údaje: "static void advance_pointer (cbuf_handle_t cbuf)". Můžete vytvořit podobnou pomocnou funkci, která se nazývá při mazání hodnot z vyrovnávací paměti.

    Rozhraní šablony

    Aby implementace C ++ podporovala jakýkoli typ dat, postupujte podle šablony:
  • Vyčistěte vyrovnávací paměť.
  • Přidávání a mazání dat.
  • ​​
  • Kontrola plného /prázdného stavu.
  • Kontrola aktuálního počtu položek.
  • Kontrola celkové kapacity kontejneru.
  • Aby nedošlo k zničení dat po odstranění vyrovnávací paměti, používají se inteligentní ukazatelé C ++, aby uživatelé mohli spravovat data.
  • V tomto příkladu vyrovnávací paměť C ++ simuluje většinu implementační logiky C, ale vede k mnohem čistějšímu a opakovaněji použitelnému návrhu. Navíc kontejner C ++ používá "std :: mutex" k poskytování aktuálně orientované implementace. Při vytváření třídy vyberte data pro hlavní vyrovnávací paměť a nastavte její velikost. Tím se vyloučí režie vyžadovaná implementací C. Na rozdíl od toho konstruktor C ++ nespustí "reset", protože specifikuje počáteční hodnoty členů, kruhový kontejner běží ve správném stavu. Zpět nahoru Dejte nám zpětnou vaz Při implementaci cyklického kontejneru "size" C ++ a"Kapacita" udává počet položek ve frontě, nikoliv velikost v bajtech.

    Ovladač UART STM32

    Po spuštění vyrovnávací paměti musí být integrován do ovladače UART. Nejprve jako globální prvek v souboru je tedy nutné deklarovat:
  • "descriptor_rbd" a vyrovnávací paměť "_rbmem: static rbd_t _rbd";
  • "statický znak"
    ".
  • Jelikož se jedná o ovladač UART, kde každá písmena musí být 8bitová, je přípustné vytvoření pole znaků. Pokud je použit 9 nebo 10 bitový režim, pak každý prvek by měl být "uint16_t". Kontejner je vypočítán tak, aby se zabránilo ztrátě dat. Frekvenční moduly často obsahují statistické informace, které umožňují sledovat maximální využití. V inicializační funkci "uart_init" musí být vyrovnávací paměť inicializována voláním "ring_buffer_init" a přenosem atributové struktury na každého člena, kterému jsou přiděleny sjednané hodnoty. Pokud je úspěšně inicializován, modul UART je vyveden z resetu, příjem přerušení je povolen v IFG2.
    Druhou změnou funkce je "uart_getchar". Čtení přijatého znaku z periferního zařízení UART se nahrazuje čtením z fronty. Je-li fronta prázdná, musí funkce vrátit -1. Poté musíte implementovat UART a získat ISR. Otevřete soubor záhlaví "msp430g2553.h", přejděte dolů na sekci vektorů přerušení, kde najde vektor s názvem USCIAB0RX. Pojmenování znamená, že se používá v modulech USCI A0 a B0. Stav přerušení příjmu USCI A0 lze přečíst z IFG2. Je-li nainstalován, má být příznak vymazán a data v přijímajícím oddílu jsou umístěna do vyrovnávací pamětipomocí "ring_buffer_put".

    skladování UART údajů

    Toto úložiště poskytuje informace o tom, jak číst data z UART pomocí DMA, když je počet bajtů pro příjem není znám. Rodina mikrokontrolérů vyrovnávací paměť STM32 může pracovat v různých režimech:
  • ANKETA (bez DMA, bez IRQ) - Žádost musí dotaz bitů stavu zjistit, zda nový znak a přečíst si to dost rychle, aby byly všechny bajty. Velmi jednoduchá implementace, ale nikdo ji nepoužívá v reálném životě. Nevýhody - je snadné chybět přijaté znaky v datových paktech, funguje pouze pro nízké přenosové rychlosti.
  • režimu (bez DMA) přerušit - kruhový buffer, běží UART přerušení a pokračuje CPU pro zpracování nástroj pro příjem dat. Nejrozšířenější přístup ve všech dnešních aplikacích funguje dobře ve střední řadě. Nevýhody - přerušení řízení se provádí u každého přijatého symbolu může zastavit další úkoly v oblasti vysoce výkonných mikroprocesorů s mnoha přerušeními, zatímco operační systém, když dostávali datové pakety.
  • Způsob DMA pro přenos dat z RX USART zaregistruje do paměti v hardwaru. V této fázi je nutná interakce s aplikací, s výjimkou v případě potřeby pro zpracování dat aplikace. Může být velmi snadné pracovat s operačními systémy. Optimalizováno pro vysoké přenosové rychlosti & gt; 1Mbps a nízkonapěťové aplikace, v případě velkých datových paketů se může zvýšit velikost vyrovnávací pamětifunkčnost.
  • Implementace ARDUINO

    Arduino Ribbon Buffer se vztahuje jak na návrh desek, tak na programovací prostředí, které se používá k práci. Jádrem Arduino je mikroprocesor řady Atmel AVR. Jedná se o AVR, která provádí většinu práce a v mnoha ohledech deska Arduino kolem AVR poskytuje funkce - snadno připojitelné kontakty, sériové rozhraní USB pro programování a komunikaci. Mnoho běžných karet společnosti Arduino v současné době používá kruhový buffer s staršími deskami ATmega 328, které používají ATmega168 a ATmega8. Desky jako Mega vybírají složitější možnosti, například 1280 a podobně. Čím rychleji a Zero, tím lepší využití ARM. Tam je asi deset různých Arduino desek s jmény. Mohou mít různé množství paměti flash, RAM a I /O portů s vyrovnávací pamětí AVR.
    Proměnná "roundBufferIndex" se používá k ukládání aktuální pozice a při přidání do vyrovnávací paměti bude existovat omezení pole.
    Toto jsou výsledky spuštění kódu. Čísla jsou uložena v vyrovnávací paměti a když jsou plné, začínají přepisovat. Takže můžete získat poslední čísla N.
    V předchozím příkladu byl index použit pro přístup k aktuální pozici vyrovnávací paměti, protože stačí vysvětlit operaci. Ale obecně je normální použít ukazatel. Toto je upravený kód pro použití ukazatele namísto indexu. V podstatě stejná operace jako předchozí a získané výsledky jsou podobné.

    Vysoce výkonné operace CAS

    Disruptor jeVysoce výkonná knihovna pro streamování zpráv, vyvinutá a otevřená před několika lety společností LMAX Exchange. Vytvořili tento software pro zvládnutí obrovské návštěvnosti (více než 6 milionů TPS) ve své maloobchodní obchodní platformě. V roce 2010 všichni překvapili, jak rychle může být jejich systém, a to po dokončení veškeré obchodní logiky v jednom vlákně. Zatímco jedno vlákno je důležité pojetí v jejich řešení, Disruptor běží v prostředí s více podprocesy a je založena na kruhové paměti - tok, ve kterém již není potřeba stará data, protože příchod čerstvější a více relevantní. V takovém případě bude fungovat buď návrat falešné logické hodnoty nebo zámek. Pokud žádný z těchto řešení nevyhovuje uživatelé mohou realizovat vyrovnávací měnit velikost, ale pouze tehdy, když je naplněn, a to pouze tehdy, pokud výrobce dosáhne konce pole. Změna velikosti vyžadují pohybující se všechny položky v nově přidělené větší soustavy při použití jako základní datové struktury, což je samozřejmě nákladné operace. Existuje mnoho dalších věcí, které dělají Disruptor rychlou, jako je dávkové zasílání zpráv. Kruhový buffer „qtserialport“ (sériový port) je převzat z QIODevice, mohou být použity pro různé sériových dat a zahrnuje všechna sériová zařízení. Sériový port je vždy otevřen pro výhradní přístup, což znamená, že další procesy nebo niti nelze přistupovat k otevřené seriálport Prstencové vyrovnávací paměti jsou velmi užitečné při programování pro "C", například můžete odhadnout proud bajtů přicházející přes UART.

    Související publikace