{"id":53751,"date":"2019-12-09T00:00:00","date_gmt":"2019-12-08T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash"},"modified":"2020-02-18T14:01:41","modified_gmt":"2020-02-18T11:01:41","slug":"moya-realizatsiya-koltsevogo-bufera-v-nor-flash","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash","title":{"rendered":"Minu rakendus ringbuffer NOR flashis","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h1 id=\"predystoriya\">Eellugu<\/h1>\n<p><\/p>\n<p>Meil on oma arendatud m\u00fc\u00fcgiautomaadid. Sees on Raspberry Pi ja veidi lisaplaati. \u00dchendatud on m\u00fcndiproovija, pangakaardilugeja\u2026 K\u00f5ike haldab ise kirjutatud programm. Kogu t\u00f6\u00f6 ajalugu salvestatakse flash-m\u00e4lupessa (MicroSD), mis edastatakse seej\u00e4rel interneti kaudu (USB-modemi abil) serverisse, kus see s\u00e4ilitatakse andmebaasis. M\u00fc\u00fcgiteave laaditakse 1C-sse, samuti on olemas lihtne veebiliides j\u00e4lgimiseks jne. <\/p>\n<p><\/p>\n<p>See t\u00e4hendab, et ajakiri on eluliselt vajalik - arvestamiseks (seal on tulu, m\u00fc\u00fcgid jms), j\u00e4lgimiseks (k\u00f5iksugu t\u00f5rked ja muud eriolukorrad); see on, v\u00f5iks \u00f6elda, kogu teave, mis meil selle automaadi kohta on. <\/p>\n<p><\/p>\n<h1 id=\"problema\">Probleem<\/h1>\n<p><\/p>\n<p>Flash-m\u00e4lud osutuvad v\u00e4ga ebakindlateks seadmeteks. Need riknevad \u00fcpris regulaarselt. See toob kaasa nii automaatide seiskumisi kui ka (kui mingil p\u00f5hjusel ei saanud ajakirja online edastada) andmete kadumise.<\/p>\n<p><\/p>\n<p><em>See ei ole esimene kogemus flash-m\u00e4lude kasutamisest, enne seda oli teistsugune projekt, kus oli rohkem kui sada seadet, kus ajalugu hoiti USB-flash-m\u00e4ludel, seal olid samuti usaldusv\u00e4\u00e4rsuse probleemid, m\u00f5nikord oli kuu jooksul riknenud m\u00e4lude arv k\u00fcmnetes. Proovisime erinevaid flash-m\u00e4lusid, sealhulgas ka SLC m\u00e4luga br\u00e4nditud, jah, m\u00f5ned mudelid on usaldusv\u00e4\u00e4rsemad kui teised, kuid flash-m\u00e4lude vahetamine ei lahendanud probleemi kardinaalselt.<\/em><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <\/p>\n<p><strong>T\u00e4helepanu!<\/strong> \u041b\u043e\u043d\u0433\u0440\u0438\u0434! \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e &#171;\u043f\u043e\u0447\u0435\u043c\u0443&#187;, \u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e &#171;\u043a\u0430\u043a&#187;, \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u0438\u0434\u0442\u0438 <noindex><a rel=\"nofollow\" href=\"#format\">l\u00f5ppu<\/a><\/noindex> artiklist.<\/p>\n<p><\/p>\n<h1 id=\"reshenie\">Lahendus<\/h1>\n<p><\/p>\n<p>Esimene m\u00f5te, mis tuleb meelde: loobuda MicroSD-st, panna n\u00e4iteks SSD ja laadida sealt. Teoreetiliselt on see v\u00f5ib-olla v\u00f5imalik, kuid suhteliselt kallis ja mitte v\u00e4ga usaldusv\u00e4\u00e4rne (lisandub USB-SATA adapter; odavate SSD-de riketestatistika ei ole samuti julgustav).<\/p>\n<p><\/p>\n<p>USB HDD ei tundu samuti eriti atraktiivne lahendus.<\/p>\n<p><\/p>\n<p>Seet\u00f5ttu j\u00f5udsime sellise variandini: j\u00e4tta laadimine MicroSD-lt, kuid kasutada neid read-only re\u017eiimis, ning t\u00f6\u00f6 ajalugu (ja muu konkreetse seadme jaoks unikaalne teave - seerianumber, sensorite kalibreerimine jne) hoida kuskil mujal. <\/p>\n<p><\/p>\n<p>Read-only failis\u00fcsteemide teema Raspberry Pi jaoks on juba p\u00f5hjalikult uuritud, ma ei hakka selle artikli raames detailidele peatuma. <em>(kuid kui huvi on - v\u00f5ib-olla kirjutan selle teema kohta mini-artikli)<\/em>. Ainuke punkt, mida tahaksin m\u00e4rkida: nii isikliku kogemuse kui ka juba rakendanud tagasiside p\u00f5hjal on paranduste usaldusv\u00e4\u00e4rsuses olemas. Jah, t\u00e4ielikult rikete eest p\u00e4\u00e4seda ei saa, kuid nende sagedust on t\u00e4iesti reaalne oluliselt v\u00e4hendada. Ja ka kaartide vormingud muutuvad \u00fchtseks, mis muudab teenindava personali asenduse oluliselt lihtsamaks.<\/p>\n<p><\/p>\n<h2 id=\"apparatnaya-chast\">Riistvara<\/h2>\n<p><\/p>\n<p>M\u00e4lu t\u00fc\u00fcbi valik ei tekitanud erilisi kahtlusi \u2014 NOR Flash.<br \/>\nArgumentid: <\/p>\n<p><\/p>\n<ul>\n<li>\u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 (\u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0448\u0438\u043d\u0430 SPI, \u043e\u043f\u044b\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c, \u0442\u0430\u043a \u0447\u0442\u043e &#171;\u0436\u0435\u043b\u0435\u0437\u043d\u044b\u0445&#187; \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043d\u0435 \u043f\u0440\u0435\u0434\u0432\u0438\u0434\u0438\u0442\u0441\u044f);<\/li>\n<li>naljakas hind;<\/li>\n<li>standardne t\u00f6\u00f6protokoll (rakendus on juba Linuxi tuumas olemas, soovi korral v\u00f5ib v\u00f5tta ka kolmanda osapoole lahenduse, mida on samuti saadaval, v\u00f5i isegi kirjutada oma, hea, et k\u00f5ik on lihtne);<\/li>\n<li>usaldusv\u00e4\u00e4rsus ja ressurss:<br \/>\nt\u00fc\u00fcpilisest andmelehelt: andmed s\u00e4ilitab 20 aastat, 100000 kustutamists\u00fcklit iga bloki kohta;<br \/>\nv\u00e4listest allikatest: \u00e4\u00e4rmiselt madal BER, v\u00e4idetakse, et vea parandamise koodide vajadust ei ole <em>(m\u00f5nedes teadustes k\u00e4sitletakse ECC-d NOR-i jaoks, kuid tavaliselt peetakse seal silmas MLC NOR-i, nii et selline asi juhtub ka)<\/em>.<\/li>\n<\/ul>\n<p><\/p>\n<p>Hinnatakse n\u00f5udeid mahu ja ressursi osas.<\/p>\n<p><\/p>\n<p>Soov on, et andmed s\u00e4ilitaksid garantii korral mitu p\u00e4eva. See on vajalik selleks, et igasuguste sideprobleemide korral ei kaoks m\u00fc\u00fcgihaja ajalugu. Suundume 5 p\u00e4eva poole, mille jooksul <em>(isegi arvestades n\u00e4dalavahetusi ja p\u00fchi)<\/em> probleemi lahendada.<\/p>\n<p><\/p>\n<p>Meil koguneb n\u00fc\u00fcd \u00f6\u00f6p\u00e4evas umbes 100 kb logi (3-4 tuhat kirje), kuid j\u00e4rk-j\u00e4rgult see number kasvab \u2014 detailide arv suureneb, lisanduvad uued s\u00fcndmused. Lisaks esinevad m\u00f5nikord puhangud (m\u00f5ni sensor hakkab valeh\u00e4iretega spammima, n\u00e4iteks). Arvestagem 10 tuhande kirje peale 100 baiti \u2014 megabait p\u00e4evas.<\/p>\n<p><\/p>\n<p>Seega tuleb kokku 5 MB puhast (h\u00e4sti pigistatavat) andmeid. Nendele veel <em>(harjumusp\u00e4rane hinnang)<\/em> 1 MB teenindusandmeid.<\/p>\n<p><\/p>\n<p>Seda silmas pidades on meie vajadus mikroskeemi j\u00e4rele 8 MB, kui me ei kasuta kokkusurumist, v\u00f5i 4 MB, kui me seda teeme. Need on t\u00e4iesti reaalsed numbrid selle t\u00fc\u00fcpi m\u00e4lu jaoks.<\/p>\n<p><\/p>\n<p>Mida ressurssi puutub: kui planeerime, et m\u00e4lu kirjutatakse t\u00e4ielikult \u00fcle mitte sagedamini kui iga 5 p\u00e4eva tagant, siis 10-aastase teenuse jooksul saame v\u00e4hem kui tuhat \u00fcle kirjutamise ts\u00fcklit.<br \/>\nTuletan meelde, et tootja lubab sada tuhat.<\/p>\n<p>\n<b class=\"spoiler_title\">Veidi NOR vs NAND-ist<\/b><\/p>\n<p>T\u00e4na on muidugi NAND m\u00e4lu tunduvalt populaarsem, kuid selle projekti jaoks ma seda kasutada ei soovitaks: NAND, erinevalt NORist, n\u00f5uab kindlasti vigade parandamise koode, rikkeplokkide tabeleid jne., ja NAND mikrokiipide jalgade arv on tavaliselt samuti suurem.<\/p>\n<p><\/p>\n<p>NORi puuduseks v\u00f5ib m\u00e4rkida:<\/p>\n<p><\/p>\n<ul>\n<li>v\u00e4ike maht (ja seega k\u00f5rge hind megabaiti kohta);<\/li>\n<li>madal edastuskiirus (peamiselt seet\u00f5ttu, et kasutatakse j\u00e4rjestikku liidest, tavaliselt SPI v\u00f5i I2C);<\/li>\n<li>aeglane kustutamine (s\u00f5ltuvalt ploki suurusest v\u00f5tab see m\u00f5nest osast sekundist kuni mitme sekundini).<\/li>\n<\/ul>\n<p><\/p>\n<p>Tundub, et miski pole kriitiline, nii et j\u00e4tkame.<\/p>\n<p><\/p>\n<p>Kui detailid huvitavad, on valitud mikrokiip <noindex><a rel=\"nofollow\" href=\"https:\/\/www.adestotech.com\/wp-content\/uploads\/doc3686.pdf\">at25df321a<\/a><\/noindex> <em>(kuigi see ei oma suurt t\u00e4htsust, on turul palju analooge, mis on \u00fchenduste ja k\u00e4skude osas \u00fchilduvad; isegi kui tahame kasutada teise tootja mikrokiipi ja\/v\u00f5i teise mahtu, t\u00f6\u00f6tab see koodi muutmata)<\/em>.<\/p>\n<p><\/p>\n<p>Kasutangi Linuxi tuuma sisse ehitatud draiverit, Raspberryl, t\u00e4nu seadmepuu overlaytoetusele, on k\u00f5ik v\u00e4ga lihtne \u2014 tuleb panna \/boot\/overlaysse kompileeritud overlay ja teha veidi muudatusi \/boot\/config.txt.<\/p>\n<p>\n<b class=\"spoiler_title\">N\u00e4ide dts failist<\/b><\/p>\n<p>Austusega \u00f6eldes ei ole ma kindel, et see on kirjutatud vigadeta, kuid see t\u00f6\u00f6tab.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">\/*\n * Device tree overlay for at25 at spi0.1\n *\/\n\n\/dts-v1\/;\n\/plugin\/;\n\n\/ {\n    compatible = \"brcm,bcm2835\", \"brcm,bcm2836\", \"brcm,bcm2708\", \"brcm,bcm2709\"; \n\n    \/* disable spi-dev for spi0.1 *\/\n    fragment@0 {\n        target = &lt;&amp;spi0&gt;;\n        __overlay__ {\n            status = \"okay\";\n            spidev@1{\n                status = \"disabled\";\n            };\n        };\n    };\n\n    \/* the spi config of the at25 *\/\n    fragment@1 {\n        target = &lt;&amp;spi0&gt;;\n        __overlay__ {\n            #address-cells = &lt;1&gt;;\n            #size-cells = &lt;0&gt;;\n            flash: m25p80@1 {\n                    compatible = \"atmel,at25df321a\";\n                    reg = &lt;1&gt;;\n                    spi-max-frequency = &lt;50000000&gt;;\n\n                    \/* default to false:\n                    m25p,fast-read ;\n                    *\/\n            };\n        };\n    };\n\n    __overrides__ {\n        spimaxfrequency = &lt;&amp;flash&gt;,\"spi-max-frequency:0\";\n        fastread = &lt;&amp;flash&gt;,\"m25p,fast-read?\";\n    };\n};<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">Ja veel \u00fcks rida config.txt-s<\/b><\/p>\n<pre><code class=\"plaintext\">dtoverlay=at25:spimaxfrequency=50000000<\/code><\/pre>\n<p><\/p>\n<p>Mikrokiibi \u00fchendamise kirjelduse vahele j\u00e4tan. \u00dchest k\u00fcljest ei ole ma elektroonika spetsialist, teisest k\u00fcljest on see minu jaoks isegi liiga lihtne: mikrokiibil on vaid 8 jalga, millest me vajame maapinda, toiteallikat ja SPI-d (CS, SI, SO, SCK); tasemed kattuvad Raspberry Pi omadega, t\u00e4iendavat toitekaablit ei ole vaja \u2014 lihtsalt \u00fchendage kuus mainitud kontakti.<\/p>\n<p><\/p>\n<h2 id=\"postanovka-zadachi\">\u00dclesande seadmine<\/h2>\n<p><\/p>\n<p>Nagu tavaliselt, l\u00e4bib \u00fclesande seadmine mitu iteratsiooni, ma arvan, et on aeg j\u00e4rgmise jaoks. Nii et peatugem, kogume kokku selle, mis on juba kirjutatud, ja selgitame v\u00e4lja varjatud detailid.<\/p>\n<p><\/p>\n<p>Nii oleme otsustanud, et ajakiri hoitakse SPI NOR Flashis.<\/p>\n<p>\n<b class=\"spoiler_title\">Mis on NOR Flash, neile, kes ei tea<\/b><\/p>\n<p>See on energiateadlik m\u00e4lu, millega saab teha kolme operatsiooni:<\/p>\n<p><\/p>\n<ol>\n<li>Lugemine:<br \/>\nTavaline lugemine: edastame aadressi ja loeme nii palju baite, kui vajame;<\/li>\n<li>Salvestamine:<br \/>\nNOR flash'i kirjutamine n\u00e4ib olevat tavaline, kuid sel on \u00fcks erip\u00e4ra: saab ainult muuta 1-ks 0, kuid mitte vastupidi. N\u00e4iteks, kui meie m\u00e4lu rakus oli 0x55, siis p\u00e4rast 0x0f kirjutamist salvestatakse seal juba 0x05. <em>(vt allolevat tabelit)<\/em>;<\/li>\n<li>Kustutamine:<br \/>\nMuidugi peame suutma teha ka vastupidist operatsiooni \u2014 muuta 0-ks 1, just selleks on olemas kustutamise operatsioon. Erinevalt esimestest kahest, toimib see mitte baitidega, vaid plokkidega (valitud mikroskeemi minimaalne kustutusplokk on 4 kB). Kustutamine h\u00e4vitab kogu ploki ja see on ainus viis 0 muuta 1-ks. Seet\u00f5ttu tuleb flash-m\u00e4luga t\u00f6\u00f6tades sageli andmestruktuure joondada kustutusploki piirile.<br \/>\nNOR Flash'i kirjutamine:<\/li>\n<\/ol>\n<p><\/p>\n<p>Binaarsed andmed<\/p>\n<p><strong>See oli<\/strong><br \/>\n<code>01010101<\/code><\/p>\n<p><strong>Kirjutasime<\/strong><br \/>\n<code>00001111<\/code><\/p>\n<p><strong>Muutus<\/strong><br \/>\n<code>00000101<\/code><\/p>\n<p><\/p>\n<p>Ise ajakiri esindab muutuva pikkusega kirjeid. T\u00fc\u00fcpiline kirje pikkus on umbes 30 baiti (kuigi m\u00f5nikord v\u00f5ib esineda ka mitme kilobaidi pikkuseid kirjeid). <em>Selles osas t\u00f6\u00f6tame nendega lihtsalt kui baitide kogumiga, kuid kui on huvitav, siis kirjete sees kasutatakse CBOR'i.<\/em><\/p>\n<p><\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0436\u0443\u0440\u043d\u0430\u043b\u0430, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e &#171;\u043d\u0430\u0441\u0442\u0440\u043e\u0435\u0447\u043d\u0443\u044e&#187; \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043a\u0430\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c\u0443\u044e, \u0442\u0430\u043a \u0438 \u043d\u0435\u0442: \u043d\u0435\u043a\u0438\u0439 ID \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u0430, \u043a\u0430\u043b\u0438\u0431\u0440\u043e\u0432\u043a\u0438 \u0434\u0430\u0442\u0447\u0438\u043a\u043e\u0432, \u0444\u043b\u0430\u0433 &#171;\u0430\u043f\u043f\u0430\u0440\u0430\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d&#187;, etc.<br \/>\nSee teave esindab v\u00f5tme-v\u00e4\u00e4rtuse kirjeid, mis samuti salvestatakse CBOR'is. Meil ei ole seda teavet v\u00e4ga palju (kuni paar kilobaiti), see uuendatakse harva.<br \/>\nEdaspidi nimetame seda kontekstiks.<\/p>\n<p><\/p>\n<p>Kui meenutada, millest see artikkel algas, on v\u00e4ga oluline tagada andmete usaldusv\u00e4\u00e4rne hoidmine ja, kui v\u00f5imalik, katkematu t\u00f6\u00f6 ka seadme riketel v\u00f5i andmekahjustusel.<\/p>\n<p><\/p>\n<p>Milliseid probleemide allikaid saaks kaaluda?<\/p>\n<p><\/p>\n<ul>\n<li>\u041e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0438\u0442\u0430\u043d\u0438\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 write\/erase. \u042d\u0442\u043e \u0438\u0437 \u0440\u0430\u0437\u0440\u044f\u0434\u0430 &#171;\u043f\u0440\u043e\u0442\u0438\u0432 \u043b\u043e\u043c\u0430 \u043d\u0435\u0442 \u043f\u0440\u0438\u0451\u043c\u0430&#187;.<br \/>\nTeave aadressilt <noindex><a rel=\"nofollow\" href=\"https:\/\/electronics.stackexchange.com\/questions\/225956\/what-would-happen-in-case-of-power-outage-during-nor-flash-erase-or-programming\">arutelu<\/a><\/noindex> \u043d\u0430 stackexchange: \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043f\u0438\u0442\u0430\u043d\u0438\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 flash \u0447\u0442\u043e erase (\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 1), \u0447\u0442\u043e write (\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432 0) \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a undefined behavior: \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f, \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e (\u0441\u043a\u0430\u0436\u0435\u043c, \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 10 \u0431\u0430\u0439\u0442\/80 \u0431\u0438\u0442, \u0430 \u0443\u0441\u043f\u0435\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e 45 \u0431\u0438\u0442), \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0438 \u0442\u043e, \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u0431\u0438\u0442\u043e\u0432 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0432 &#171;\u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u043c&#187; \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 (\u0447\u0442\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0430\u0442\u044c \u043a\u0430\u043a 0, \u0442\u0430\u043a \u0438 1);<\/li>\n<li>Flash-m\u00e4lu enda vead.<br \/>\nBER on kuigi v\u00e4ga madal, kuid ei tohi olla null;<\/li>\n<li>Bussi vead<br \/>\nSPI kaudu edastatavad andmed ei ole mingil viisil kaitstud, v\u00f5ivad tekkida nii \u00fcksikud bitivead kui ka s\u00fcnkroonimisvead \u2014 bitide kaotus v\u00f5i lisamine (mis viib massiliste andmete moonutusteni);<\/li>\n<li>Muud vead\/rikkumised<br \/>\n\u041e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435, &#171;\u0433\u043b\u044e\u043a\u0438&#187; Raspberry, \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e \u0438\u043d\u043e\u043f\u043b\u0430\u043d\u0435\u0442\u044f\u043d&#8230;<\/li>\n<\/ul>\n<p><\/p>\n<p>Olen s\u00f5nastanud n\u00f5uded, mille t\u00e4itmine on minu arvates vajalik usaldusv\u00e4\u00e4rsuse tagamiseks:<\/p>\n<p><\/p>\n<ul>\n<li>salvestused peavad minema kohe m\u00e4lupulgale, edasil\u00fckatud salvestust ei arvestata; - kui viga tekib, siis peab see avastatama ja t\u00f6\u00f6tlemine toimuma v\u00f5imalikult varakult; - s\u00fcsteem peab v\u00f5imalusel taastama t\u00f6\u00f6 p\u00e4rast vigu.<br \/>\n<em>(\u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0436\u0438\u0437\u043d\u0438 &#171;\u043a\u0430\u043a \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c&#187;, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c, \u0434\u0443\u043c\u0430\u044e, \u0432\u0441\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c: \u043f\u043e\u0441\u043b\u0435 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 &#171;\u043f\u043e\u0431\u0438\u043b\u0430\u0441\u044c&#187; \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0435 \u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f)<\/em><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"idei-podhody-razmyshleniya\">Ideed, l\u00e4henemised, m\u00f5tted<\/h2>\n<p><\/p>\n<p>Kui hakkasin sellele \u00fclesandele m\u00f5tlema, liikusid mu peas ringi hulgaliselt ideid, n\u00e4iteks:<\/p>\n<p><\/p>\n<ul>\n<li>kasutada andmete tihendamist;<\/li>\n<li>kasutada nutikaid andmestruktuure, n\u00e4iteks hoida salvestuste p\u00e4iseid eraldi iseenesest salvestustest, et vigade korral saaksid teised andmed probleemideta lugeda;<\/li>\n<li>kasutada bitifiltreid salvestuse l\u00f5petamise kontrollimiseks toite v\u00e4ljal\u00fclitamisel;<\/li>\n<li>hoida kontrollsummasid k\u00f5igi ja k\u00f5ige kohta;<\/li>\n<li>kasutada mingisugust vigadele vastupidavat kodeerimist.<\/li>\n<\/ul>\n<p><\/p>\n<p>Osad neist ideedest olid kasutusel, m\u00f5nel oli otsustanud loobuda. Vaatame j\u00e4rjestikku.<\/p>\n<p><\/p>\n<h3 id=\"szhatie-dannyh\">Andmete kokkusurumine<\/h3>\n<p><\/p>\n<p>\u0421\u0430\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b\u0435, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c\u044b\u0435 (&#171;\u043a\u0438\u043d\u0443\u043b\u0438 \u043c\u043e\u043d\u0435\u0442\u043a\u0443 5 \u0440\u0443\u0431\u043b\u0435\u0439&#187;, &#171;\u043d\u0430\u0436\u0430\u043b\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0432\u044b\u0434\u0430\u0447\u0438 \u0441\u0434\u0430\u0447\u0438&#187;, &#8230;). \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0436\u0430\u0442\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c.<\/p>\n<p><\/p>\n<p>Tihendamise kulud on ebaolulised (meie protsessor on piisavalt v\u00f5imas, isegi esimesel Pi-l oli \u00fcks tuum 700 MHz-l, t\u00e4nap\u00e4evastes mudelites on mitu tuuma, mille sagedus \u00fcletab gigahertsi), andmesalvestuse vahetuskiirus ei ole k\u00f5rge (m\u00f5ned megabait sekundis), salvestuste suurus on v\u00e4ike. \u00dcldiselt, kui tihendamine mingil moel j\u00f5udlust m\u00f5jutab, siis ainult positiivselt. <em>(absoluutselt mitte kriitiline, lihtsalt konstateerin)<\/em>. Plus meil ei ole ju p\u00e4ris embedded, vaid tavaline Linux \u2013 seega implementatsioon ei peaks n\u00f5udma palju pingutust (piisab lihtsalt raamatukogude lingimisest ja m\u00f5ne funktsiooni kasutamisest sealt).<\/p>\n<p><\/p>\n<p>V\u00f5eti t\u00fckk logifailist t\u00f6\u00f6tavast seadmest (1,7MB, 70 tuhat kirje) ja alguses kontrolliti selle kokkusurumisv\u00f5imet olemasolevate programmide gzip, lz4, lzop, bzip2, xz, zstd abil.<\/p>\n<p><\/p>\n<ul>\n<li>gzip, xz, zstd n\u00e4itasid sarnaseid tulemusi (40KB).<br \/>\n\u00dcllatas, et trendikas xz n\u00e4itas end siin gzipi v\u00f5i zstd tasemel;<\/li>\n<li>lzip vaikeseadetega andis veidi halvemad tulemused;<\/li>\n<li>lz4 ja lzop n\u00e4itasid mitte eriti head tulemust (150KB);<\/li>\n<li>bzip2 n\u00e4itas \u00fcllatavalt head tulemust (18KB).<\/li>\n<\/ul>\n<p><\/p>\n<p>Nii et andmed on v\u00e4ga h\u00e4sti tihendatavad.<br \/>\nSeega (kui me ei leia fataalseid puudusi) tihendamine peaks toimuma! Lihtsalt sellep\u00e4rast, et sama m\u00e4lupulgale mahtuda rohkem andmeid.<\/p>\n<p><\/p>\n<p>M\u00f5elgem puudustele.<\/p>\n<p><\/p>\n<p>Esimene probleem: me oleme juba kokku leppinud, et iga kirje peab viivitamatult minema m\u00e4lupulgale. Tavaliselt kogub arhiveerija andmeid sisendvoogudest kuni otsustab, et on aeg kirjutada v\u00e4ljundisse. Meie peame aga kohe saama tihendatud andmepaketi ja salvestama selle mitte-volatile m\u00e4llu.<\/p>\n<p><\/p>\n<p>N\u00e4en kolme teed:<\/p>\n<p><\/p>\n<ol>\n<li>Tihendada iga kirje s\u00f5naraamatutihenduse abil, mitte eelnevalt k\u00e4siteldu algoritmide kaudu.<br \/>\n\u0412\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043d\u043e \u043c\u043d\u0435 \u043e\u043d \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u0414\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u0440\u0438\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u0441\u0436\u0430\u0442\u0438\u044f \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c &#171;\u0437\u0430\u0442\u043e\u0447\u0435\u043d&#187; \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043b\u044e\u0431\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u0438\u044f \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0430\u0434\u0430\u0435\u0442. \u0414\u0430, \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u044f, \u043d\u043e \u044d\u0442\u043e \u0436\u0435 \u0433\u043e\u043b\u043e\u0432\u043d\u0430\u044f \u0431\u043e\u043b\u044c \u2014 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043b\u043e\u0432\u0430\u0440\u044f; \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441 \u043a\u0430\u043a\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u044f \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u0441\u0436\u0430\u0442\u0430&#8230;<\/li>\n<li>\u0421\u0436\u0438\u043c\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c &#171;\u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438&#187; \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438, \u043d\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445.<br \/>\nK\u00e4sitletavad kokkusurumise algoritmid ei ole m\u00f5eldud selliste suurte kirjetega t\u00f6\u00f6tamiseks (k\u00fcmned baitid), tihenduskoefitsient on ilmselt v\u00e4iksem kui 1 (st andmete mahu suurenemine, mitte kokkusurumine);<\/li>\n<li>Teha FLUSH p\u00e4rast iga kirjet.<br \/>\nPaljuski tihendamisraamatukogudes on FLUSH-i tugi. See on k\u00e4sk (v\u00f5i parameeter tihendamisprotseduurile), mille saades arhiveerija loob tihendatud voog, et sellest l\u00e4htudes saaks taastada <strong>k\u00f5ik<\/strong> tihendamata andmed, mis on juba saadud. Selline analoog <code>sync<\/code> failis\u00fcsteemides v\u00f5i <code>commit<\/code> SQLis.<br \/>\nOluline on, et j\u00e4rgnevad tihendamisoperatsioonid saavad kasutada akumuleeritud s\u00f5nastikku ning tihendusaste ei kannata nii palju nagu eelnevas variandi puhul.<\/li>\n<\/ol>\n<p><\/p>\n<p>M\u00f5tlen, et on ilmselge, et valisin kolmanda variandi, peatume sellel l\u00e4hemalt.<\/p>\n<p><\/p>\n<p>L\u00f6ydettiin <noindex><a rel=\"nofollow\" href=\"https:\/\/www.bolet.org\/~pornin\/deflate-flush.html\">suurep\u00e4rane artikkel<\/a><\/noindex> FLUSH-ist zlib-is.<\/p>\n<p><\/p>\n<p>Tehtud inspiratsiooniks artiklist, tegin katse, v\u00f5ttes 70 tuhat p\u00e4ringut p\u00e4ringute logidest reaalsetelt seadmetelt, kui lehe suurus on 60 KB <em>(lehe suuruse juurde me veel naaseme)<\/em> sain:<\/p>\n<p><\/p>\n<p>Algandmed<br \/>\ngzip tihendamine -9 (ilma FLUSHita)<br \/>\nzlib Z_PARTIAL_FLUSH-iga<br \/>\nzlib Z_SYNC_FLUSH-iga<\/p>\n<p><strong>Maht, KB<\/strong><br \/>\n1692<br \/>\n40<br \/>\n352<br \/>\n604<\/p>\n<p><\/p>\n<p>Esmapilgul tundub, et FLUSH-i hind on \u00fclem\u00e4\u00e4ra k\u00f5rge, kuid tegelikult on meie valik vaene \u2014 kas mitte \u00fcldse tihendada v\u00f5i tihendada (ja v\u00e4ga efektiivselt) FLUSH-iga. \u00c4rge unustage, et meil on 70 tuhat kirjet, Z_PARTIAL_FLUSH-i toodu \u00fcleliigusus on ainult 4-5 baiti kirje kohta. Tihenduskoefitsient osutus peaaegu 5:1, mis on suurep\u00e4rane tulemus.<\/p>\n<p>\n<b class=\"spoiler_title\">\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u043c, \u043d\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 Z_SYNC_FLUSH &#8212; \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u0435\u043b\u0430\u0442\u044c FLUSH<\/b><\/p>\n<p>Kui kasutada Z_SYNC_FLUSH-i, on iga kirje nelja viimast baiti alati 0x00, 0x00, 0xff, 0xff. Kui need on meile teada \u2014 siis me ei pea neid salvestama, seega on l\u00f5plik suurus vaid 324 KB.<\/p>\n<p><\/p>\n<p>Artiklis, millele viitan, on seletus:<\/p>\n<p><\/p>\n<blockquote><p>Uus t\u00fc\u00fcp 0 blokk t\u00fchjade sisudega lisatakse.<\/p>\n<p>T\u00fc\u00fcp 0 blokk t\u00fchjade sisudega koosneb:<\/p>\n<ul>\n<li>kolmest bitist koosnevast ploki p\u00e4isest;<\/li>\n<li>0 kuni 7 bitti, mis on v\u00f5rdsed nulliga, et saavutada baitide joondamine;<\/li>\n<li>neljast baitist koosnevast j\u00e4rjestusest 00 00 FF FF.<\/li>\n<\/ul>\n<p>\n<\/p><\/blockquote>\n<p>Nagu ei ole keeruline m\u00e4rgata, esimeses plokis enne neid 4 baiti on 3 kuni 10 nullbitid. Kuid praktika on n\u00e4idanud, et nullbitte on tegelikult v\u00e4hemalt 10.<\/p>\n<p><\/p>\n<p>Selgub, et nii l\u00fchikesed andmeplokid kodeeritakse tavaliselt (alati?) ploki t\u00fc\u00fcp 1 (fikseeritud plokk), mis kindlasti l\u00f5ppeb 7 nullbiti, kokku 10-17 garanteeritud nullbitti (ja \u00fclej\u00e4\u00e4nud on nullid umbes 50% t\u00f5en\u00e4osusega).<\/p>\n<p><\/p>\n<p>Seega 100% juhtudel testandmetel on enne 0x00, 0x00, 0xff, 0xff \u00fcks nullbait, ja rohkem kui kolmandal juhul \u2014 kaks nullbaidi. <em>(v\u00f5ib-olla on asi selles, et kasutan binaarset CBOR-i, ja tekstilisel JSON-il oleksime v\u00f5inud sagedamini kohata t\u00fc\u00fcp 2 plokke \u2014 d\u00fcnaamiline plokk, vastavalt oleksime kohanud plokke ilma lisanduvate nullbaitideta enne 0x00, 0x00, 0xff, 0xff)<\/em>.<\/p>\n<p><\/p>\n<p>Kokkuv\u00f5ttes on olemasolevate testandmete p\u00f5hjal v\u00f5imalik mahtuda alla 250 KB tihendatud andmeid.<\/p>\n<p><\/p>\n<p>Saame veel natukene kokku hoida, tegeledes bittide \u017eongleerimisega: praegu ignoreerime mitme nullbiti olemasolu ploki l\u00f5pus, samuti ei muutu m\u00f5ned bitid ploki alguses...<br \/>\nAga siis tegin ma tahteotsuse peatuda, muidu v\u00f5in sellise tempoga j\u00f5uda oma arhiiveri loomiseni.<\/p>\n<p><\/p>\n<p>Kokkuv\u00f5ttes sain oma testandmetelt 3-4 baiti kirjutamiseks, kompressioonikordaja oli \u00fcle 6:1. Ausalt \u00f6eldes: ma ei oodanud sellist tulemust, minu arvates on k\u00f5ik, mis on parem kui 2:1 \u2014 juba tulemus, mis \u00f5igustab kompressiooni kasutamist.<\/p>\n<p><\/p>\n<p>K\u00f5ik on suurep\u00e4rane, kuid zlib (deflate) on ikkagi arkaalne, tuntud ja veidi vanamoeline kompressioonialgoritm. Ainult see, et s\u00f5naraamatuks kasutatakse viimaseid 32Kb tihendamata andmeid, tundub t\u00e4na kummaline (st kui m\u00f5ni andmeplokk sarnaneb sellele, mis oli sisendis 40Kb tagasi, siis hakkab see uuesti arhiivima, mitte ei viita varasemale esinemisele). Moodne kaasaegne arhiiver m\u00f5\u00f5dab s\u00f5naraamatu suurust tihti megabaitides, mitte kilobaitides.<\/p>\n<p><\/p>\n<p>Nii et j\u00e4tkame meie mini-uuringut arhiivide \u00fcle.<\/p>\n<p><\/p>\n<p>J j\u00e4rgmiseks prooviti bzip2 (tuletan meelde, et ilma FLUSHita n\u00e4itas see fantastilist tihendust, peaaegu 100:1). Kahjuks FLUSHiga ei andnud ta end h\u00e4sti tunda, tihendatud andmete suurus oli suurem kui tihendamata.<\/p>\n<p>\n<b class=\"spoiler_title\">Minu oletused eba\u00f5nnestumise p\u00f5hjustest<\/b><\/p>\n<p>Libbz2 pakub ainult \u00fchte flush-varianti, mis tundub olevat s\u00f5naraamatu puhastamine (analoog Z_FULL_FLUSH zlibis), r\u00e4\u00e4kida mingist t\u00f5husast tihendamisest p\u00e4rast seda ei saa.<\/p>\n<p><\/p>\n<p>Viimaseks prooviti zstd. Olenevalt parameetritest tihendab ta kas gzipi tasemel, kuid palju kiiremini, v\u00f5i paremini kui gzip.<\/p>\n<p><\/p>\n<p>\u0423\u0432\u044b, \u0441 FLUSH \u0438 \u043e\u043d \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u0441\u0435\u0431\u044f &#171;\u043d\u0435 \u043e\u0447\u0435\u043d\u044c&#187;: \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0436\u0430\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0448\u0435\u043b \u043e\u043a\u043e\u043b\u043e 700\u041a\u0431.<\/p>\n<p><\/p>\n<p>Mina <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/zstd\/issues\/900\">esitasin k\u00fcsimuse<\/a><\/noindex> projekti lehe kaudu githubis, sain vastuse, et tuleb arvestada kuni 10 baiti haldusandmeid iga tihendatud andmeploki kohta, mis on l\u00e4hedal saadud tulemustele, deflate'i mitte mingil juhul ei saavuta.<\/p>\n<p><\/p>\n<p>Sellega otsustasin arhiivide katsetamisel peatuda (tuletan meelde, et xz, lzip, lzo, lz4 ei n\u00e4idanud ennast veel FLUSHi testimise etapis, ja ma ei hakanud arvestama eksootiliste tihendamisalgoritmidega).<\/p>\n<p><\/p>\n<p>Naaseme arhiivimise probleemide juurde.<\/p>\n<p><\/p>\n<p>Teine probleem (nagu \u00f6eldakse j\u00e4rjestuse, mitte t\u00e4henduse j\u00e4rgi) on, et kokkusurutud andmed esindavad \u00fchtset voogu, kus pidevalt viidatakse eelnevatele segmentidele. Seega, kui m\u00f5ni kokkusurutud andmete segment on kahjustatud, kaotame mitte ainult seotud lahtised andmed, vaid ka k\u00f5ik j\u00e4rgnevad.<\/p>\n<p><\/p>\n<p>Selle probleemi lahendamiseks on mitu l\u00e4henemist:<\/p>\n<p><\/p>\n<ol>\n<li>Probleemi ennetamine \u2014 lisada kokkusurutud andmetesse \u00fcleliigsust, mis v\u00f5imaldab vigu tuvastada ja parandada; sellest r\u00e4\u00e4gime hiljem;<\/li>\n<li>Minimeerida tagaj\u00e4rjed h\u00e4ire tekkimisel.<br \/>\nOleme varem r\u00e4\u00e4kinud, et iga andmeploki saab kokku suruda s\u00f5ltumatult, mis t\u00e4hendab, et probleem kaob iseenesest (\u00fche bloki andmete rikkumine viib ainult selle bloki andmete kaotamiseni). Siiski on see \u00e4\u00e4rmuslik olukord, kus andmete kokkusurumine osutub ebaefektiivseks. Teine \u00e4\u00e4rmus: kasutada k\u00f5iki 4MB meie kiipi kui \u00fchte arhiivi, mis annab meile suurep\u00e4rase kokkusurumise, kuid katastroofilised tagaj\u00e4rjed andmete rikkumise korral.<br \/>\n<em>Jah, usaldusv\u00e4\u00e4rsuse osas on vajalik kompromiss. Kuid tuleb meeles pidada, et me t\u00f6\u00f6tame v\u00e4lja andmete salvestamise formaati energiat mitte vajavas m\u00e4lus, millel on \u00e4\u00e4rmiselt madal BER ja deklareeritud andmete s\u00e4ilitamise aeg 20 aastat.<\/em><\/li>\n<\/ol>\n<p><\/p>\n<p>Eksperimentide k\u00e4igus avastasin, et m\u00e4rgatavad kokkusurumise taseme kaotused algavad alla 10KB suurustes kokkusurutud andmeplokkides.<br \/>\n\u0420\u0430\u043d\u0435\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u043c\u0435\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u0443\u044e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e, \u044f \u043d\u0435 \u0432\u0438\u0436\u0443 \u043f\u0440\u0438\u0447\u0438\u043d, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 &#171;\u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u2014 \u043e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u0441\u0436\u0430\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445&#187;.<\/p>\n<p><\/p>\n<p>Seega on minimaalne m\u00f5istlik lehe suurus 16KB (koos varuga teenindusteabe jaoks). Siiski seab nii v\u00e4ike lehe suurus m\u00e4rkimisv\u00e4\u00e4rseid piiranguid maksimaalse andmereservi suurusele.<\/p>\n<p><\/p>\n<p>Kuigi ma ei prognoosi hetkel suuremaid kui \u00fches kilobaidis kokkusurutud salvestusi, otsustasin kasutada 32KB suuruseid lehti (kokku 128 lehte kiibi kohta).<\/p>\n<p><\/p>\n<p><strong>Kokkuv\u00f5te:<\/strong><\/p>\n<p><\/p>\n<ul>\n<li>Salvestame andmed kokkusurutud kujul zlib (deflate) abil;<\/li>\n<li>Iga salvestuse jaoks seadistame Z_SYNC_FLUSH;<\/li>\n<li>Igal kokkusurutud salvestusel l\u00f5ikame \u00e4ra l\u00f5ppbaidid, <em>(n\u00e4iteks 0x00, 0x00, 0xff, 0xff)<\/em>; pealkirjas n\u00e4itame, kui palju baite oleme l\u00f5iganud;<\/li>\n<li>Andmed salvestatakse lehtedena 32 kb kaupa; lehe sees on \u00fchtne kokkupressitud andmevoog; iga lehe jaoks alustame kokkupressimist uuesti.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ja enne, kui l\u00f5petame kokkupressimise, tahaksin juhtida t\u00e4helepanu sellele, et meil \u00f5nnestub kokkupressida vaid paar baitit salvestuse kohta, seega on \u00e4\u00e4rmiselt oluline mitte puhtust teavet paisutada, iga bait on siin arvesse v\u00f5etud.<\/p>\n<p><\/p>\n<h3 id=\"hranenie-zagolovkov-dannyh\">Andmepealkirjade salvestamine<\/h3>\n<p><\/p>\n<p>Kuna meil on muutuva pikkusega salvestused, peame kuidagi m\u00e4\u00e4rama salvestuste asukoha\/piirid.<\/p>\n<p><\/p>\n<p>Ma tean kolme l\u00e4henemist:<\/p>\n<p><\/p>\n<ol>\n<li>K\u00f5ik salvestused on salvestatud katkematusse voogu, k\u00f5igepealt tuleb salvestuse pealkiri, mis sisaldab pikkust, ja seej\u00e4rel endine salvestus.<br \/>\nSelles variandis v\u00f5ivad nii pealkirjad kui ka andmed olla muutuva pikkusega.<br \/>\nSisuliselt on meil \u00fchek\u00fclgne loend, mida kasutatakse pidevalt;<\/li>\n<li>Pealkirjad ja salvestused ise on salvestatud eraldi voogudes.<br \/>\nKasutades kindla pikkusega pealkirju, saavutame selle, et \u00fche pealkirja rike ei m\u00f5juta teisi.<br \/>\nSarnast l\u00e4henemist kasutatakse n\u00e4iteks paljudes failis\u00fcsteemides;<\/li>\n<li>Salvestused on salvestatud katkematusse voogu, salvestuse piir m\u00e4\u00e4ratakse teatud m\u00e4rgiste (s\u00fcmbolid\/s\u00fcmbolite jada, mis on andmeblokis keelatud) j\u00e4rgi. Kui salvestuses leidub marker, siis asendame selle teatud jadaga (ekreerime selle).<br \/>\nSarnast l\u00e4henemist kasutatakse n\u00e4iteks PPP protokollis.<\/li>\n<\/ol>\n<p><\/p>\n<p>Illustreerin.<\/p>\n<p><\/p>\n<p>Variant 1:<br \/>\n<img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/e5a9676ca21eaca07e64ddf9fcd9f2eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSiin on k\u00f5ik v\u00e4ga lihtne: teades salvestuse pikkust, saame arvutada j\u00e4rgmise pealkirja aadressi. Nii liigume pealkirjade vahel, kuni leiame 0xFF-ga t\u00e4idetud ala (vaba ala) v\u00f5i lehe l\u00f5puni.<\/p>\n<p><\/p>\n<p>Variant 2:<br \/>\n<img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/4fed4860fb659ab6042be9aeeb5c041a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n\u0418\u0437-\u0437\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (\u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432) \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. \u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043d\u0435\u0441\u0442\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0438 \u0441\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c, \u043d\u043e \u043c\u043d\u0435 \u0441\u0438\u043c\u043f\u0430\u0442\u0438\u0447\u043d\u0435\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434: \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438, \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 (\u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430) \u0443 \u043d\u0430\u0441 \u0438\u0434\u0443\u0442 \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 \u0434\u0430\u043d\u043d\u044b\u0435 (\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b) \u2014 \u043e\u0442 \u043a\u043e\u043d\u0446\u0430. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d\u0438 &#171;\u0432\u0441\u0442\u0440\u0435\u0442\u044f\u0442\u0441\u044f&#187; (\u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c) \u2014 \u0441\u0447\u0438\u0442\u0430\u0435\u043c \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0439.<\/p>\n<p><\/p>\n<p>Variant 3:<br \/>\n<img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/dfb64009aa7781fcb8a47423ff4160c6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSiin pole vajadust hoida p\u00e4ises pikkust v\u00f5i muid andmete asukoha kohta k\u00e4ivaid andmeid, piisab markeritest, mis t\u00e4histavad kirjete piire. Siiski tuleb andmeid t\u00f6\u00f6delda kirjutamisel\/loodud.<br \/>\nMarkerina kasutaksin 0xff (millega leht on t\u00e4idetud p\u00e4rast kustutamist), seega ei t\u00f5lgendata vabatahtlikku ala t\u00f5eks.<\/p>\n<p><\/p>\n<p>V\u00f5rdlustabel:<\/p>\n<p><\/p>\n<p>Variant 1<br \/>\nOption 2<br \/>\nVariant 3<\/p>\n<p><strong>Vigade taluvus<\/strong><br \/>\n\u2014<br \/>\n+<br \/>\n+<\/p>\n<p><strong>Kompaktsus<\/strong><br \/>\n+<br \/>\n\u2014<br \/>\n+<\/p>\n<p><strong>Rakendamise keerukus<\/strong><br \/>\n*<br \/>\n**<br \/>\n**<\/p>\n<p><\/p>\n<p>Esimesel variandil on surmav puudus: kui m\u00f5ni p\u00e4is on kahjustatud, siis h\u00e4vib kogu j\u00e4rgmine ahel. \u00dclej\u00e4\u00e4nud variandid v\u00f5imaldavad taastada osa andmeid isegi massiliste kahjustuste korral.<br \/>\n\u041d\u043e \u0442\u0443\u0442 \u0443\u043c\u0435\u0441\u0442\u043d\u043e \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u0436\u0430\u0442\u043e\u043c \u0432\u0438\u0434\u0435, \u0442\u0430\u043a \u0438 \u0442\u0430\u043a \u043c\u044b \u0442\u0435\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u043e\u0441\u043b\u0435 &#171;\u0431\u0438\u0442\u043e\u0439&#187; \u0437\u0430\u043f\u0438\u0441\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u0445\u043e\u0442\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0438 \u0441\u0442\u043e\u0438\u0442 \u043c\u0438\u043d\u0443\u0441, \u043c\u044b \u0435\u0433\u043e \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c.<\/p>\n<p><\/p>\n<p>Kompaktsus:<\/p>\n<p><\/p>\n<ul>\n<li>esimeses variandis peame p\u00e4ises hoidma ainult pikkust, kui kasutada t\u00e4isarve muutuva pikkusega, siis enamikul juhtudel piisab \u00fchest baitist;<\/li>\n<li>teises variandis peame hoidma algset aadressi ja pikkust; kirje peaks olema pideva suurusega, hindan 4 baiti kirje kohta (kaks baiti nihke jaoks ja kaks baiti pikkuse jaoks);<\/li>\n<li>kolmandale variandile piisab vaid \u00fchest s\u00fcmbolist kirje alguse t\u00e4histamiseks, pluss ise kirje t\u00e4nu ekraanile suureneb 1-2%. \u00dcldiselt on ligikaudne pariteet esimese variandiga.<\/li>\n<\/ul>\n<p><\/p>\n<p>Alguses kaalusin teist varianti p\u00f5hjalikult (ja isegi kirjutasin teostuse). L\u00f5petasin selle, kui otsustasin l\u00f5puks kasutada kokkusurumist.<\/p>\n<p><\/p>\n<p><em>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u044f \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043a\u043e\u0440\u0430\u0431\u043b\u044f, \u043a\u0443\u0440\u0441\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u043c\u0435\u0436\u0434\u0443 \u0417\u0435\u043c\u043b\u0451\u0439 \u0438 \u041c\u0430\u0440\u0441\u043e\u043c \u2014 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0441\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u0437\u043b\u0443\u0447\u0435\u043d\u0438\u0435, &#8230;<\/em><\/p>\n<p><\/p>\n<p>Mis puutub kolmandasse variandisse: panin sellele kaks t\u00e4hte rakendamise keerukuse t\u00f5ttu, lihtsalt seet\u00f5ttu, et ma ei armasta ninaga tegelemist ekraanide, pikkuste muutmiseks jne. Jah, v\u00f5ib-olla olen kallutatud, kuid koodi pean ma ikkagi kirjutama \u2014 miks sundida end tegema seda, mis ei meeldi.<\/p>\n<p><\/p>\n<p><strong>Kokkuv\u00f5te:<\/strong> \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0446\u0435\u043f\u043e\u0447\u0435\u043a &#171;\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b&#187; \u0438\u0437-\u0437\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p><\/p>\n<h3 id=\"ispolzovanie-bitovyh-poley-dlya-kontrolya-uspeshnosti-operaciy-zapisi\">Bitiv\u00e4ljade kasutamine kirje kirjutamise operatsioonide eduka kontrollimise jaoks<\/h3>\n<p><\/p>\n<p>Ma ei m\u00e4leta enam, kust ma selle idee sain, aga see n\u00e4eb enam-v\u00e4hem v\u00e4lja nii:<br \/>\nIga kirje jaoks eraldame mitu bitti lipu salvestamiseks.<br \/>\n<em>Kuidas me varem r\u00e4\u00e4kisime, p\u00e4rast erase\u2019it on k\u00f5ik bitid t\u00e4idetud 1-ga ja saame muuta 1 0-ks, aga mitte vastupidi.<\/em> \u0422\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f &#171;\u0444\u043b\u0430\u0433 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d&#187; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c 1, \u0434\u043b\u044f &#171;\u0444\u043b\u0430\u0433 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d&#187; \u2014 0.<\/p>\n<p><\/p>\n<p>Nii v\u00f5ib v\u00e4lja n\u00e4ha muutuva pikkusega kirje paigutamine flash-m\u00e4lu:<\/p>\n<p><\/p>\n<ol>\n<li>Seame lipu \"kirje pikkus algas\";<\/li>\n<li>Salvestame pikkuse;<\/li>\n<li>Seame lipu \"andmete salvestamine algas\";<\/li>\n<li>Salvestame andmed;<\/li>\n<li>Seame lipu \"salvestamine l\u00f5ppes\".<\/li>\n<\/ol>\n<p><\/p>\n<p>Lisaks on meil \"tekkis viga\" lipp, kokku 4 bitilist lippu.<\/p>\n<p><\/p>\n<p>Sellisel juhul on meil kaks stabiilset olekut \"1111\" \u2014 salvestamine ei alanud ja \"1000\" \u2014 salvestamine \u00f5nnestus; ootamatul salvestamisprotsessi katkestamisel saame vahepealsed olekud, mille saame hiljem tuvastada ja k\u00e4sitleda.<\/p>\n<p><\/p>\n<p>L\u00e4henemine on huvitav, kuid see kaitseb ainult ootamatute toitekatkestuste ja sarnaste t\u00f5rgete eest, mis on muidugi t\u00e4htis, kuid see ei ole kaugeltki ainus (ja isegi mitte peamine) v\u00f5imalik t\u00f5rgete p\u00f5hjus.<\/p>\n<p><\/p>\n<p><strong>Kokkuv\u00f5te:<\/strong> Liigume edasi, otsides head lahendust.<\/p>\n<p><\/p>\n<h3 id=\"kontrolnye-summy\">Kontrollsummad<\/h3>\n<p><\/p>\n<p>Kontrollsummad pakuvad ka v\u00f5imalust veenduda (piisava t\u00f5en\u00e4osusega), et loeme just seda, mis pidi olema salvestatud. Ja erinevalt eelnevalt arutatud bitiv\u00e4ljadest t\u00f6\u00f6tavad nad alati.<\/p>\n<p><\/p>\n<p>Kui vaadata potentsiaalsete probleemide loetelu, millest me r\u00e4\u00e4kisime, suudab kontrollsumma tuvastada vea s\u00f5ltumata selle p\u00e4ritolust <em>(v.a. v\u00f5ib-olla pahatahtlikud v\u00e4lismaali inimesed \u2014 need v\u00f5ivad ka kontrollsummat valeh\u00e4irega petta)<\/em>.<\/p>\n<p><\/p>\n<p>Seega, kui meie eesm\u00e4rk on kontrollida, et andmed on terved, on kontrollsummad suurep\u00e4rane m\u00f5te.<\/p>\n<p><\/p>\n<p>Kontrollsummade arvutamise algoritmi valik ei tekitanud k\u00fcsimusi \u2014 CRC. \u00dchelt poolt v\u00f5imaldavad matemaatilised omadused 100% tuvastada teatud t\u00fc\u00fcpi vigu, teiselt poolt n\u00e4itab see algoritm juhuslike andmete puhul tavaliselt kokkulangevuste t\u00f5en\u00e4osust mitte oluliselt suurem kui teoreetiline piir. <img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/bf9cca3564db7d9d03d3ce49642d3a71.jpg\" style=\"display:block;margin: 0 auto;\" \/>Olgu see mitte k\u00f5ige kiirem algoritm, mitte alati minimaalne kokkup\u00f5rgete arvu poolest, kuid tal on \u00fcks v\u00e4ga oluline omadus: testides, millega olen kokku puutunud, ei ole olnud mustreid, kus see selgelt eba\u00f5nnestuks. Stabiilsus on antud juhul peamine kvaliteet.<\/p>\n<p><\/p>\n<p>Rohke uurimist\u00f6\u00f6 n\u00e4ide: <noindex><a rel=\"nofollow\" href=\"http:\/\/amsoftware.narod.ru\/algo.html\">osa 1<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"http:\/\/amsoftware.narod.ru\/algo2.html\">Osa 2<\/a><\/noindex> <em>(linkidena narod.ru, vabandust)<\/em>.<\/p>\n<p><\/p>\n<p>Siiski ei ole kontrollsummade valimise \u00fclesanne veel l\u00f5ppenud, CRC on terve kontrollsummade perekond. Tuleb otsustada pikkuse \u00fcle ja seej\u00e4rel valida pol\u00fcnoom.<\/p>\n<p><\/p>\n<p>Kontrollsummade pikkuse valik ei ole nii lihtne k\u00fcsimus, kui esmapilgul tundub.<\/p>\n<p><\/p>\n<p>Illustreerime:<br \/>\nOlgu meil veavoodus iga bait <img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/89a9be2edf2a43cc9115eba37fa02fc8.jpg\" style=\"display:block;margin: 0 auto;\" \/> ja ideaalne kontrollsumma, arvutame keskmise veahulga miljoni kirje kohta:<\/p>\n<p><\/p>\n<p>Andmed, bait<br \/>\nKontrollsumma, bait<br \/>\nTuvastamata vead<br \/>\nVale tuvastamine<br \/>\nKokku vale signaalide arv<\/p>\n<p>1<br \/>\n0<br \/>\n1000<br \/>\n0<br \/>\n1000<\/p>\n<p>1<br \/>\n1<br \/>\n4<br \/>\n999<br \/>\n1003<\/p>\n<p>1<br \/>\n2<br \/>\n\u22480<br \/>\n1997<br \/>\n1997<\/p>\n<p>1<br \/>\n4<br \/>\n\u22480<br \/>\n3990<br \/>\n3990<\/p>\n<p>10<br \/>\n0<br \/>\n9955<br \/>\n0<br \/>\n9955<\/p>\n<p>10<br \/>\n1<br \/>\n39<br \/>\n990<br \/>\n1029<\/p>\n<p>10<br \/>\n2<br \/>\n\u22480<br \/>\n1979<br \/>\n1979<\/p>\n<p>10<br \/>\n4<br \/>\n\u22480<br \/>\n3954<br \/>\n3954<\/p>\n<p>1000<br \/>\n0<br \/>\n632305<br \/>\n0<br \/>\n632305<\/p>\n<p>1000<br \/>\n1<br \/>\n2470<br \/>\n368<br \/>\n2838<\/p>\n<p>1000<br \/>\n2<br \/>\n10<br \/>\n735<br \/>\n745<\/p>\n<p>1000<br \/>\n4<br \/>\n\u22480<br \/>\n1469<br \/>\n1469<\/p>\n<p><\/p>\n<p>Paistab, et k\u00f5ik on lihtne \u2014 vali kaitstud andmete pikkuse p\u00f5hjal kontrollsumma pikkus miinimumiga vale signaalide arvuga \u2014 ja asi on korras.<\/p>\n<p><\/p>\n<p>Siiski, l\u00fchikeste kontrollsummadega on probleem: kuigi need tuvastavad h\u00e4sti \u00fcksikuid bitti vigu, v\u00f5ivad nad piisavalt suure t\u00f5en\u00e4osusega lugeda t\u00e4iesti juhuslikke andmeid \u00f5igeks. Habr\u00e9s on juba olnud artikkel, mis kirjeldab <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/428746\/\">probleemi reaalses elus<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Seet\u00f5ttu, et muuta kontrollsummade juhusliku kokkulangemise praktiline v\u00f5imalus peaaegu v\u00f5imatuks, tuleb kasutada v\u00e4hemalt 32-bitiseid kontrollsummasid <em>(\u00fcle 64 bitise pikkuse puhul kasutatakse tavaliselt kr\u00fcptograafilisi r\u00e4sifunktsioone)<\/em>.<\/p>\n<p><\/p>\n<p>Kuigi ma olen varem kirjutanud, et tuleb iga hinna eest ruumi kokku hoida, kasutame siiski 32-bitist kontrollsummat (16 bitti on liiga v\u00e4he, kokkup\u00f5rgete t\u00f5en\u00e4osus on \u00fcle 0,01%; 24 bitti on, nagu \u00f6eldakse, ei siia ega sinna).<\/p>\n<p><\/p>\n<p>Siin v\u00f5ib tekkida vastuv\u00e4ide: kas me t\u00f5esti s\u00e4\u00e4stsime iga baidi kompressimise valimisel, et n\u00fc\u00fcd anda kohe 4 baiti? Ei ole ju parem mitte tihendada ja mitte kontrollsummat lisada? Loomulikult ei, tihendamise puudumine <em>ei t\u00e4henda<\/em>, et me ei vaja terviklikkuse kontrolli.<\/p>\n<p><\/p>\n<p>Pol\u00fcnoomi valimise osas ei hakka me ratast leiutama, vaid v\u00f5tame populaarsed CRC-32C.<br \/>\nSee kode tuvastab 6 bittviga pakettides, mille suurus on kuni 22 baiti (ilmselt k\u00f5ige levinum juhtum meie jaoks), 4 bittviga pakettides, mille suurus on kuni 655 baiti (ka levinud juhtum meie jaoks), 2 v\u00f5i mis tahes paaritu arv bittvigu pakettides, mille suurus on m\u00f5istlik.<\/p>\n<p>\n<b class=\"spoiler_title\">Kui kedagi huvitavad \u00fcksikasjad<\/b><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Cyclic_redundancy_check\">Wikipedia artikkel<\/a><\/noindex> CRC kohta.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/users.ece.cmu.edu\/~koopman\/crc\/c32\/0x8f6e37a0_len.txt\">CRC-32C koodi parameetrid<\/a><\/noindex> . Tundub, et <noindex><a rel=\"nofollow\" href=\"http:\/\/users.ece.cmu.edu\/~koopman\/crc\/notes.html\">Kaupmani veebis<\/a><\/noindex> \u2014 ilmselt peamine ekspert CRC alal maailmas.<\/p>\n<p><\/p>\n<p>Uues <noindex><a rel=\"nofollow\" href=\"http:\/\/users.ece.cmu.edu\/~koopman\/networks\/dsn02\/dsn02_koopman.pdf\">tema artiklis<\/a><\/noindex> on <noindex><a rel=\"nofollow\" href=\"https:\/\/users.ece.cmu.edu\/~koopman\/crc\/c32\/0xfa567d89_len.txt\">veel \u00fcks huvitav kood<\/a><\/noindex>, mis tagab veidi paremad parameetrid meie jaoks asjakohaste pakettide pikkuste jaoks, kuid ma ei pidanud vahet oluliseks ja olen piisavalt kompetentne, et valida kohandatud kood standardse ja p\u00f5hjalikult uuritud koodi asemel.<\/p>\n<p><\/p>\n<p>Veelgi enam, kuna meil on andmed kokku surutud, on k\u00fcsimus: kas arvestada kontrollsummat surutud v\u00f5i mitte surutud andmetest?<\/p>\n<p><\/p>\n<p>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b &#171;\u0437\u0430&#187; \u043f\u043e\u0434\u0441\u0447\u0451\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b \u043d\u0435\u0441\u0436\u0430\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<p><\/p>\n<ul>\n<li>meil on l\u00f5puks vaja kontrollida andmete s\u00e4ilitamise ohutust \u2014 nii et me kontrollime seda otse (samuti kontrollitakse v\u00f5imalikud vigadega seotud puuduj\u00e4\u00e4gid kompressiooni\/dekompressiooni rakendamises, m\u00e4lurikked jms);<\/li>\n<li>algoritm deflate zlibis on piisavalt k\u00fcps ja <em>ei tohiks<\/em> \u043f\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u0438 &#171;\u043a\u0440\u0438\u0432\u044b\u0445&#187; \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u043e\u043d \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u043e \u0432\u0445\u043e\u0434\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u0441\u043d\u0438\u0437\u0438\u0432 \u043e\u0431\u0449\u0443\u044e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438 (\u043f\u0440\u043e\u0432\u0451\u043b \u0442\u0435\u0441\u0442 \u0441 \u0438\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0434\u0438\u043d\u043e\u0447\u043d\u043e\u0433\u043e \u0431\u0438\u0442\u0430 \u0432 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438, zlib \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 \u0442\u0440\u0435\u0442\u0438 \u0441\u043b\u0443\u0447\u0430\u0435\u0432).<\/li>\n<\/ul>\n<p><\/p>\n<p>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b &#171;\u043f\u0440\u043e\u0442\u0438\u0432&#187; \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0441\u0443\u043c\u043c\u044b \u043d\u0435\u0441\u0436\u0430\u0442\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<p><\/p>\n<ul>\n<li>CRC &#171;\u0437\u0430\u0442\u043e\u0447\u0435\u043d&#187; \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0434 \u043d\u0435\u043c\u043d\u043e\u0433\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0431\u0438\u0442\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u044b \u0434\u043b\u044f \u0444\u043b\u0435\u0448-\u043f\u0430\u043c\u044f\u0442\u0438 (\u0431\u0438\u0442\u043e\u0432\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0441\u0436\u0430\u0442\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c, \u0447\u0438\u0441\u0442\u043e \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c &#171;\u043f\u043e\u0439\u043c\u0430\u0442\u044c&#187; \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u044e);<\/li>\n<li>mulle ei meeldi idee edastada dekompressorile potentsiaalselt vigaseid andmeid, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.cvedetails.com\/vulnerability-list\/vendor_id-72\/product_id-1820\/GNU-Zlib.html\">kes teab<\/a><\/noindex>, kuidas ta reageerib.<\/li>\n<\/ul>\n<p><\/p>\n<p>Selles projektis otsustasin k\u00f5rvale kalduda tavap\u00e4rasest praktikast, kus s\u00e4ilitada kontrollsummat mitte surutud andmetest.<\/p>\n<p><\/p>\n<p><strong>Kokkuv\u00f5te:<\/strong> kasutame CRC-32C, kontrollsummat arvutame andmetelt sellisel kujul, nagu need salvestatakse flash-m\u00e4llu (p\u00e4rast surumist).<\/p>\n<p><\/p>\n<h3 id=\"izbytochnost\">\u00dcksus<\/h3>\n<p><\/p>\n<p>Liigne \u00fcleliigse kodeerimise kasutamine ei v\u00f5imalda andmete kaotust t\u00e4ielikult v\u00e4listada, kuid see v\u00f5ib oluliselt (tihti kordades) v\u00e4hendada taastamatute andmete kaotuse t\u00f5en\u00e4osust.<\/p>\n<p><\/p>\n<p>Saame kasutada erinevaid \u00fclearuse, et vigu korrigeerida.<br \/>\nHamming'i koodid suudavad parandada \u00fcksikute bittide vigu, Reed-Salomon koodid on s\u00fcmboolsed, mitmed andmekopeerimised koos kontrollsummadega v\u00f5i duplikaatkodeerimine nagu RAID-6 v\u00f5ivad aidata andmeid taastada isegi massiliste riketega.<br \/>\nAlguses olin ma seadnud eesm\u00e4rgiks laialdase vigadevastase kodeerimise kasutamise, kuid hiljem m\u00f5istsin, et esmalt tuleb teada, millistest vigadest me soovime end kaitsta, ja alles seej\u00e4rel valida kodeerimine.<\/p>\n<p><\/p>\n<p>R\u00e4\u00e4kisime varem, et vigu tuleb tuvastada v\u00f5imalikult kiiresti. Millistes olukordades me v\u00f5ime vigadega kokku puutuda?<\/p>\n<p><\/p>\n<ol>\n<li>\u041d\u0435\u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c (\u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u0438\u0442\u0430\u043d\u0438\u0435, \u0437\u0430\u0432\u0438\u0441 Raspberry, &#8230;)<br \/>\nKahjuks j\u00e4\u00e4b sellise vea korral ainus v\u00f5imalus, et ignoreerida kehtetuks osutunud salvestusi ja pidada andmeid kadunuks;<\/li>\n<li>Salvestamise vead (mingil p\u00f5hjusel kirjutati flash-m\u00e4 \u043f\u0430\u043c\u044f\u0442\u0438 midagi muud, kui oli plaanitud)<br \/>\nSelliseid vigu saame koheselt tuvastada, kui teeme p\u00e4rast salvestamist kontrollimist.<\/li>\n<li>Andmete moonutamine m\u00e4lus salvestamise k\u00e4igus;<\/li>\n<li>Lugemisvead<br \/>\nVea parandamiseks piisab, kui kontrollsumma mittesobivuse korral lugemist mitu korda korrata.<\/li>\n<\/ol>\n<p><\/p>\n<p>Seega ei saa ainult kolmanda t\u00fc\u00fcbi vead (andmete iseeneslik riknemine salvestamise ajal) parandada ilma vigadevastase kodeerimiseta. Tall on usutav, et sellised vead on siiski \u00e4\u00e4rmiselt ebat\u00f5en\u00e4olsed.<\/p>\n<p><\/p>\n<p><strong>Kokkuv\u00f5te:<\/strong> otsustasime loobuda \u00fcleliigsest kodeerimisest, kuid kui kasutamine n\u00e4itab, et see otsus on vale, siis naaseme k\u00fcsimuse juurde (koos akumuleeritud statistika riketest, mis v\u00f5imaldab valida optimaalse kodeerimist\u00fc\u00fcbi).<\/p>\n<p><\/p>\n<h3 id=\"prochee\">Muud<\/h3>\n<p><\/p>\n<p>Loomulikult ei v\u00f5imalda artikli formaat iga detaili selgitada <em>(ja minu energia on juba ammendunud)<\/em>, seega l\u00e4hen l\u00fchidalt \u00fcle m\u00f5ningate punktide, mida varem ei puudutatud.<\/p>\n<p><\/p>\n<ul>\n<li>\u0420\u0435\u0448\u0435\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b &#171;\u0440\u0430\u0432\u043d\u043e\u043f\u0440\u0430\u0432\u043d\u044b\u043c\u0438&#187;<br \/>\nSee, there won't be any special pages with metadata, separate streams, etc., instead, there will be a single stream that rewrites all pages sequentially.<br \/>\nThis ensures even wear of the pages, eliminates a single point of failure, and it's simply preferable;<\/li>\n<li>It is essential to provide for versioning of the format.<br \/>\nA format without a version number in the header is evil!<br \/>\nIt's enough to add a field with some Magic Number (signature) in the page header that indicates the version of the format being used. <em>(I don't think there will be even a dozen of them in practice)<\/em>;<\/li>\n<li>Use a variable-length header for records (of which there are many), aiming to make it 1 byte in length for most cases;<\/li>\n<li>To encode the length of the header and the length of the trimmed part of the compressed record, use variable-length binary codes.<\/li>\n<\/ul>\n<p><\/p>\n<p>Was very helpful <noindex><a rel=\"nofollow\" href=\"https:\/\/planetcalc.com\/2481\/\">the online generator<\/a><\/noindex> of Huffman codes. It took just a few minutes to find the necessary variable-length codes.<\/p>\n<p><\/p>\n<h1 id=\"anchorformatanchoropisanie-formata-hraneniya-dannyh\"><noindex><a rel=\"nofollow\" name=\"format\"><\/a><\/noindex>Data storage format description<\/h1>\n<p><\/p>\n<h2 id=\"byte-order\">Byte order<\/h2>\n<p><\/p>\n<p>Fields larger than one byte are stored in big-endian format (network byte order), meaning that 0x1234 is written as 0x12, 0x34.<\/p>\n<p><\/p>\n<h2 id=\"delenie-na-stranicy\">Paging<\/h2>\n<p><\/p>\n<p>All flash memory is divided into equal-sized pages.<\/p>\n<p><\/p>\n<p>The default page size is 32KB, but no more than 1\/4 of the total size of the memory chip (for a 4MB chip, there are 128 pages).<\/p>\n<p><\/p>\n<p>Each page stores data independently of the others (meaning the data of one page does not reference the data of another page).<\/p>\n<p><\/p>\n<p>All pages are numbered in natural order (in ascending address order), starting from number 0 (the zero page starts at address 0, the first at 32KB, the second at 64KB, etc.).<\/p>\n<p><\/p>\n<p>\u041c\u0438\u043a\u0440\u043e\u0441\u0445\u0435\u043c\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u0443\u0444\u0435\u0440 (ring buffer), \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0438\u0434\u0451\u0442 \u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0441 \u043d\u043e\u043c\u0435\u0440\u043e\u043c 0, \u043f\u043e\u0442\u043e\u043c \u0441 \u043d\u043e\u043c\u0435\u0440\u043e\u043c 1, &#8230;, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0442\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0446\u0438\u043a\u043b \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f \u0441 \u043d\u0443\u043b\u0435\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<p><\/p>\n<h2 id=\"vnutri-stranicy\">Inside the page<\/h2>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/39b45f83dc46bb2fd7081ed2a0b638c9.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f 4-\u0431\u0430\u0439\u0442\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043f\u043e\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430\u044f \u0441\u0443\u043c\u043c\u0430 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 (CRC-32C), \u0434\u0430\u043b\u0435\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 &#171;\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430\u044f \u0441\u0443\u043c\u043c\u0430&#187;.<\/p>\n<p><\/p>\n<p>The page header (shown in dark green in the diagram) consists of:<\/p>\n<p><\/p>\n<ul>\n<li>a two-byte Magic Number field (which is also the version format indicator)<br \/>\nfor the current version of the format, it is considered as <code>0xed00 \u2295 lehe number<\/code>;<\/li>\n<li>\u0434\u0432\u0443\u0445\u0431\u0430\u0439\u0442\u043d\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u0430 &#171;\u0412\u0435\u0440\u0441\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b&#187; (\u043d\u043e\u043c\u0435\u0440 \u0446\u0438\u043a\u043b\u0430 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0430\u043c\u044f\u0442\u0438).<\/li>\n<\/ul>\n<p><\/p>\n<p>Lehe salvestused salvestatakse kokku surutud kujul (kasutatakse deflate algoritmi). K\u00f5ik salvestused \u00fchel lehel surutakse \u00fches voos (kasutatakse \u00fchise s\u00f5naraamatuga), igal uuel lehel hakkab surumine uuesti. Seega vajab iga salvestuse dekompressioon k\u00f5iki eelnevaid salvestusi sellelt lehelt (ja ainult sellest).<\/p>\n<p><\/p>\n<p>Iga salvestus surutakse Z_SYNC_FLUSH m\u00e4rgiga, samas on kokku surutud voolu l\u00f5pus 4 baiti 0x00, 0x00, 0xff, 0xff, ees v\u00f5ib olla \u00fcks v\u00f5i kaks nullbaiti.<br \/>\nSeda j\u00e4rjestust (pikkusega 4, 5 v\u00f5i 6 baiti) me ei salvesta v\u00e4lkp\u00f6\u00f6rdes.<\/p>\n<p><\/p>\n<p>Salvestuse pealkiri koosneb 1, 2 v\u00f5i 3 baitist, mis sisaldavad:<\/p>\n<p><\/p>\n<ul>\n<li>\u00fche bitti (T), mis t\u00e4histab salvestuse t\u00fc\u00fcpi: 0 \u2014 kontekst, 1 \u2014 p\u00e4evik;<\/li>\n<li>\u043f\u043e\u043b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b (S) \u043e\u0442 1 \u0434\u043e 7 \u0431\u0438\u0442, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0449\u0435\u0435 \u0434\u043b\u0438\u043d\u0443 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0438 &#171;\u0445\u0432\u043e\u0441\u0442&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438;<\/li>\n<li>salvestuse pikkuse (L).<\/li>\n<\/ul>\n<p><\/p>\n<p>V\u00e4\u00e4rtuste tabel S:<\/p>\n<p><\/p>\n<p>S<br \/>\nPealkirja pikkus, bait<br \/>\nSalvestamisel eemaldatav, bait<\/p>\n<p><code>0<\/code><br \/>\n1<br \/>\n5 (<code>00 00 00 ff ff<\/code>)<\/p>\n<p><code>10<\/code><br \/>\n1<br \/>\n6 (<code>00 00 00 00 ff ff<\/code>)<\/p>\n<p><code>110<\/code><br \/>\n2<br \/>\n4 (<code>00 00 ff ff<\/code>)<\/p>\n<p><code>1110<\/code><br \/>\n2<br \/>\n5 (<code>00 00 00 ff ff<\/code>)<\/p>\n<p><code>11110<\/code><br \/>\n2<br \/>\n6 (<code>00 00 00 00 ff ff<\/code>)<\/p>\n<p><code>1111100<\/code><br \/>\n3<br \/>\n4 (<code>00 00 ff ff<\/code>)<\/p>\n<p><code>1111101<\/code><br \/>\n3<br \/>\n5 (<code>00 00 00 ff ff<\/code>)<\/p>\n<p><code>1111110<\/code><br \/>\n3<br \/>\n6 (<code>00 00 00 00 ff ff<\/code>)<\/p>\n<p><\/p>\n<p>Proovisin illustreerida, ei tea, kui selgelt see \u00f5nnestus:<br \/>\n<img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/8c9b739eec5af4429395c32b4ba4044a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nKollane esindab siin v\u00e4lja T, valge \u2014 v\u00e4lja S, roheline L (surutud andmete pikkus baitides), sinine \u2014 surutud andmed, punane \u2014 surutud andmete l\u00f5ppbaitid, mida ei kirjutata v\u00e4lkp\u00f6\u00f6rdesse.<\/p>\n<p><\/p>\n<p>Seega saame k\u00f5ige levinuma pikkusega salvestuste pealkirjad (kuni 63+5 baiti surutud kujul) salvestada \u00fche baitiga.<\/p>\n<p><\/p>\n<p>Iga salvestuse j\u00e4rel on kontrollsummana CRC-32C, mille algv\u00e4\u00e4rtused (init) v\u00f5etakse eelneva kontrollsummat v\u00e4\u00e4rtusest.<\/p>\n<p><\/p>\n<p><em>CRC \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c &#171;\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438&#187;, \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 (\u043f\u043b\u044e\u0441-\u043c\u0438\u043d\u0443\u0441 \u0438\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u0442 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435) \u0442\u0430\u043a\u0430\u044f \u0444\u043e\u0440\u043c\u0443\u043b\u0430: <img decoding=\"async\" alt=\"Minu rakendus ringbuffer NOR flashis\" src=\"\/wp-content\/uploads\/2019\/12\/b194d6a3d18ae2f4ae5d4054a93c0ea3.jpg\" style=\"display:block;margin: 0 auto;\" \/>.<br \/>\nSeega arvutame tegelikult CRC k\u00f5igist eelnevatest baitidest pealkirjades ja andmetes sellel lehel.<\/em><\/p>\n<p><\/p>\n<p>Otseselt kontrollsummale j\u00e4rgneb j\u00e4rgmise salvestuse pealkiri.<\/p>\n<p><\/p>\n<p>Pealkiri on konstrueeritud nii, et selle esimene bait oleks alati erinev 0x00 ja 0xff (kui pealkirja esimesele baitile satume 0xff, siis t\u00e4hendab see, et see on kasutamata ala; 0x00 aga signaalib t\u00f5rget).<\/p>\n<p><\/p>\n<h2 id=\"primernye-algoritmy\">Umbes algoritmid<\/h2>\n<p><\/p>\n<h3 id=\"chtenie-iz-flesh-pamyati\">Lugemine v\u00e4lkp\u00f6\u00f6rdest<\/h3>\n<p><\/p>\n<p>Iga lugemine toimub kontrollsummade kontrollimisega.<br \/>\nKui kontrollsumma ei kattu, loetakse andmeid mitu korda lootes \u00f5iged andmed siiski lugeda.<\/p>\n<p><\/p>\n<p><em>(see on m\u00f5ttekas, Linux ei vaheta NOR Flash'i lugemist, on kontrollitud)<\/em><\/p>\n<p><\/p>\n<h3 id=\"zapis-v-flesh-pamyat\">Salvestamine m\u00e4lukiipidesse<\/h3>\n<p><\/p>\n<p>Salvestame andmed.<br \/>\nLugeme need.<\/p>\n<p><\/p>\n<p>Kui loetud andmed ei lange kokku salvestatud andmetega, t\u00e4idame ala nullidega ja anname teada veast.<\/p>\n<p><\/p>\n<h3 id=\"podgotovka-novoy-mikroshemy-k-rabote\">Uue kiibi t\u00f6\u00f6ks ettevalmistamine<\/h3>\n<p><\/p>\n<p>Initsialiseerimiseks salvestatakse esimesse (t\u00e4psemalt nullsesse) lehte versiooniga 1 pealkiri.<br \/>\nP\u00e4rast seda salvestatakse sellele lehele algne kontekst (sisaldab automaadi UUID ja vaikeseaded). <\/p>\n<p><\/p>\n<p>K\u00f5ik, m\u00e4lukiip on t\u00f6\u00f6tamiseks valmis.<\/p>\n<p><\/p>\n<h3 id=\"zagruzka-avtomata\">Automaatide laadimine<\/h3>\n<p><\/p>\n<p>Laadimise k\u00e4igus loetakse iga lehe esimesed 8 baiti (pealkiri + CRC), lehti, millel on tundmatu Magic Number v\u00f5i vale CRC, ignoreeritakse.<br \/>\n\u0418\u0437 &#171;\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0445&#187; \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439, \u0438\u0437 \u043d\u0438\u0445 \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u0438\u043c\u0435\u044e\u0449\u0430\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043d\u043e\u043c\u0435\u0440.<br \/>\n\u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c CRC, \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0444\u043b\u0430\u0433\u0430 &#171;\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442&#187;. \u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u2014 \u044d\u0442\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u2014 \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0451\u043c &#171;\u0436\u0438\u0432\u0443\u044e&#187; \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<br \/>\n\u0430 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438, \u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441 \u0444\u043b\u0430\u0433\u043e\u043c &#171;\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442&#187; \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c.<br \/>\nSalvestame zlib s\u00f5nastiku (see on vajalik selle lehe t\u00e4iendamiseks).<\/p>\n<p><\/p>\n<p>K\u00f5ik, laadimine on l\u00f5pule viidud, kontekst on taastatud, saab t\u00f6\u00f6tada.<\/p>\n<p><\/p>\n<h3 id=\"dobavlenie-zapisi-v-zhurnal\">Kande lisamine p\u00e4evikusse<\/h3>\n<p><\/p>\n<p>Kandme surumise \u00f5ige s\u00f5nastiku abil, kasutades Z_SYNC_FLUSH. Kontrollime, kas surutud kande mahub praegusele lehele.<br \/>\nKui ei mahuta (v\u00f5i lehel oli CRC vigu) - alustame uut lehte (vt alla).<br \/>\nSalvestame kande ja CRC. Kui esines viga - alustame uut lehte.<\/p>\n<p><\/p>\n<h3 id=\"novaya-stranica\">Uus leht<\/h3>\n<p><\/p>\n<p>Valime vaba lehe, millel on madalaim number (vabana peame lehte, millel on vale kontrollsumma pealkirjas v\u00f5i mille versioon on v\u00e4iksem kui praegune). Kui selliseid lehti ei ole, valime lehe, millel on minimaalne number ja mille versioon on v\u00f5rdne praegusega.<br \/>\nTeeme valitud lehe erase. Kontrollime sisu 0xff vastu. Kui midagi on valesti - v\u00f5tame j\u00e4rgmise vaba lehe jne.<br \/>\nKustutatud lehele salvestame pealkirja, esimese kirjana praeguse konteksti oleku, j\u00e4rgmise - kirjutamata p\u00e4evikukande (kui see on olemas).<\/p>\n<p><\/p>\n<h1 id=\"primenimost-formata\">Formaadi kohaldatavus<\/h1>\n<p><\/p>\n<p>Minu arvates on see hea formaat mis tahes m\u00f5\u00f5dukaid andmeid (lihtne tekst, JSON, MessagePack, CBOR, v\u00f5ib-olla protobuf) salvestamiseks NOR Flashis.<\/p>\n<p><\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0444\u043e\u0440\u043c\u0430\u0442 &#171;\u0437\u0430\u0442\u043e\u0447\u0435\u043d&#187; \u043f\u043e\u0434 SLC NOR Flash.<\/p>\n<p><\/p>\n<p>Seda ei tohiks kasutada seadmetega, millel on k\u00f5rge BER, nagu NAND v\u00f5i MLC NOR. <em>(Kas sellist m\u00e4lu on \u00fcldse m\u00fc\u00fcgis? Olen kohanud viiteid ainult vigade parandamise teadusartiklites.)<\/em>.<\/p>\n<p><\/p>\n<p>Veelgi enam, seda ei tohiks kasutada seadmetega, millel on oma FTL: USB flash, SD, MicroSD jne. <em>(\u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u044f \u0434\u0435\u043b\u0430\u043b \u0444\u043e\u0440\u043c\u0430\u0442 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 512 \u0431\u0430\u0439\u0442, \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u043e\u0439 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043d\u043e\u043c\u0435\u0440\u0430\u043c\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u2014 \u0438\u043d\u043e\u0433\u0434\u0430 \u0438\u0437 &#171;\u0433\u043b\u044e\u043a\u043d\u0443\u0432\u0448\u0435\u0439&#187; \u0444\u043b\u0435\u0448\u043a\u0438 \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0447\u0442\u0435\u043d\u0438\u0435\u043c \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435)<\/em>.<\/p>\n<p><\/p>\n<p>S\u00f5ltuvalt \u00fclesannetest saab formaati kasutada ilma muutmisteta m\u00e4lupulkadel vahemikus 128Kbit (16Kb) kuni 1Gbit (128Mb). Soovi korral saab seda kasutada ka suurema mahutavusega kiipidel, kuid t\u00f5en\u00e4oliselt tuleb lehek\u00fclje suurust kohandada. <em>(Aga siin kerkib juba esile majanduslik otstarbekus, NOR Flashi suur mahutus ei ole odav.)<\/em>.<\/p>\n<p><\/p>\n<p>Kui kellelegi tundus formaat huvitav ja ta tahab seda kasutada avatud projektis \u2014 kirjutage, p\u00fc\u00fcan leida aega koodi korrigeerimiseks ja \u00fcles laadimiseks Githubi.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Kokkuv\u00f5te<\/h1>\n<p><\/p>\n<p>Kuidas n\u00e4ha, osutus formaat l\u00f5puks lihtsaks. <em>ja lausa igavaks.<\/em>.<\/p>\n<p><\/p>\n<p>Artikli formaadis on raske kajastada oma seisukoha arengut, kuid uskuge mind: alguses tahtsin luua midagi keerukat ja purunematut, mis suudaks ellu j\u00e4\u00e4da isegi tuumapommi l\u00e4heduses. Kuid m\u00f5istus (loodetavasti) siiski v\u00f5itis ja prioriteedid nihkusid j\u00e4rk-j\u00e4rgult lihtsuse ja kompaktsetuse suunas.<\/p>\n<p><\/p>\n<p>Kas on v\u00f5imalik, et ma eksisin? Jah, loomulikult. T\u00e4iesti v\u00f5imalik on n\u00e4iteks, et oleme ostnud partiid halva kvaliteediga kiipe. V\u00f5i m\u00f5nel muul p\u00f5hjusel ei vasta seade ootustele usaldusv\u00e4\u00e4rsuse osas.<\/p>\n<p><\/p>\n<p>Kas mul on selle juhtumi jaoks plaan? Ma arvan, et artikkel lugedes ei kahtle te, et plaan on. Ja isegi mitte \u00fcks.<\/p>\n<p><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e, \u0444\u043e\u0440\u043c\u0430\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0438 \u043a\u0430\u043a &#171;\u043f\u0440\u043e\u0431\u043d\u044b\u0439 \u0448\u0430\u0440&#187;.<\/p>\n<p><\/p>\n<p>Hetkel t\u00f6\u00f6tab k\u00f5ik laua peal normaalselt, m\u00f5ni p\u00e4ev tagasi v\u00f5etakse lahendus kasutusele. <em>(umbes)<\/em> \u043d\u0430 \u0441\u043e\u0442\u043d\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432 &#171;\u0431\u043e\u0435\u0432\u043e\u0439&#187; \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 (\u0431\u043b\u0430\u0433\u043e, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0444\u043e\u0440\u043c\u0430\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0434\u0451\u0436\u043d\u043e \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0431\u043e\u0438; \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443). \u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434\u044b <em>(ja kui \u00f5nne pole, siis ka varem)<\/em>.<\/p>\n<p><\/p>\n<p>Kui kasutamise tulemused paljastavad t\u00f5siseid probleeme ja t\u00e4iendavaid arendusi on vaja, siis kirjutan sellest kindlasti.<\/p>\n<p><\/p>\n<h1 id=\"literatura\">Kirjandus<\/h1>\n<p><\/p>\n<p>Ei tahtnud koostada pikka igavat nimekirja kasutatud t\u00f6\u00f6dest, l\u00f5puks on Google k\u00f5igile olemas.<\/p>\n<p><\/p>\n<p>Siin otsustasin j\u00e4tta loetelu leidudest, mis tundusid mulle eriti huvitavad, kuid j\u00e4rk-j\u00e4rgult said need otse artikli tekstis, ja nimekirjas j\u00e4i alles ainult \u00fcks punkt:<\/p>\n<p><\/p>\n<ol>\n<li>Utiliit <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/madler\/infgen\/\">infgen<\/a><\/noindex> autor zlib. Suudab selgelt kuvada deflate\/zlib\/gzip arhiivide sisu. Kui pead arvestama deflate (v\u00f5i gzip) formaadi sisemise struktuuriga \u2014 soovitan soojalt.<\/li>\n<\/ol>\n<p>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/479044\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0415\u0441\u0442\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u043d\u0443\u0442\u0440\u0438 Raspberry Pi \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0435. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043c\u043e\u043d\u0435\u0442\u043e\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a, \u043a\u0443\u043f\u044e\u0440\u043e\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a, \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0438\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u2026 \u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u043c \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u0430\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430. \u0412\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0432 \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0430 \u0444\u043b\u0435\u0448\u043a\u0435 (MicroSD), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 (\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e USB-\u043c\u043e\u0434\u0435\u043c\u0430) \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0442\u0430\u043c \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0411\u0414. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0434\u0430\u0436\u0430\u0445 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 1\u0441, \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-53751","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0415\u0441\u0442\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u043d\u0443\u0442\u0440\u0438 Raspberry Pi \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041c\u043e\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043b\u044c\u0446\u0435\u0432\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 NOR flash | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0415\u0441\u0442\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u043d\u0443\u0442\u0440\u0438 Raspberry Pi \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-12-08T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:01:41+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Minu ringbufferi rakendus NOR flash'is | ProHoster","description":"Eelajalugu Omavad kaubanduslikud automaadid on enda kujundatud. Sees on Raspberry Pi ja natuke lisatahti eraldi plaadil.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041c\u043e\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043b\u044c\u0446\u0435\u0432\u043e\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430 \u0432 NOR flash | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f \u0415\u0441\u0442\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u044b \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u043d\u0443\u0442\u0440\u0438 Raspberry Pi \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0435.","og:url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/moya-realizatsiya-koltsevogo-bufera-v-nor-flash","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-12-08T21:00:00+00:00","article:modified_time":"2020-02-18T11:01:41+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"53751","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 08:36:23","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:18:30","updated":"2026-01-24 08:36:23","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/53751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=53751"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/53751\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=53751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=53751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=53751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}