prehistory
Өзүбүздүн дизайндагы автоматтар бар. Raspberry Pi ичинде жана өзүнчө тактадагы кээ бир зымдар. Тыйын акцептору, векселдерди кабыл алуучу, банк терминалы туташтырылды... Баары өзүн өзү жазган программа менен башкарылат. Бүткүл иш тарыхы флэш-дисктеги (MicroSD) журналга жазылат, андан кийин ал Интернет аркылуу (USB модемди колдонуу менен) серверге өткөрүлүп берилет, ал жерде маалымат базасында сакталат. Сатуу жөнүндө маалымат 1cге жүктөлөт, мониторинг жүргүзүү үчүн жөнөкөй веб-интерфейс дагы бар.
Башкача айтканда, журнал өтө маанилүү болуп саналат - бухгалтердик эсепке алуу (киреше, сатуу, ж.б.), мониторинг (ар кандай бузулуулар жана башка форс-мажордук жагдайлар); Бул, бир айта алабыз, биз бул машина жөнүндө бардык маалымат болуп саналат.
маселе
Флэш-дисктер өздөрүн өтө ишенимсиз түзүлүштөр катары көрсөтөт. Алар көз арткан мыйзамдуулук менен ийгиликке жетпейт. Бул машинанын иштебей калышына да, (эгер кандайдыр бир себептерден улам журналды онлайн өткөрүү мүмкүн болбосо) маалыматтардын жоголушуна алып келет.
Бул флэш-дисктерди колдонуунун биринчи тажрыйбасы эмес, буга чейин журнал USB флэш-дисктерде сакталган жүздөн ашык түзмөктөрү бар дагы бир долбоор болгон, ошондой эле ишенимдүүлүк менен көйгөйлөр болгон, кээде иштебей калгандардын саны. бир ай ондогон болду. Биз ар кандай флеш-дисктерди, анын ичинде SLC эс тутуму бар фирмалык дисктерди сынап көрдүк, кээ бир моделдер башкаларга караганда ишенимдүү, бирок флэш-дисктерди алмаштыруу көйгөйдү түп тамырынан бери чече алган жок.
Эскертүү! Longread! Эгер сизди “эмне үчүн” кызыктырбай, “кантип” гана кызыктырса, түз кете аласыз макала.
чечим
Акылга келген биринчи нерсе: MicroSDден баш тартып, мисалы, SSDди орнотуп, андан жүктөө. Теориялык жактан мүмкүн, балким, бирок салыштырмалуу кымбат жана анчалык деле ишеничтүү эмес (USB-SATA адаптери кошулган; бюджеттик SSD дисктеринин иштебей калышынын статистикасы да кубандырбайт).
USB HDD да өзгөчө жагымдуу чечимге окшобойт.
Ошондуктан, биз бул параметрге келдик: MicroSDден жүктөөнү калтырыңыз, бирок аларды окуу үчүн гана режимде колдонуңуз жана операция журналын (жана белгилүү бир аппараттык бөлүккө уникалдуу болгон башка маалымат - сериялык номер, сенсор калибрлөө ж.б.) башка жерде сактаңыз. .
Малина үчүн окууга гана арналган FS темасы мурунтан эле ичинде жана сыртында изилденген, мен бул макалада ишке ашыруунун деталдарына токтолбойм (бирок кызыгуу болсо, балким, мен бул тема боюнча чакан макала жазам). Мен белгилегим келген бир гана жагдай, жеке тажрыйбадан да, аны ишке ашыргандардын сынынан да ишенимдүүлүк пайда болот. Ооба, бузулуулардан толугу менен арылуу мүмкүн эмес, бирок алардын жыштыгын олуттуу кыскартуу мүмкүн. Ал эми карталар унификацияланууда, бул тейлөө кызматкерлери үчүн алмаштырууну бир топ жеңилдетет.
аппараттык бөлүгү
Эс тутум түрүн тандоодо эч кандай шек болгон эмес - NOR Flash.
Аргументтер:
- жөнөкөй туташуу (көбүнчө SPI автобусу, аны колдонуу тажрыйбасы бар, андыктан аппараттык камсыздоо көйгөйлөрү күтүлбөйт);
- күлкүлүү баа;
- стандарттуу иштөө протоколу (ишке ашыруу ядродо мурунтан эле бар) Linux, кааласаңыз, үчүнчү тараптын бирин ала аласыз, алар да бар, же өзүңүздүн жазыңыз, бактыга жараша, баары жөнөкөй);
- ишенимдүүлүк жана ресурс:
типтүү маалымат баракчасынан: маалыматтар 20 жыл сакталат, ар бир блок үчүн 100000 XNUMX өчүрүү цикли;
үчүнчү жактын булактарынан: өтө төмөн BER, каталарды оңдоо коддорунун кереги жок деп эсептейт (кээ бир эмгектерде NOR үчүн ECC каралат, бирок, адатта, алар дагы эле MLC NOR дегенди билдирет; бул да болот).
Келгиле, көлөмгө жана ресурска болгон талаптарды баалайлы.
Мен маалыматтардын бир нече күн сакталышын каалайт элем. Бул байланыш менен кандайдыр бир көйгөйлөр болгон учурда, сатуу тарыхы жоголуп кетпеши үчүн зарыл. Биз 5 күнгө көңүл бурабыз, бул аралыкта (дем алыш жана майрам күндөрүн да эске алганда) көйгөйдү чечсе болот.
Учурда биз күнүнө 100 кб журналдарды чогултабыз (3-4 миң жазуу), бирок бара-бара бул көрсөткүч өсүп жатат - деталдар көбөйүүдө, жаңы окуялар кошулууда. Андан тышкары, кээде жарылуулар болот (кээ бир сенсор, мисалы, жалган позитивдер менен спам жөнөтө баштайт). Биз ар бири 10 байт 100 миң жазуу үчүн эсептейбиз - күнүнө мегабайт.
Жалпысынан 5 МБ таза (жакшы кысылган) маалымат чыгат. Аларга көбүрөөк (орой баа) 1МБ кызмат маалыматы.
Башкача айтканда, биз кысуу колдонбосок 8 МБ чип керек, же колдонсок 4 МБ чип керек. Эс тутумдун бул түрү үчүн абдан реалдуу сандар.
Ресурска келсек: эгерде биз эстутумдун баары 5 күндө бир жолудан ашык эмес кайра жазылып турууну пландаштырсак, анда 10 жылдан ашык кызматта биз миңден аз кайра жазуу циклин алабыз.
Эске сала кетейин, өндүрүүчү жүз миң убада кылат.
NOR жана NAND жөнүндө бир аз
Бүгүнкү күндө, албетте, NAND эстутуму алда канча популярдуу, бирок мен аны бул долбоор үчүн колдонбойм: NAND, NORдан айырмаланып, катаны оңдоо коддорун, начар блоктордун таблицасын ж.б., ошондой эле буттарын колдонууну талап кылат. NAND чиптери, адатта, алда канча көп.
NOR кемчиликтери төмөнкүлөрдү камтыйт:
- кичинекей көлөмү (жана, демек, мегабайт үчүн жогорку баа);
- төмөн байланыш ылдамдыгы (негизинен сериялык интерфейс колдонулгандыктан, көбүнчө SPI же I2C);
- жай өчүрүү (блоктун өлчөмүнө жараша ал секунданын бир бөлүгүнөн бир нече секундага чейин созулат).
Биз үчүн сынчыл эч нерсе жок окшойт, ошондуктан улантабыз.
Эгерде деталдар кызыктуу болсо, микросхема тандалды (бирок, бул маанилүү эмес, рынокто pinout жана командалык тутумда шайкеш келген көптөгөн аналогдор бар; биз башка өндүрүүчүдөн жана/же башка өлчөмдөгү микросхеманы орнотууну кааласак дагы, бардыгы өзгөрүлбөй иштейт. код).
Мен ядрого орнотулганын колдоном Linux Драйвер, Raspberry'де, түзмөк дарагынын катмарын колдоонун аркасында баары абдан жөнөкөй - компиляцияланган катмарды /boot/overlays ичине салып, /boot/config.txt файлын бир аз өзгөртүшүңүз керек.
Мисал dts файлы
Чынын айтсам, мен катасыз жазылганына ишенбейм, бирок ал иштейт.
/*
* Device tree overlay for at25 at spi0.1
*/
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709";
/* disable spi-dev for spi0.1 */
fragment@0 {
target = <&spi0>;
__overlay__ {
status = "okay";
spidev@1{
status = "disabled";
};
};
};
/* the spi config of the at25 */
fragment@1 {
target = <&spi0>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
flash: m25p80@1 {
compatible = "atmel,at25df321a";
reg = <1>;
spi-max-frequency = <50000000>;
/* default to false:
m25p,fast-read ;
*/
};
};
};
__overrides__ {
spimaxfrequency = <&flash>,"spi-max-frequency:0";
fastread = <&flash>,"m25p,fast-read?";
};
};Жана config.txt ичиндеги дагы бир сап
dtoverlay=at25:spimaxfrequency=50000000Мен чипти Raspberry Piге туташтыруу сүрөттөлүшүн өткөрүп жиберем. Бир жагынан алганда, мен электроника боюнча адис эмесмин, экинчи жагынан, бул жерде баары мен үчүн да баналдык: микросхемада 8 гана буту бар, анын ичинен бизге жер, күч, SPI (CS, SI, SO, SCK) керек. ); деңгээлдер Raspberry Pi менен бирдей, кошумча зымдар талап кылынбайт - жөн гана көрсөтүлгөн 6 пинди туташтырыңыз.
Тапшырманын коюлушу
Адаттагыдай эле, маселенин билдирүүсү бир нече кайталоодон өтөт жана менимче, кийинкиге убакыт келди. Андыктан токтоп, буга чейин жазылгандарды чогултуп, көмүскөдө калган деталдарды тактап алалы.
Ошентип, биз журнал SPI NOR Flashте сакталат деп чечтик.
Билбегендер үчүн NOR Flash деген эмне?
Бул туруктуу эс тутум, анын жардамы менен сиз үч операцияны аткара аласыз:
- Окуу:
Эң кеңири таралган окуу: биз даректи өткөрүп беребиз жана канча байт керек болсо, ошончо байт окуйбуз; - Ыйык Китепте:
NOR флэшке жазуу кадимкидей көрүнөт, бирок анын бир өзгөчөлүгү бар: 1ден 0гө гана өзгөртө аласыз, бирок тескерисинче эмес. Мисалы, эс тутум уячасында 0x55 болсо, анда ага 0x0f жазгандан кийин, 0x05 ал жерде сакталат. (төмөнкү таблицаны караңыз); - Тазалоо:
Албетте, биз тескери операцияны жасай алышыбыз керек - 0дөн 1ге өзгөртүү, тазалоо операциясы дал ушул үчүн. Биринчи экөөнөн айырмаланып, ал байттар менен эмес, блоктор менен иштейт (тандалган чиптеги минималдуу өчүрүү блогу 4кб). Erase бүт блокту жок кылат жана 0дөн 1ге өзгөртүүнүн бирден-бир жолу. Ошондуктан, флэш-эстутум менен иштегенде, көп учурда маалымат структураларын өчүрүү блогунун чектерине тууралашыңыз керек.
NOR Flash менен жаздыруу:
Бинардык маалыматтар
ал
01010101
Жазылды
00001111
Болуп калды
00000101
Журналдын өзү өзгөрмө узундуктагы жазуулардын ырааттуулугун билдирет. Жазуунун типтүү узундугу болжол менен 30 байт (узундугу бир нече килобайт болгон жазуулар кээде кездешет). Бул учурда, биз алар менен жөн гана байт топтому катары иштейбиз, бирок, эгер сизди кызыктырсаңыз, CBOR жазуулардын ичинде колдонулат
Журналдан тышкары, биз жаңыланган жана жаңыланбаган кээ бир "орнотуу" маалыматын сакташыбыз керек: белгилүү бир түзмөк ID, сенсор калибрлөөлөрү, "түзмөк убактылуу өчүрүлгөн" желек ж.б.
Бул маалымат CBORда сакталган ачкыч-маанилик жазуулардын жыйындысы.
Кийинкиде биз аны контекст деп атайбыз.
Бул макаланын кайдан башталганын эстесек, маалыматтын ишенимдүү сакталышын жана мүмкүн болсо, аппараттык камсыздоо бузулган/маалымат бузулган учурда да үзгүлтүксүз иштешин камсыз кылуу абдан маанилүү.
Көйгөйлөрдүн кандай булактарын кароого болот?
- Жазуу/тазалоо операциялары учурунда өчүрүлөт. Бул "ломго каршы айла жок" категориясынан.
Маалыматтан stackexchange боюнча: жарк менен иштөөдө кубат өчүрүлгөндө, өчүрүү (1ге коюлган) жана жазуу (0) экөө тең аныкталбаган жүрүм-турумга алып келет: маалыматтарды жарым-жартылай жазууга болот (айталы, биз 10 байт/80 бит өткөрдүк. , бирок азырынча 45 битти гана жазууга болбойт), биттердин айрымдары “аралык” абалда болушу да мүмкүн (окуу 0 жана 1ди да чыгарышы мүмкүн); - Флеш эс тутумдун өзүндөгү каталар.
BER өтө төмөн болсо да, нөлгө барабар боло албайт; - Автобус каталары
SPI аркылуу берилүүчү маалыматтар эч кандай түрдө корголгон эмес, бир бит каталары да, синхрондоштуруу каталары да болушу мүмкүн - биттердин жоголушу же кыстарылышы (бул маалыматтын массалык бурмаланышына алып келет); - Башка каталар / мүчүлүштүктөр
Коддогу каталар, Raspberry мүчүлүштүктөрү, келгиндердин кийлигишүүсү...
Мен талаптарды иштеп чыктым, алардын аткарылышы, менин оюмча, ишенимдүүлүктү камсыз кылуу үчүн зарыл:
- жазуулар флеш эстутумга дароо кириши керек, кечиктирилген жазуулар каралбайт - эгерде ката пайда болсо, аны мүмкүн болушунча эртерээк аныктоо жана иштетүү керек - мүмкүн болсо, система каталарды калыбына келтириши керек;
("кандай болбошу керек" деген жашоодон бир мисал, менимче, мунун баары туш келди: шашылыш түрдө кайра жүктөөдөн кийин файл системасы "бузулган" жана операциялык система жүктөлбөйт)
Идеялар, ыкмалар, ой жүгүртүүлөр
Мен бул көйгөй жөнүндө ойлоно баштаганда, менин башыма көптөгөн идеялар келип түштү, мисалы:
- маалыматтарды кысуу колдонуу;
- акылдуу маалымат структураларын колдонуңуз, мисалы, жазуулардын аталыштарын жазуулардын өзүнөн өзүнчө сактоо, эгер кандайдыр бир жазууда ката болсо, калганын эч кандай көйгөйсүз окуй аласыз;
- электр энергиясы өчүрүлгөндө жаздыруунун аякташын көзөмөлдөө үчүн бит талааларын колдонуңуз;
- бардык нерсе үчүн текшерүү суммасын сактоо;
- ызы-чууга туруктуу коддоонун кандайдыр бир түрүн колдонуңуз.
Бул идеялардын кээ бирлери колдонулса, башкаларынан баш тартуу чечими кабыл алынды. Тартип менен кетели.
берилиштерди кысуу
Биз журналга жазган окуялардын өзүлөрү окшош жана кайталануучу («5 рублдик тыйын ыргыттык», «өзгөртүү баскычын басышты»,...). Ошондуктан, кысуу абдан натыйжалуу болушу керек.
Кысуунун ашыкча чыгымы анчалык деле чоң эмес (биздин процессорубуз абдан күчтүү, жада калса биринчи Pi 700 МГц жыштыгы менен бир өзөккө ээ, азыркы моделдерде гигагерцтен ашык жыштыгы менен бир нече өзөк бар), сактагыч менен алмашуу курсу төмөн (бир нече секундасына мегабайт), жазуулардын көлөмү аз. Жалпысынан алганда, кысуу аткарууга таасирин тийгизсе, анда ал оң гана болот. (такыр сынга алынбайт, жөн гана айтып жатат)Мындан тышкары, бизде чыныгы орнотулганы жок, бирок кадимкиси бар. Linux — ошондуктан ишке ашыруу көп күч-аракетти талап кылбашы керек (жөн гана китепкананы байланыштырып, андан бир нече функцияларды колдонуу жетиштүү).
Журналдын бир бөлүгү жумушчу түзүлүштөн алынган (1.7 МБ, 70 миң жазуу) жана алгач компьютерде жеткиликтүү gzip, lz4, lzop, bzip2, xz, zstd аркылуу кысылышын текшерген.
- gzip, xz, zstd окшош натыйжаларды көрсөттү (40Kb).
Модалуу xz бул жерде gzip же zstd деңгээлинде өзүн көрсөткөнүнө таң калдым; - демейки орнотуулары менен lzip бир аз жаман натыйжаларды берди;
- lz4 жана lzop абдан жакшы натыйжаларды көрсөткөн эмес (150Kb);
- bzip2 таң калыштуу жакшы натыйжа көрсөттү (18Kb).
Ошентип, маалыматтар абдан жакшы кысылган.
Ошентип (эгер биз өлүмгө дуушар болгон кемчиликтерди таппаса) кысуу болот! Жөн гана, анткени бир эле флэш-дискке көбүрөөк маалымат туура келет.
Келгиле, кемчиликтери жөнүндө ойлонуп көрөлү.
Биринчи маселе: биз буга чейин эле ар бир жазуу дароо жарк өтүшү керек деп макулдаштык. Адатта, архивчи дем алыш күнү жазууга убакыт келди деп чечкенге чейин кириш агымынан маалыматтарды чогултат. Биз дароо маалыматтын кысылган блогун кабыл алып, аны туруксуз эс тутумда сакташыбыз керек.
Мен үч жолду көрөм:
- Жогоруда талкууланган алгоритмдердин ордуна сөздүк кысуу аркылуу ар бир жазууну кысуу.
Бул толугу менен иштеген вариант, бирок мага жакпайт. Кысуунун аздыр-көптүр татыктуу деңгээлин камсыз кылуу үчүн, сөздүк белгилүү бир маалыматтарга ылайыкташтырылган болушу керек; Ооба, сөздүктүн жаңы версиясын түзүү менен көйгөйдү чечсе болот, бирок бул баш оору – сөздүктүн бардык версияларын сактоого туура келет; Ар бир жазууда сөздүктүн кайсы версиясы менен кысылганын көрсөтүүбүз керек... - "Классикалык" алгоритмдердин жардамы менен ар бир жазууну кысуу, бирок башкалардан көз карандысыз.
Каралып жаткан кысуу алгоритмдери бул көлөмдөгү (ондогон байт) жазуулар менен иштөө үчүн иштелип чыккан эмес, кысуу катышы 1ден кем болот (башкача айтканда, кысуунун ордуна маалымат көлөмүн көбөйтүү); - Ар бир жаздыруудан кийин FLUSH кылыңыз.
Көптөгөн кысуу китепканаларында FLUSH колдоосу бар. Бул буйрук (же кысуу процедурасынын параметри), аны алгандан кийин архиватор кысылган агымды түзөт, ошондуктан аны калыбына келтирүү үчүн колдонсо болот. бардык буга чейин кабыл алынган кысылбаган маалыматтар. Мындай аналогsyncфайл системаларында жеcommitsql менен.
Маанилүү нерсе, кийинки кысуу операциялары топтолгон сөздүктү колдоно алат жана кысуу катышы мурунку версиядагыдай көп жабыркабайт.
Мен үчүнчү вариантты тандап алганым айдан ачык деп ойлойм, аны кененирээк карап көрөлү.
Табылды zlibдеги FLUSH жөнүндө.
Мен макаланын негизинде тизе сынагын жасадым, чыныгы түзмөктөн 70 миң журнал жазуусун алдым, барактын көлөмү 60 Кб (биз барактын өлчөмүнө кийинчерээк кайтып келебиз) алынган:
алгачкы маалыматтар
Компрессия gzip -9 (FLUSH жок)
zlib Z_PARTIAL_FLUSH менен
zlib Z_SYNC_FLUSH менен
Көлөмү, КБ
1692
40
352
604
Бир караганда, FLUSH берген баа өтө жогору, бирок чындыгында бизде тандоо аз - же такыр кысбоо, же FLUSH менен кысуу (жана абдан эффективдүү). Бизде 70 миң жазуу бар экенин унутпашыбыз керек, Z_PARTIAL_FLUSH киргизген ашыкча жазуу ар бир жазууга 4-5 байт гана түзөт. Ал эми кысуу катышы дээрлик 5:1 болуп чыкты, бул эң сонун натыйжа.
Бул күтүлбөгөн нерсе болушу мүмкүн, бирок Z_SYNC_FLUSH чындыгында FLUSH кылуунун натыйжалуу жолу
Z_SYNC_FLUSH колдонгондо, ар бир жазуунун акыркы 4 байты дайыма 0x00, 0x00, 0xff, 0xff болот. Эгер биз аларды билсек, анда аларды сактоонун кереги жок, ошондуктан акыркы өлчөмү 324 Кб гана.
Мен шилтеме берген макалада түшүндүрмө бар:
Бош мазмуну бар жаңы типтеги 0 блогу тиркелет.
Бош мазмуну бар 0 типтеги блок төмөнкүлөрдөн турат:
- үч биттик блоктун аталышы;
- 0 - 7 бит нөлгө барабар, байтты тегиздөө үчүн;
- төрт байт ырааттуулугу 00 00 FF FF.
Көрүнүп тургандай, бул 4 байттын алдындагы акыркы блокто 3төн 10го чейин нөл бит бар. Бирок, практика көрсөткөндөй, иш жүзүндө жок дегенде 10 нөл бит бар.
Көрсө, мындай кыска маалымат блоктору адатта (ар дайым?) 1-типтеги блоктун (туруктуу блок) жардамы менен коддолгон, ал сөзсүз түрдө 7 нөл бит менен аяктап, жалпысынан 10-17 кепилденген нөл биттерин берет (ал эми калгандары болжол менен 50% ыктымалдыгы менен нөл болот.
Ошентип, тесттик маалыматтарда 100% учурларда 0x00, 0x00, 0xff, 0xff алдында бир нөл байт, ал эми үчтөн биринен көбүрөөгүндө эки нөл байт бар. (балким, мен экилик CBOR колдоном жана JSON текстин колдонууда 2 типтеги блоктор - динамикалык блок кеңири таралган, тиешелүүлүгүнө жараша 0x00, 0x00, 0xff, 0xff чейин кошумча нөл байты жок блоктор кездешет).
Бардыгы болуп, колдо болгон тесттик маалыматтарды колдонуу менен, кысылган маалыматтардын 250 Кб азына батуу мүмкүн.
Бит жонглёру менен бир аз көбүрөөк үнөмдөөгө болот: азыр биз блоктун аягында бир нече нөл биттин болушуна көңүл бурбайбыз, блоктун башында бир нече бит да өзгөрбөйт...
Бирок андан кийин мен токтоо жөнүндө чечкиндүү чечим кабыл алдым, антпесе ушундай темп менен мен өзүмдүн архивимди иштеп чыгууга жетиштим.
Жалпысынан, тесттик маалыматтарымдан мен жазууга 3-4 байт алдым, кысуу катышы 6:1ден ашты. Мен чынчыл болом: Менин оюмча, мындай натыйжаны күткөн эмесмин, 2: 1ден жакшы нерсе - кысуу колдонууну актаган натыйжа;
Баары жакшы, бирок zlib (deflate) дагы эле архаикалык, татыктуу жана бир аз эскирген кысуу алгоритми. Кысылбаган маалымат агымынын акыркы 32 Кб сөздүк катары колдонулушу таң калыштуу көрүнөт (башкача айтканда, кандайдыр бир маалымат блогу 40 Кб мурунку кириш агымында болгонуна абдан окшош болсо, анда ал кайра архивделе баштайт, жана мурунку окуяга шилтеме кылбайт). Модалуу заманбап архивчилерде сөздүктүн көлөмү көбүнчө килобайт менен эмес, мегабайт менен өлчөнөт.
Ошентип, биз архивчилерди изилдөөнү улантабыз.
Андан кийин биз bzip2ди сынап көрдүк (эсиңизде болсун, FLUSH жок, ал дээрлик 100:1 фантастикалык кысуу катышын көрсөткөн). Тилекке каршы, ал FLUSH менен абдан начар аткарылды, кысылган маалыматтардын көлөмү кысылбаган маалыматтардан чоңураак болуп чыкты;
Ийгиликсиздиктин себептери жөнүндө менин божомолдорум
Libbz2 бир гана флеш вариантын сунуштайт, ал сөздүктү тазалайт (zlibдеги Z_FULL_FLUSHга окшош), андан кийин эч кандай эффективдүү кысуу жөнүндө сөз жок.
Ал эми акыркы сыналган zstd болгон. Параметрлерге жараша, ал gzip деңгээлинде кысып, бирок gzipге караганда алда канча тезирээк же жакшыраак.
Тилекке каршы, FLUSH менен ал жакшы иштеген жок: кысылган маалыматтардын көлөмү болжол менен 700 Кб болгон.
Я Долбоордун github баракчасында мен кысылган маалыматтардын ар бир блогу үчүн 10 байтка чейин кызматтык маалыматтарга ишенишиңиз керек деген жооп алдым, бул алынган натыйжаларга жакын, дефлатка жетүүгө эч кандай жол жок;
Мен архивчилер менен болгон эксперименттеримди ушул жерден токтотууну чечтим (xz, lzip, lzo, lz4 FLUSH жок тестирлөө стадиясында да өзүн көрсөтпөгөнүн жана экзотикалык кысуу алгоритмдерин эске алган жокмун).
Архивдөө көйгөйлөрүнө кайрылалы.
Экинчи (алар мааниси боюнча эмес, ирети менен айткандай) көйгөй - кысылган маалыматтар бир агым болуп саналат, анда мурунку бөлүмдөргө дайыма шилтемелер бар. Ошентип, кысылган маалыматтардын бир бөлүгү бузулса, биз кысылбаган маалыматтардын байланышкан блогун гана эмес, андан кийинкилерин да жоготобуз.
Бул маселени чечүү үчүн бир ыкма бар:
- Көйгөйдүн пайда болушун болтурбоо - кысылган маалыматтарга ашыкчаларды кошуу, бул каталарды аныктоого жана оңдоого мүмкүндүк берет; бул жөнүндө кийинчерээк сүйлөшөбүз;
- Эгер көйгөй пайда болсо, кесепеттерин азайтыңыз
Биз буга чейин ар бир маалымат блогун өз алдынча кысуу мүмкүн экенин айтканбыз жана көйгөй өзүнөн-өзү жок болот (бир блоктун маалыматтарынын бузулушу бул блок үчүн гана маалыматтардын жоголушуна алып келет). Бирок, бул маалыматтарды кысуу натыйжасыз боло турган экстремалдык учур. Карама-каршы экстремалдык: биздин чиптин бардык 4МБны бирдиктүү архив катары колдонуңуз, бул бизге эң сонун кысуу, бирок маалыматтар бузулган учурда катастрофалык кесепеттерге алып келет.
Ооба, ишенимдүүлүк жагынан компромисс керек. Бирок биз өтө төмөн BER жана 20 жылдык маалыматтарды сактоо мөөнөтү менен туруксуз эс үчүн маалыматтарды сактоо форматын иштеп жатканыбызды унутпашыбыз керек.
Эксперименттердин жүрүшүндө мен кысуу деңгээлиндеги аздыр-көптүр байкаларлык жоготуулар көлөмү 10 КБдан аз кысылган маалыматтардын блокторунда башталарын байкадым.
Мурда колдонулган эстутум беттелген деп айтылган; мен "бир барак - кысылган маалыматтардын бир блогу" кат алышуусунун колдонулбашы үчүн эч кандай себеп жок.
Башкача айтканда, минималдуу акылга сыярлык барактын көлөмү 16Kb (кызмат маалыматы үчүн резерв менен). Бирок, мындай кичинекей барак өлчөмү максималдуу рекорд өлчөмүнө олуттуу чектөөлөрдү киргизет.
Мен азырынча кысылган түрдө бир нече килобайттан чоңураак жазууларды күтпөйм, бирок мен 32 Кб барактарды колдонууну чечтим (бир чипке жалпысынан 128 барак).
кыскача маалымат:
- Биз zlib (deflate) аркылуу кысылган маалыматтарды сактайбыз;
- Ар бир жазуу үчүн биз Z_SYNC_FLUSH орнотобуз;
- Ар бир кысылган жазуу үчүн биз арткы байттарды кыркабыз (мисалы, 0x00, 0x00, 0xff, 0xff); баш сөздө биз канча байт кесип алганыбызды көрсөтөбүз;
- Биз маалыматтарды 32 Кб барактарда сактайбыз; барактын ичинде кысылган маалыматтардын бирдиктүү агымы бар; Ар бир баракта биз кайрадан кысуу баштайбыз.
Жана, кысуу менен бүтөөрдөн мурун, мен сиздин көңүлүңүздү бир жазууда бир нече байт гана кысылган маалыматтарга ээ экендигине бургум келет, андыктан кызмат маалыматын толтурбоо өтө маанилүү, бул жерде ар бир байт эсептелет.
Маалымат баштарын сактоо
Бизде өзгөрмө узундуктагы жазуулар болгондуктан, кандайдыр бир жол менен жазуулардын жайгашуусун/чектерин аныкташыбыз керек.
Мен үч ыкманы билем:
- Бардык жазуулар үзгүлтүксүз агымда сакталат, адегенде узундугун камтыган жазуу аталышы, андан кийин жазуунун өзү болот.
Бул ишке ашырууда аталыштар да, маалыматтар да өзгөрүлмө узундукта болушу мүмкүн.
Негизи, биз ар дайым колдонулуучу жалгыз шилтемеленген тизмени алабыз; - Баш маалымат жана жазуулар өзүнчө агымдарда сакталат.
Туруктуу узундуктагы аталыштарды колдонуу менен биз бир баш теманын бузулушу башкаларына таасирин тийгизбешин камсыз кылабыз.
Ушундай эле ыкма, мисалы, көптөгөн файл системаларында колдонулат; - Жазуулар үзгүлтүксүз агымда сакталат, жазуу чеги белгилүү бир маркер менен аныкталат (маалымат блокторунда тыюу салынган символ/символдордун ырааттуулугу). Жазуунун ичинде маркер бар болсо, анда биз аны кандайдыр бир ырааттуулук менен алмаштырабыз (андан качабыз).
Ушундай эле ыкма, мисалы, МЖӨ протоколунда колдонулат.
Мен иллюстрациялайм.
Option 1:

Бул жерде бардыгы абдан жөнөкөй: жазуунун узундугун билүү менен, кийинки аталыштын дарегин эсептей алабыз. Ошентип, биз 0xff (эркин аймак) же барактын аягы менен толтурулган аймакка туш болмоюнча, рубрикалар аркылуу жылабыз.
Option 2:

Жазуунун өзгөрмө узундугуна байланыштуу, биз бир бетке канча жазуу (демек, баштар) керек болорун алдын ала айта албайбыз. Сиз баш жана маалыматтардын өзүн ар кандай барактарга тарата аласыз, бирок мен башка ыкманы жактырам: биз баш саптарды да, маалыматтарды да бир бетке жайгаштырабыз, бирок баш саптар (туруктуу өлчөмдө) барактын башынан келет жана маалыматтар (өзгөрмө узундуктагы) аягында келет. Алар "жолугушуу" менен (жаңы жазуу үчүн бош орун жетишсиз), биз бул баракты толук деп эсептейбиз.
Option 3:

Жазуулардын чектерин көрсөткөн маркерлердин узундугун же жайгашкан жери жөнүндө башка маалыматты сактоонун кажети жок; Бирок, жазуу/окуу учурунда маалыматтар иштетилиши керек.
Мен маркер катары 0xff колдонот элем (тазалангандан кийин баракты толтурат), андыктан бош аймак сөзсүз түрдө маалымат катары каралбайт.
Салыштыруу таблицасы:
параметр 1
параметр 2
параметр 3
Ката толеранттуулук
-
+
+
жыштыгы
+
-
+
Ишке ашыруунун татаалдыгы
*
**
**
1-варианттын өлүмгө алып келе турган кемчилиги бар: эгерде баш элементтердин бири бузулса, кийинки чынжыр толугу менен бузулат. Калган варианттар чоң зыянга учураган учурда да айрым маалыматтарды калыбына келтирүүгө мүмкүндүк берет.
Бирок бул жерде биз маалыматтарды кысылган түрдө сактоону чечкенибизди эстен чыгарбоо керек, ошондуктан биз "сынган" жазуудан кийин барактагы бардык маалыматтарды жоготуп алабыз, ошондуктан таблицада минус болсо да, биз аны эске алуу.
Компакттуулук:
- биринчи вариантта, эгер биз өзгөрмө узундуктагы бүтүн сандарды колдонсок, анда биз бир байт менен гана ала алабыз;
- экинчи вариантта биз баштапкы даректи жана узундукту сакташыбыз керек; жазуу туруктуу өлчөм болушу керек, мен бир жазуу үчүн 4 байт деп эсептейм (офсет үчүн эки байт, узундугу үчүн эки байт);
- үчүнчү вариант жаздыруунун башталышын көрсөтүү үчүн бир гана белгини талап кылат, плюс жазуунун өзү экрандан улам 1-2% га көбөйөт. Жалпысынан алганда, биринчи параметр менен болжолдуу паритет.
Башында мен экинчи вариантты негизги деп эсептедим (жана ишке ашырууну да жаздым). Акыры компрессияны колдонууну чечкенде гана мен андан баш тарттым.
Балким, качандыр бир күнү мен дагы ушундай вариантты колдоном. Мисалы, мен Жер менен Марстын ортосунда саякаттаган кеме үчүн маалыматтарды сактоо менен алектенишим керек болсо, анда ишенимдүүлүк, космостук нурлануу, ... үчүн такыр башка талаптар болот.
Үчүнчү вариантка келсек: мен аны ишке ашыруунун татаалдыгы үчүн эки жылдыз бердим, анткени мен калканч менен аралашканды, процесстин узундугун өзгөртүүнү ж.б. Ооба, балким, мен бир жактуумун, бирок мен кодду жазууга туура келет - эмне үчүн өзүңүздү жакпаган нерсени кылууга мажбурлашыңыз керек.
кыскача маалымат: Натыйжалуулугуна жана ишке ашыруунун оңойлугуна байланыштуу "узундуктагы баш - өзгөрмө узундуктагы маалыматтар" чынжырчалар түрүндө сактоо опциясын тандайбыз.
Жазуу операцияларынын ийгилигине мониторинг жүргүзүү үчүн бит талааларын колдонуу
Мен бул идеяны кайдан алганым азыр эсимде жок, бирок ал мындай окшойт:
Ар бир жазуу үчүн биз желектерди сактоо үчүн бир нече бит бөлүп беребиз.
Мурда айткандай, өчүргөндөн кийин бардык биттер 1лер менен толтурулат жана биз 1ди 0гө өзгөртө алабыз, бирок тескерисинче эмес. Ошентип, "желек коюлган эмес" үчүн биз 1ди, "туу коюлган" үчүн 0ду колдонобуз.
Бул жерде өзгөрүлмө узундуктагы жазууну флешке коюу төмөнкүдөй болушу мүмкүн:
- "Узундукту жазуу башталды" желекчесин коюу;
- Узундугун жазыңыз;
- "Маалыматтарды жазуу башталды" желегин коюу;
- Биз маалыматтарды жазуу;
- "Жазуу аяктады" желекчесин коюңуз.
Мындан тышкары, бизде "ката кетти" желекчеси болот, жалпысынан 4 бит желекчелер.
Бул учурда, бизде эки туруктуу абал бар "1111" - жазуу баштала элек жана "1000" - жазуу ийгиликтүү болду; жаздыруу процесси күтүлбөгөн үзгүлтүккө учураган учурда, биз андан кийин аныктап, иштеп чыга турган аралык абалдарды алабыз.
Бул ыкма кызыктуу, бирок ал күтүлбөгөн жерден электр энергиясынын үзгүлтүккө учурашынан жана ушул сыяктуу бузулуулардан гана коргойт, бул, албетте, маанилүү, бирок бул мүмкүн болгон каталардын жалгыз (же ал тургай негизги) себебинен алыс.
кыскача маалымат: Жакшы чечимди издөөнү уланталы.
Текшерүү суммалары
Текшерүү суммалары ошондой эле биз эмнени жазышыбыз керек экенин так окуп жатканыбызга (акылга сыярлык ыктымалдуулук менен) ынанууга мүмкүндүк берет. Жана, жогоруда талкууланган бит талааларынан айырмаланып, алар ар дайым иштешет.
Эгерде биз жогоруда талкуулаган көйгөйлөрдүн потенциалдуу булактарынын тизмесин карасак, анда текшерүү суммасы катаны анын келип чыгышына карабастан тааный алат. (балким, зыяндуу келгиндерден башкасы - алар текшерүү суммасын да жасалмалашы мүмкүн).
Демек, биздин максатыбыз маалыматтардын бузулбаганын текшерүү болсо, текшерүү суммалары сонун идея.
Контролдук сумманы эсептөө үчүн алгоритмди тандоо эч кандай суроолорду жараткан жок - CRC. Бир жагынан, математикалык касиеттер каталардын айрым түрлөрүн 100% кармоого мүмкүндүк берет, экинчи жагынан, кокус маалыматтарда бул алгоритм кагылышуулардын ыктымалдыгын теориялык чектен көп эмес көрсөтөт;
. Бул эң ылдам алгоритм эмес, кагылышуулардын саны боюнча ар дайым минималдуу эмес, бирок ал абдан маанилүү сапатка ээ: мен жолуккан сыноолордо, ал ачыктан-ачык иштебей калган схемалар болгон эмес. Бул учурда туруктуулук негизги сапат болуп саналат.
Көлөмдүү изилдөөнүн мисалы: , (narod.ru шилтемеси, кечиресиз).
Бирок, текшерүү суммасын тандоо милдети толук эмес. Сиз узундугу жөнүндө чечим кабыл алышы керек, андан кийин көп мүчө тандоо.
Көзөмөл суммасынын узундугун тандоо биринчи караганда көрүнгөндөй жөнөкөй маселе эмес.
Мен мисал келтирейин:
Ар бир байтта ката болуу ыктымалдыгын алалы
жана идеалдуу текшерүү суммасы, келгиле, миллион жазуудагы каталардын орточо санын эсептеп көрөлү:
Берилиштер, байт
Текшерүү суммасы, байт
Аныкталбаган каталар
Жалган каталарды аныктоо
Жалпы жалган позитивдер
1
0
1000
0
1000
1
1
4
999
1003
1
2
≈0
1997
1997
1
4
≈0
3990
3990
10
0
9955
0
9955
10
1
39
990
1029
10
2
≈0
1979
1979
10
4
≈0
3954
3954
1000
0
632305
0
632305
1000
1
2470
368
2838
1000
2
10
735
745
1000
4
≈0
1469
1469
Баары жөнөкөй окшойт - корголгон маалыматтардын узундугуна жараша, минималдуу туура эмес позитивдер менен текшерүү суммасынын узундугун тандаңыз - жана айла-амал баштыкта.
Бирок, кыска контролдук суммалар менен көйгөй пайда болот: алар бир бит каталарды аныктоодо жакшы болсо да, алар бир кыйла жогорку ыктымалдуулук менен толугу менен кокус маалыматтарды туура деп кабыл алышат. Буга чейин Habré сүрөттөгөн макала бар болчу .
Ошондуктан, кокус текшерүү суммасын дал келүү дээрлик мүмкүн эмес кылуу үчүн, узундугу 32 бит же андан көп болгон контролдук суммаларды колдонушуңуз керек. (64 биттен ашкан узундуктар үчүн, адатта, криптографиялык хэш-функциялар колдонулат).
Мурда мейкиндикти үнөмдөө керек деп жазганыма карабастан, биз дагы эле 32 биттик текшерүү суммасын колдонобуз (16 бит жетишсиз, кагылышуу ыктымалдыгы 0.01% дан жогору; жана 24 бит, анткени алар айт, бул жерде да, ал жакта да жок) .
Бул жерде каршылык пайда болушу мүмкүн: азыр бир эле учурда 4 байт берүү үчүн кысуу тандоодо ар бир байтты сактадыкпы? Кысылбай же контролдук сумманы кошпой эле койсо болбойбу? Албетте, жок, кысуу жок мааниси жок, бизге бүтүндүгүн текшерүүнүн кереги жок.
Көп мүчөнү тандоодо биз дөңгөлөктү кайра ойлоп таппайбыз, бирок азыр популярдуу болгон CRC-32Сти алабыз.
Бул код 6 байтка чейинки пакеттерде 22 бит каталарды (балким, биз үчүн эң кеңири таралган учур), 4 байтка чейинки пакеттерде 655 бит каталарды (биз үчүн дагы жалпы учур), 2 же пакеттердеги так сандагы бит каталарды аныктайт ар кандай акылга сыярлык узундугу.
Эгер кимдир бирөө майда-чүйдөсүнө чейин кызыкдар болсо
CRC жөнүндө.
боюнча — балким, планетадагы башкы CRC адиси.
В болуп саналат , бул бизге тиешелүү болгон пакеттердин узундугу үчүн бир аз жакшыраак параметрлерди камсыз кылат, бирок мен айырманы олуттуу деп эсептеген жокмун жана мен стандарттуу жана жакшы изилденген коддун ордуна колдонуучунун кодун тандоого жетиштүү компетенттүү болдум.
Ошондой эле, биздин маалыматтар кысылгандыктан, суроо туулат: кысылган же кысылбаган маалыматтардын текшерүү суммасын эсептешибиз керекпи?
Кысылбаган маалыматтардын текшерүү суммасын эсептөөнүн пайдасына аргументтер:
- Биз акыр аягында маалыматтарды сактоонун коопсуздугун текшеришибиз керек - ошондуктан биз аны түздөн-түз текшеребиз (ошол эле учурда кысуу/декомпрессияны ишке ашыруудагы мүмкүн болгон каталар, бузулган эс тутумдун бузулушу жана башкалар текшерилет);
- Zlibдеги дефлат алгоритми жетишээрлик жетилген ишке ашырууга жана керек эмес, "кыйшык" киргизүү маалыматтары менен түшүү, андан тышкары, ал көп учурда катаны аныктоонун жалпы ыктымалдыгын төмөндөтүп, киргизүү агымындагы каталарды өз алдынча аныктай алат (кыска жазууда бир битти тескерилөө менен тест жүргүздү, zlib катаны аныктады; учурлардын үчтөн биринде).
Кысылбаган маалыматтардын текшерүү суммасын эсептөөгө каршы аргументтер:
- CRC атайын флеш-эстутумга мүнөздүү болгон бир нече бит каталар үчүн “ыңгайлаштырылган” (кысылган агымдагы бит катасы чыгуу агымынын чоң өзгөрүшүнө алып келиши мүмкүн, бул боюнча, теориялык жактан алганда, биз кагылышууну “кармап алабыз”);
- Мүмкүн болгон бузулган маалыматтарды декомпрессорго өткөрүү идеясы мага жаккан жок, ал кандай реакция кылат.
Бул долбоордо мен кысылбаган маалыматтардын текшерүү суммасын сактоо боюнча жалпы кабыл алынган практикадан четтөөнү чечтим.
кыскача маалымат: Биз CRC-32C колдонобуз, биз маалыматтан текшерүү суммасын флешке жазылган формада эсептейбиз (кысылуудан кийин).
Артыкчылык
Ашыкча коддоону колдонуу, албетте, маалыматтардын жоголушун жок кылбайт, бирок, ал олуттуу түрдө (көбүнчө чоңдуктагы көптөгөн буйруктар боюнча) калыбына келтирилгис маалымат жоготуу ыктымалдыгын азайтат.
Биз каталарды оңдоо үчүн ар кандай ашыкча түрлөрүн колдоно алабыз.
Хамминг коддору бир бит каталарды оңдой алат, Рид-Соломон тамга коддору, контролдук суммалар менен айкалышкан маалыматтардын бир нече көчүрмөсү же RAID-6 сыяктуу коддоолор массалык коррупция болгон учурда да маалыматтарды калыбына келтирүүгө жардам берет.
Башында, мен каталарга туруктуу коддоонун кеңири жайылышын көздөп жүрдүм, бирок андан кийин биз алгач өзүбүздү кандай каталардан коргогубуз келгени жөнүндө түшүнүккө ээ болушубуз керек экенин түшүндүм, андан кийин коддоону тандашыбыз керек.
Биз мурда каталарды мүмкүн болушунча тезирээк кармоо керек деп айтканбыз. Кайсы учурларда каталарга туш болушубуз мүмкүн?
- Бүтпөгөн жазуу (жазып жатканда кандайдыр бир себептерден улам электр энергиясы өчүп калган, малина катып калган, ...)
Тилекке каршы, мындай ката болгон учурда, жараксыз жазууларды этибарга албай, маалыматтарды жоготкон деп эсептөө гана калды; - Жазуу каталары (негедир флеш эстутумга жазылган нерсе жазылган эмес)
Жазгандан кийин дароо текшерүүнү окусак, мындай каталарды дароо байкай алабыз; - Сактоо учурунда эстутумдагы маалыматтардын бурмаланышы;
- Окуу каталары
Аны оңдоо үчүн текшерүү суммасы дал келбесе, окууну бир нече жолу кайталоо жетиштүү.
Башкача айтканда, үчүнчү типтеги каталарды гана (сактоо учурунда маалыматтардын стихиялуу бузулушу) катага туруктуу коддоосуз оңдоо мүмкүн эмес. Мындай каталар дагы эле өтө күмөндүү окшойт.
кыскача маалымат: ашыкча коддоодон баш тартуу чечими кабыл алынды, бирок эгерде операция бул чечимдин катасын көрсөтсө, анда маселени кароого кайтыңыз (коддоштуруунун оптималдуу түрүн тандоого мүмкүндүк берүүчү каталар боюнча буга чейин топтолгон статистика менен).
Прочее
Албетте, макаланын форматы форматтагы ар бир бит актоого мүмкүндүк бербейт (жана менин күчүм түгөндү), ошондуктан мен мурда козголбогон кээ бир пункттарга кыскача токтоло кетейин.
- Бардык барактарды «тең» кылуу чечими кабыл алынды
Башкача айтканда, метадайындар, өзүнчө жиптер ж.б. бар атайын барактар болбойт, анын ордуна бардык барактарды кезеги менен кайра жаза турган бир жип болот.
Бул барактардын бир калыпта эскирүүсүн камсыздайт, бир дагы ката кетирбейт жана мага жагат; - Форматтын версиясын камсыз кылуу зарыл.
Башында версия номери жок формат жаман!
Беттин башына белгилүү бир сыйкырдуу номери (колу) бар талааны кошуу жетиштүү, ал колдонулган форматтын версиясын көрсөтөт. (Иш жүзүндө алардын ондогону болот деп ойлобойм); - Жазуулар үчүн өзгөрүлмө узундуктагы башты колдонуңуз (алардын саны көп), көпчүлүк учурда аны 1 байт узун кылууга аракет кылыңыз;
- Баштын узундугун жана кысылган жазуунун кесилген бөлүгүнүн узундугун коддоо үчүн өзгөрмө узундуктагы экилик коддорду колдонуңуз.
Көп жардам берди Хаффман коддору. Бир нече мүнөттүн ичинде биз керектүү өзгөрмө узундуктагы коддорду тандап алдык.
Маалыматтарды сактоо форматынын сүрөттөлүшү
Байт тартиби
Бир байттан чоң талаалар big-endian форматында сакталат (тармак байт тартиби), башкача айтканда, 0x1234 0x12, 0x34 деп жазылат.
Барактоо
Бардык флэш эстутум бирдей өлчөмдөгү барактарга бөлүнгөн.
Демейки беттин өлчөмү 32 Кб, бирок эстутум микросхемасынын жалпы көлөмүнүн 1/4 бөлүгүнөн ашпайт (4 МБ чип үчүн 128 барак алынат).
Ар бир барак маалыматтарды башкалардан көз карандысыз сактайт (башкача айтканда, бир барактагы маалымат башка барактагы маалыматтарга шилтеме кылбайт).
Бардык беттер натурал тартипте (даректердин өсүү тартибинде) 0 номеринен баштап номерленет (нөл барак 0 даректен башталат, биринчи барак 32Кбдан башталат, экинчи барак 64Кбдан башталат ж.б.)
Эстутум микросхемасы циклдик буфер (шакек буфери) катары колдонулат, башкача айтканда, адегенде жазуу 0-бетке, андан кийин 1-санга, ..., акыркы баракты толтурганыбызда жаңы цикл башталат жана жазуу нөлдүк барактан уланат. .
Барактын ичинде

Барактын башында 4 байт барактын аталышы сакталат, андан кийин баш маалымат текшерүү суммасы (CRC-32C), андан кийин жазуулар “баш, маалыматтар, текшерүү суммасы” форматында сакталат.
Барактын аталышы (диаграммада кир жашыл) төмөнкүлөрдөн турат:
- эки байт сыйкырдуу номер талаасы (ошондой эле формат версиясынын белгиси)
форматтын учурдагы версиясы үчүн ал катары эсептелет0xed00 ⊕ номер страницы; - эки байт эсептегич "Барак версиясы" (эстутумду кайра жазуу циклинин номери).
Барактагы жазуулар кысылган түрдө сакталат (дефлят алгоритми колдонулат). Бир беттеги бардык жазуулар бир жипте кысылган (жалпы сөздүк колдонулат) жана ар бир жаңы баракта кысуу жаңыдан башталат. Башкача айтканда, кандайдыр бир жазууну ачуу үчүн бул барактагы бардык мурунку жазуулар (жана ушул гана) талап кылынат.
Ар бир жазуу Z_SYNC_FLUSH желекчеси менен кысылып, кысылган агымдын аягында 4 байт 0x00, 0x00, 0xff, 0xff болот, мүмкүн алдында дагы бир же эки нөл байт болот.
Флэш эстутумга жазып жатканда бул ырааттуулукту (узундугу 4, 5 же 6 байт) жокко чыгарабыз.
Жазуунун аталышы 1, 2 же 3 байт сактайт:
- жазуу түрүн көрсөтүүчү бир бит (T): 0 - контекст, 1 - журнал;
- 1ден 7 битке чейинки өзгөрүлмө узундук талаасы (S), баштын узундугун жана декомпрессия үчүн жазууга кошулууга тийиш болгон "куйрукту" аныктайт;
- рекорд узундугу (L).
S наркынын таблицасы:
S
Баш маалымат узундугу, байт
Жазууда ташталган, байт
0
1
5 (00 00 00 ff ff)
10
1
6 (00 00 00 00 ff ff)
110
2
4 (00 00 ff ff)
1110
2
5 (00 00 00 ff ff)
11110
2
6 (00 00 00 00 ff ff)
1111100
3
4 (00 00 ff ff)
1111101
3
5 (00 00 00 ff ff)
1111110
3
6 (00 00 00 00 ff ff)
Мен сүрөттөөгө аракет кылдым, анын канчалык айкын болгонун билбейм:

Бул жерде сары түс T талаасын, ак S талаасын, жашыл L (кысылган маалыматтардын байт менен узундугу), көк кысылган маалыматтарды, кызыл флеш-эске жазылбаган кысылган маалыматтардын акыркы байттарын көрсөтөт.
Ошентип, биз бир байтта эң кеңири таралган узундуктагы (кысылган түрдө 63+5 байтка чейин) жазуу аталыштарын жаза алабыз.
Ар бир жазуудан кийин CRC-32C контролдук суммасы сакталат, анда мурунку текшерүү суммасынын инверттелген мааниси баштапкы маани (init) катары колдонулат.
CRC "узактыгы" касиетине ээ, төмөнкү формула иштейт (процессте плюс же минус бит инверсиясы):
.
Башкача айтканда, биз бул баракчадагы бардык мурунку байттардын жана маалыматтардын CRCин эсептейбиз.
Түздөн-түз текшерүү суммасынан кийинки жазуунун баш аты.
Аталышы анын биринчи байттары ар дайым 0x00 жана 0xffден айырмаланып тургандай кылып иштелип чыккан (эгерде баштын биринчи байтынын ордуна 0xff жолуксак, анда бул пайдаланылбаган аймак экенин билдирет; 0x00 катаны билдирет).
Мисал алгоритмдер
Flash эс тутумунан окуу
Ар кандай окуу текшерүү суммасын текшерүү менен келет.
Эгерде текшерүү суммасы дал келбесе, анда туура маалыматтарды окуу үмүтү менен окуу бир нече жолу кайталанат.
(бул түшүнүктүү, Linux NOR Flash'тан алынган көрсөткүчтөрдү кэштебейт, текшерилген)
Флэш эстутумга жазыңыз
Биз маалыматтарды жазып жатабыз.
Келгиле, аларды окуйлу.
Окулган маалыматтар жазылган маалыматтарга дал келбесе, анда биз аймакты нөлгө толтуруп, ката жөнүндө сигнал беребиз.
Жаңы микросхеманы иштетүүгө даярдоо
Инициализациялоо үчүн 1-версиясы бар аталыш биринчи (же тагыраак айтканда нөл) баракка жазылат.
Андан кийин, баштапкы контекст бул баракка жазылат (машинанын UUID жана демейки жөндөөлөрдү камтыйт).
Болду, флеш-эс тутум колдонууга даяр.
Машина жүктөлүүдө
Жүктөлүп жатканда, ар бир барактын алгачкы 8 байты (баш аты + CRC) окулат, белгисиз Сыйкырдуу номери же туура эмес CRC бар барактар этибарга алынбайт.
«Туура» барактардан максималдуу версиясы бар барактар тандалып алынат жана алардан эң көп сандагы барак алынат.
Биринчи жазуу окулат, КРКнын тууралыгы жана "контекст" желекчесинин бар-жоктугу текшерилет. Эгер баары жакшы болсо, бул барак учурдагы деп эсептелет. Болбосо, биз "жандуу" баракты тапканга чейин мурункуга кайтабыз.
жана табылган баракта биз "контекст" желек менен колдонгон бардык жазууларды окуйбуз.
zlib сөздүгүн сактаңыз (бул баракка кошуу үчүн керек болот).
Болду, жүктөө аяктады, контекст калыбына келтирилди, сиз иштей аласыз.
Журналга жазуу кошуу
Биз жазууну туура сөздүк менен кысып, Z_SYNC_FLUSH көрсөтүү менен кысылган жазуу учурдагы баракка туура келерин көрөбүз.
Эгерде ал туура келбесе (же баракта CRC каталары бар болсо), жаңы баракты баштаңыз (төмөндө караңыз).
Биз жазуу жана CRC жазып. Ката пайда болсо, жаңы баракты баштаңыз.
Жаңы бет
Биз минималдуу саны менен акысыз баракты тандайбыз (биз бекер баракты баш жагында туура эмес текшерүү суммасы бар же учурдагыдан азыраак версиясы бар барак деп эсептейбиз). Эгерде андай барактар жок болсо, азыркыга барабар версиясы барлардын ичинен минималдуу саны бар баракты тандаңыз.
Тандалган баракты өчүрөбүз. Биз мазмунду 0xff менен текшеребиз. Эгер бир нерсе туура эмес болсо, кийинки акысыз баракты алып, ж.б.
Өчүрүлгөн баракка баш жазууну жазабыз, биринчи жазуу контексттин учурдагы абалы, кийинкиси жазылбаган журнал жазуусу (эгерде бар болсо).
Форматтын колдонулушу
Менин оюмча, бул NOR Flash ичинде аздыр-көптүр кысылган маалымат агымдарын (жөнөкөй текст, JSON, MessagePack, CBOR, мүмкүн protobuf) сактоо үчүн жакшы формат болуп чыкты.
Албетте, формат SLC NOR Flash үчүн "ыңгайлаштырылган".
Аны NAND же MLC NOR сыяктуу жогорку BER медиалары менен колдонууга болбойт (мындай эстутум сатуу үчүн да барбы? Мен аны оңдоо коддору боюнча эмгектерде гана көргөм).
Мындан тышкары, ал өзүнүн FTL'и бар түзмөктөр менен колдонулбашы керек: USB флеш, SD, MicroSD ж.б (Мындай эс тутум үчүн мен 512 байт барак өлчөмү, ар бир барактын башында кол тамга жана уникалдуу жазуу номерлери бар форматты түздүм - кээде жөнөкөй ырааттуу окуу менен "жасаган" флеш-дисктен бардык маалыматтарды калыбына келтирүүгө мүмкүн болгон).
Милдеттерге жараша формат 128Кбиттен (16Кб) 1Гбитке (128МБ) чейин флеш дисктерде өзгөрүүсүз колдонулушу мүмкүн. Кааласаңыз, аны чоңураак микросхемаларда колдонсоңуз болот, бирок сиз барактын өлчөмүн тууралашыңыз керек болот (Бирок бул жерде экономикалык максатка ылайыктуулугу жөнүндө суроо туулат; чоң көлөмдөгү NOR Flash баасы кубандырбайт).
Эгер кимдир бирөө форматты кызыктуу деп тапса жана аны ачык долбоордо колдонууну кааласа, жаз, мен убакыт таап, кодду жылтыратып, аны githubга жайгаштырууга аракет кылам.
жыйынтыктоо
Көрүнүп тургандай, аягында формат жөнөкөй болуп чыкты жана ал тургай кызыксыз.
Макалада менин көз карашымдын эволюциясын чагылдыруу кыйын, бирок мага ишенип коюңуз: адегенде мен татаал, бузулбас, жакын жердеги өзөктүк жарылуудан да аман чыга ала турган нерсени жараткым келди. Бирок, акыл (мен үмүттөнөм) дагы эле жеңишке жетишти жана бара-бара артыкчылыктар жөнөкөйлүккө жана компакттуулукка өттү.
Балким, мен жаңылышкандырмын? Ооба албетте. Мисалы, биз сапаты төмөн микросхемалардын партиясын сатып алганбыз. Же кандайдыр бир башка себептерден улам жабдуулар ишенимдүүлүк күтүүлөргө жооп бербейт.
Бул үчүн менде план барбы? Макаланы окугандан кийин план бар экенине эч кандай шек жок деп ойлойм. Ал тургай жалгыз эмес.
Бир аз олуттуураак айтканда, формат жумушчу вариант катары да, "сыноо шары" катары да иштелип чыккан.
Учурда столдун үстүндө баары жакшы иштеп жатат, түзмө-түз башка күнү чечим жайылтылат (болжол менен) жүздөгөн түзмөктөрдө, келгиле, "согуштук" операцияда эмне болорун карап көрөлү (бактыга жараша, формат каталарды ишенимдүү аныктоого мүмкүндүк берет деп үмүттөнөм; андыктан толук статистиканы чогулта аласыз). Бир нече айдан кийин жыйынтык чыгарууга болот (жана бактысыз болсоңуз, андан да эрте).
Эгерде колдонуунун жыйынтыгы боюнча олуттуу көйгөйлөр табылса жана жакшыртуулар талап кылынса, анда мен бул тууралуу сөзсүз жазам.
адабият
Мен колдонулган иштердин узун тажатма тизмесин түзгүм келген жок, бардыгында Google бар.
Бул жерде мен мага өзгөчө кызыктуу көрүнгөн табылгалардын тизмесин калтырууну чечтим, бирок акырындык менен алар түздөн-түз макаланын текстине өтүп, бир пункт тизмеде калды:
- Коммуналдык автордон zlib. deflate/zlib/gzip архивинин мазмунун так көрсөтө алат. Эгерде сизде deflate (же gzip) форматынын ички түзүмү менен күрөшүүгө туура келсе, мен аны абдан сунуштайм.
Source: www.habr.com
