Kaj je obroček?

Vmesni pomnilnik je znan tudi kot čakalna vrsta ali ciklični medpomnilnik in je običajna oblika čakalne vrste. To je priljubljen in enostavno uveljavljen standard, ki je predstavljen kot krog, vendar je linearni v osnovni kodi. Obročna čakalna vrsta obstaja kot niz fiksnih dolžin z dvema kazalcema: ena predstavlja začetek čakalne vrste, druga pa rep. Pomanjkljivost metode je njena fiksna velikost. Za čakalne vrste, kjer je treba elemente dodati ali odstraniti na sredini in ne samo na začetku in na koncu medpomnilnika, je najboljši pristop izvajanje kot povezan seznam.

Teoretična osnova pufra

Uporabniku je lažje izbrati učinkovito strukturo nizov po razumevanju temeljne teorije. Cycle buffer je podatkovna struktura, kjer se polje obdeluje in vizualizira v obliki zank, kar pomeni, da se indeksi vrnejo na 0, ko dosežejo dolžino matrike. To naredimo z dvema kazalcema na matriki: "glava" in "rep". Ko so podatki dodani v medpomnilnik, se indeks naslova premakne navzgor. Podobno se tudi ob odstranitvi repa premakne navzgor. Opredelitev glave, repa, smeri gibanja, kraja beleženja in branja je odvisna od izvajanja sheme.


Krožni odbojniki se pretirano učinkovito uporabljajo za reševanje težav potrošnikov. To pomeni, da je en tok izvrševanja odgovoren za proizvodnjo podatkov, drugi za porabo. Pri vgrajenih napravah z zelo nizko in srednjo stopnjo je proizvajalec predstavljen v obliki ISR ​​(informacije, prejete od senzorjev), potrošnik pa v oblikiciklu glavnega dogodka. Značilnost cikličnih blažilnikov je, da se izvajajo brez zapornic v okolju enega proizvajalca in enega potrošnika. Zaradi tega so idealne informacijske strukture za vgrajene aplikacije. Naslednja razlika je v tem, da ni natančnega načina za razlikovanje zapolnjenega sektorja od praznega. To je zato, ker se v obeh primerih glava združi z repom. Obstajajo številni načini in sredstva, s katerimi se lahko ukvarjate s tem, vendar jih večina povzroča bolj zmedeno in zapleteno berljivost.


Drugo vprašanje, ki se pojavi v zvezi s cikličnim blažilnikom. Če želite, da se podatki obnovijo ali ponovno zapišejo obstoječe, ko je poln? Strokovnjaki trdijo, da ni očitne prednosti pred seboj in da je njegovo izvajanje odvisno od posamezne situacije. Če so slednje bolj relevantne za aplikacijo, uporabite metodo za ponovno pisanje. Po drugi strani pa, če so obdelani v načinu "prvi pride - prvi je vročen", potem zavrnite nove, ko je zapolnjen obročasti vmesnik.

Realizacija ciklične čakalne vrste

Ko gre za izvedbo, so definirani podatkovni tipi, nato pa so metode: jedro, push in pop. V postopkih "push" in "pop" izračunajte "takšne" točke premika za lokacijo, v kateri bo potekal trenutni zapis in branje. Če ta lokacija kaže na rep, je medpomnilnik poln in podatki niso zabeleženi. Podobno, ko je "glava" enaka "repu", je prazna in iz nje se nič ne bere.

Standardna različica uporabe

Pomožni postopek se imenuje s programskim postopkomza pridobivanje podatkov iz krožnega vmesnika Java. Vključiti ga je treba v kritične dele, če vsebnik prebere več kot eno nit. Rep se premakne na naslednjo izmeno, preden se informacija prebere, saj je vsak blok en bajt in rezervira enako količino v medpomnilniku, ko je volumen v celoti naložen. V naprednejših izvedbah cikličnega pogona pa ni nujno, da so ločeni odseki enake velikosti. V takih primerih poskušajo shraniti še zadnji bajt, pri čemer dodajo več kontrol in meja. V takšnih shemah, če se rep premika pred branjem, se lahko informacije, ki jih je treba brati, lahko prepišejo z novo prenešenimi podatki. Na splošno je priporočljivo najprej prebrati in nato premakniti kazalec repa. Najprej določite dolžino medpomnilnika in nato ustvarite primerek "circ_bbuf_t" in dodelite kazalec na "maxlen". V tem primeru mora biti vsebnik globalni ali zložen. Na primer, če potrebujete 32-bajtni obroček, izvedite naslednje v prilogi (glejte sliko spodaj).

Specifikacija funkcionalnih zahtev

Vrsta podatkov "ring_t" je vrsta podatkov, ki vsebuje kazalec na medpomnilnik, njegovo velikost, indeks glave in repa ter števec podatkov. Funkcija inicializacije "ring_init ()" inicializira medpomnilnik na podlagi pridobitve kazalca na strukturo vsebnika, ki ga ustvari klicna funkcija z določeno velikostjo. Funkcija ring_add () doda bajt naslednjemu razpoložljivemu prostoru v medpomnilniku.Funkcija odstranjevanja ring_remove () bo izbrisala bajt iz najstarejšega razpoložljivega prostora v vsebniku. Prstan zvonjenja v funkciji ring_peek () bo odčital število bajtov "uint8_t" štetje "iz obročnega pufra na novo, podano kot parameter, ne da bi odstranili vse vrednosti iz vsebnika. Vrne število dejansko prebranih bajtov.
Funkcija ring_clear () bo nastavila "Tail" enako "Head" in naložila "0" v vse položaje vmesnega pomnilnika.

Ustvarjanje vmesnega pomnilnika v C /C ++

Zaradi omejenih virov vgrajenih sistemov lahko podatkovno strukturo s cikličnim blažilnikom najdemo v večini projektov s fiksno velikostjo, ki delujejo kot da je spomin po naravi stalen in ciklično Podatkov ni treba preurediti, ker je pomnilnik ustvarjen in uporabljen, kazalniki glave /repa pa so popravljeni. Pri ustvarjanju ciklične knjižnice vmesnega pomnilnika morajo uporabniki delati z API-ji knjižnic, namesto da neposredno spreminjajo strukturo. Zato se uporabi kapsuliranje obročnega pufra na "C". Na ta način bo razvijalec shranil izvedbo knjižnice in jo po potrebi spremenil, ne da bi jo morali končni uporabniki tudi posodobiti.

Uporabniki ne morejo delati s kazalcem "circular_but_t" in ustvariti tip deskriptorja, ki ga je mogoče uporabiti. To odpravlja potrebo po premikanju kazalca za izvajanje funkcije .typedefcbuf_handle_t. Razvijalci morajo zgraditi API-je za knjižnico. Delujejo s knjižnico krožnega medpomnilnika "C" z neprozornim tipom deskriptorja,ki se ustvari med inicializacijo. Običajno izberete "uint8_t" kot osnovni podatkovni tip. Lahko pa uporabite kateri koli določen tip, pri tem pa pazite, da boste pravilno upravljali osnovni vmesnik in število bajtov. Uporabniki komunicirajo z vsebnikom tako, da sledijo zahtevanim postopkom:
  • Inicializirajte vsebnik in njegovo velikost.
  • Ponastavite krožni vsebnik.
  • Dodajte podatke v medpomnilnik na "C".
  • Iz vsebnika dobite naslednjo vrednost.
  • Zahtevajte informacije o trenutnem številu predmetov in največji zmogljivosti.
  • In "polni" in "prazni" primeri izgledajo enako: "glava" in "rep", kazalci so enaki. Obstajata dva pristopa, ki razlikujeta med polnim in praznim:
  • Popoln državni rep + 1 == glava.
  • Prazna državna glava == rep.
  • Izvajanje knjižničnih funkcij

    Za ustvarjanje krožnega vsebnika uporabite njegovo strukturo za nadzor stanja. Če želite shraniti enkapsulacijo, je struktura definirana v datoteki knjižnice .c in ne v glavi. Pri namestitvi boste morali slediti:
  • Osnovni podatkovni vmesnik.
  • Največja velikost.
  • Sedanji položaj glave se z dodajanjem poveča.
  • Tekoči rep se poveča, ko se odstrani.
  • Oznaka, ki označuje napolnjeno posodo ali ne.
  • Zdaj, ko je zabojnik zasnovan, izvaja knjižnične funkcije. Vsak API zahteva začetni deskriptor medpomnilnika. Namesto da bi kodo zamašili s pogojnimi stavki, zaprosite za odobritev za uveljavitev zahtevAPI v slogu.
    Izvajanje ne bo trenutno usmerjeno, če v osnovno knjižnico cikličnih skladišč ni bila dodana nobena ključavnica. Za inicializacijo API odjemalci, ki zagotavljajo velikost osnovnega medpomnilnika, jo ustvarijo na strani knjižnice, na primer za poenostavitev "malloc". Sistemi, ki ne morejo uporabljati dinamičnega pomnilnika, morajo spremeniti funkcijo "init" in uporabiti drugo metodo, kot je izbiranje iz statičnega nabora vsebnikov. Drugi pristop je prekinitev enkapsulacije, ki uporabnikom omogoča statično razglasitev struktur kontejnerjev. V tem primeru mora biti "circular_buf_init" posodobljen, da vzame kazalec ali "init", ustvari strukturo skladov in vrne. Ker pa je enkapsulacija motena, jo lahko uporabniki spremenijo brez knjižničnih postopkov. Ko je vsebnik ustvarjen, izpolnite vrednost in povzročite "reset". Pred vrnitvijo iz "init" sistem zagotavlja, da je vsebnik prazen.

    Dodajanje in brisanje podatkov

    Dodajanje in odstranjevanje podatkov iz medpomnilnika zahteva manipulacijo s kazalniki "glava" in "rep". Ko ga dodate v posodo, vstavite novo vrednost v trenutne "glave" in jo promovirajte. Ko jih odstranimo, prejmejo vrednost trenutnega "repa" - kazalca in spodbujajo "rep". Če želite premakniti indeks "rep" in tudi "glavo", morate preveriti, ali vstavljanje povzroči vrednost "polno". Ko je odbojnik že poln, premaknite "rep" en korak naprej "glava".
    Ko je kazalec napredoval, izpolnite "polno" -objavljanje,preverjanje enakosti "glava == rep". Modularna uporaba operaterja povzroči, da se "glava" in "rep" ponastavita na "0", ko je dosežena največja velikost. To zagotavlja, da bosta "glava" in "rep" vedno veljavna podatkovna zbirka osnovnega podatkovnega vsebnika: "statični void predpredaj (cbuf_handle_t cbuf)". Ustvarite lahko podobno pomožno funkcijo, ki se kliče pri brisanju vrednosti iz medpomnilnika.

    Vmesnik s predlogami

    Da bi izvedba C ++ lahko podprla vse vrste podatkov, sledite predlogi:
  • Ponastavite medpomnilnik na čiščenje.
  • Dodajanje in brisanje podatkov.
  • ​​
  • Preverjanje popolnega /praznega stanja.
  • Preverjanje trenutnega števila postavk.
  • Preverjanje skupne zmogljivosti posode.
  • Da ne bi pustili nobenih podatkov po uničenju medpomnilnika, se uporabljajo inteligentni kazalci C ++, da se zagotovi, da lahko uporabniki upravljajo podatke.
  • V tem primeru medpomnilnik C ++ simulira večino logike implementacije C, toda ima za posledico veliko čistejšo in večkrat uporabno zasnovo. Poleg tega vsebnik C ++ uporablja "std :: mutex" za zagotavljanje trenutne usmerjenosti. Pri izdelavi razreda izberite podatke za glavni medpomnilnik in nastavite njegovo velikost. To odpravlja režijske stroške, ki jih zahteva izvedba C. Za razliko od tega, konstruktor C ++ ne povzroči "ponastavitve", ker določa začetne vrednosti članov članov, krožni vsebnik teče v pravilnem stanju. Ponastavitveno obnašanje vrne medpomnilnik v prazno stanje. Pri izvajanju C ++ "velikosti" cikličnega vsebnika in"Kapaciteta" poroča o številu elementov v čakalni vrsti, ne pa o velikosti v bajtih.

    Voznik UART STM32

    Po zagonu medpomnilnika mora biti integriran v gonilnik UART. Najprej kot globalni element v datoteki je zato treba razglasiti:
  • "descriptor_rbd" in vmesni pomnilnik "_rbmem: static rbd_t _rbd";
  • "statični char _rbmem
    ".
  • Ker je to voznik UART, kjer mora biti vsak znak 8-bitni, je dovoljeno ustvarjanje niza znakov. Če uporabljate 9 ali 10 bitni način, mora biti vsak element "uint16_t". Posoda se izračuna tako, da se prepreči izguba podatkov. Pogosto moduli čakalnih vrst vsebujejo statistične informacije, ki omogočajo sledenje največji možni uporabi. V inicializacijski funkciji "uart_init" mora biti medpomnilnik inicializiran s klicem "ring_buffer_init" in prenosom strukture atributov na vsakega člana, kateremu so dodeljene dogovorjene vrednosti. Če je uspešno inicializiran, je modul UART izhod iz resetiranja, prekinitveni sprejem je dovoljen v IFG2.
    Druga funkcija, ki jo je treba spremeniti, je "uart_getchar". Branje prejetega znaka iz periferne naprave UART se zamenja z branjem iz čakalne vrste. Če je čakalna vrsta prazna, mora funkcija vrniti -1. Nato morate uvesti UART, da dobite ISR. Odprite datoteko z glavo "msp430g2553.h", pomaknite se navzdol do odseka prekinjenih vektorjev, kjer najde vektor z imenom USCIAB0RX. Imenovanje pomeni, da ga uporabljajo moduli USCI A0 in B0. Stanje prekinitve sprejemanja USCI A0 se lahko odčita iz IFG2. Če je nameščen, je treba oznako izbrisati, podatki v sprejemnem predelu pa se shranijo v medpomnilnikz uporabo "ring_buffer_put".

    Shranjevanje podatkov UART

    To skladišče vsebuje informacije o tem, kako brati UART podatke z DMA, ko je število bajtov, ki jih je treba prejeti vnaprej, neznano. Družina krožnih vmesnikov STM32 lahko deluje v različnih načinih:
  • Način javljanja (brez DMA, brez IRQ) - aplikacija mora preizkusiti stanje bitov, da preveri, ali je bil nov znak sprejet in ga prebere dovolj hitro, da dobi vse bajte. Zelo preprosta izvedba, vendar je nihče ne uporablja v resničnem življenju. Cons - to je enostavno zamuditi prejete znake v paketih podatkov, deluje le za nizke hitrosti prenosa.
  • Način prekinitve (brez DMA) - obročni medpomnilnik UART prekine prekinitev in CPU preide v servisni program za obdelavo sprejema podatkov. Najbolj razširjen pristop v vseh aplikacijah danes dobro deluje v srednjem razponu. Cons - postopek prekinitve obdelave se izvede za vsak prejeti znak, lahko ustavi druge naloge v visoko zmogljivih mikrokontrolerjih z velikim številom prekinitev in hkrati operacijskim sistemom ob prejemu podatkovnega paketa.
  • Način DMA se uporablja za prenos podatkov iz registra USART RX v pomnilnik na ravni strojne opreme. Na tej stopnji interakcija z aplikacijo ni potrebna, razen potrebe po obdelavi podatkov, ki jih prejme aplikacija. Z operacijskimi sistemi je lahko zelo enostavno delati. Optimizirano za visoke hitrosti prenosa podatkov & gt; 1Mbps in aplikacije z nizko porabo energije, v primeru velikih podatkovnih paketov se lahko poveča velikost medpomnilnikafunkcionalnosti.
  • Izvajanje v programu ARDUINO

    Vmesnik za trakove Arduino se nanaša na oblikovanje plošč in programsko okolje, ki se uporablja za delo. Arduino jedro je mikrokrmilnik serije Atmel AVR. Večino dela opravlja AVR, v več pogledih pa Arduino plošča okoli AVR-a zagotavlja funkcionalnost - preprosto priključite stike, USB-serijski vmesnik za programiranje in komunikacijo. Veliko rednih Arduinovih kartic trenutno uporablja ring buffer z ATmega 328 starejšimi matičnimi ploščami, ki so uporabljale ATmega168 in ATmega8. Plošče, kot je Mega, izbirajo bolj zapletene možnosti, kot sta 1280 in podobno. Hitrejša je uporaba orodja ARM. Obstaja okoli deset različnih Arduino plošč z imeni. Imajo lahko različno količino pomnilnika flash, RAM in I /O vrat z vmesnikom AVR.
    Spremenljivka "roundBufferIndex" se uporablja za shranjevanje trenutnega položaja in pri dodajanju v medpomnilnik obstaja omejitev matrike.
    To so rezultati izvajanja kode. Številke so shranjene v medpomnilniku in ko so polne, začnejo pisati. Tako lahko dobite zadnje N številke.
    V prejšnjem primeru je bil indeks uporabljen za dostop do trenutnega položaja medpomnilnika, ker je dovolj, da pojasni operacijo. Na splošno pa je normalno uporabljati kazalec. To je spremenjena koda za uporabo kazalca namesto indeksa. V bistvu je ista operacija kot prejšnja in dobljeni rezultati podobni.

    Operacije CAS visoke učinkovitosti

    Disruptor jeVisoko zmogljiva knjižnica za pretakanje sporočil, ki jo je pred nekaj leti razvila in odprla LMAX Exchange. To programsko opremo so ustvarili za obvladovanje ogromnega prometa (več kot 6 milijonov TPS) v svoji maloprodajni finančni trgovalni platformi. V letu 2010 so vse presenetili, kako hitro bi lahko bil njihov sistem, saj so vse poslovne logike izpolnili v eni niti. Čeprav je bila ena nit v njihovi rešitvi pomemben koncept, Disruptor deluje v večnitnem okolju in temelji na obročnem medpomnilniku - toku, v katerem zastareli podatki niso več potrebni, saj prihaja bolj sveže in bolj pomembno. V tem primeru bo ali vrnitev lažne logične vrednosti ali ključavnica delovala. Če nobena od teh rešitev ne zadovolji uporabnikov, je mogoče implementirati spreminjajoči se medpomnilnik, vendar le, ko je napolnjen, in ne samo, če proizvajalec doseže konec matrike. Spreminjanje velikosti bo zahtevalo premik vseh elementov v novo dodeljeno večje polje, če se uporablja kot osnovna podatkovna struktura, kar je seveda draga operacija. Obstaja veliko drugih stvari, zaradi katerih je Disruptor hiter, kot je pošiljanje sporočil v paketnem načinu. Zobni blažilnik qtserialport (zaporednih vrat) je podedoval od QIODevice, lahko se uporablja za pridobivanje različnih serijskih informacij in vključuje vse razpoložljive serijske naprave. Serijska vrata so vedno odprta pri monopolnem dostopu, kar pomeni, da drugi procesi ali niti ne morejo dostopati do odprtega zaporedjapristanišča Ring buffers so zelo uporabni pri programiranju za "C", na primer, lahko ocenite tok bajtov, ki prihajajo skozi UART.

    Sorodne publikacije