14.3.3. Hygiena souborového systému¶
Flash paměť a SD úložiště na nasazené kameře se zaplní soubory, které žádný operátor nebude ručně mazat. Dvě rozhodnutí o tomto úložišti zůstávají s produktem po celou jeho životnost: která plocha uchovává jaký druh dat a jak jsou adresáře strukturovány, aby souborové operace fungovaly i s tím, jak aplikace hromadí záznamy.
14.3.3.1. Kam co patří¶
Kód a prostředky se vezou ve zmražených modulech a ROMFS, které sestavení potvrdí v okamžiku dodání. Stav aplikace – cokoli, co aplikace zapisuje za běhu, cokoli, co roste, cokoli, co se mezi spuštěními mění – musí být uloženo někde jinde. Kamera pro to vystavuje dvě zapisovatelné plochy:
Interní flash na
/flash: malý zapisovatelný souborový systém připojený dříve, než se spustí jakýkoli aplikační kód. Správné místo pro malé záznamy pevné velikosti, které přežijí restarty: konfigurace, kterou aplikace aktualizuje za běhu, poslední známá kalibrace, průběžný čítač, jednořádkový značkovací soubor říkající „tato kamera byla zprovozněna.“ Omezený počet zápisových cyklů – moderní interní flash paměť snese tisíce až desetitisíce zápisů na sektor, nikoli miliony, takže zápisy musí být řídké, ne pro každý snímek.SD karta na
/sdcard: větší zapisovatelný souborový systém připojený, když je karta přítomna. Správné místo pro objemné soubory proměnlivé velikosti: záznamy obrazu a videa, log soubory, data pro doladění modelu, cokoli, co může narůst na megabajty nebo gigabajty. Vyšší kapacita zápisu než interní flash paměť, ale stále konečná; vyjímatelná, vyměnitelná a plocha, která nejpravděpodobněji zmizí, když je aplikace uprostřed zápisu.
Správná odpověď na to, kam něco zapsat, je téměř vždy „flash pro malé pevné záznamy, SD pro všechno ostatní.“ Tyto dvě plochy nejsou zaměnitelné: aplikace, která čmárá svůj průběžný log soubor do /flash, vyčerpá zápisovou odolnost flash paměti v nasazení, které by na SD bylo bez problémů.
14.3.3.2. Považujte obě za schopné selhání¶
/flash i /sdcard mohou obě selhat. SD karta může být vysunuta, flash paměť může být poškozena výpadkem napájení uprostřed zápisu, oběma může dojít místo a jakákoli operace na kterékoli z nich může vyvolat OSError z důvodů, které aplikace v terénu nebude mít šanci diagnostikovat.
Aplikaci pomohou přežít dva vzory:
Obalte připojení a operace do try bloků. Každé
open(),os.listdir(),os.rename()proti cestám s uživatelskými daty může potenciálně selhat. ZachyťteOSError, zaznamenejte jej do logu a uchylte se k definované alternativě – zapište do/flash, pokud/sdcardchybí, nebo operaci přeskočte, pokud není k dispozici ani jedna.Atomické zápisy pro soubory, které musí přežít výpadek napájení. Zapište do dočasné cesty, zavřete handle a poté pomocí
os.rename()přepište živý název. Buď přejmenování uspělo a soubor je novou verzí, nebo neuspělo a soubor je starou verzí. Neexistuje žádný třetí stav, kdy je soubor zapsán napůl:import os def write_config_atomic(path, contents): tmp = path + '.tmp' with open(tmp, 'w') as f: f.write(contents) f.flush() os.rename(tmp, path)
Tento vzor funguje na flash i na SD. Nefunguje pro soubory dostatečně velké na to, aby dočasný soubor spotřeboval volné místo souborového systému; vyhraďte jej pro malé záznamy.
14.3.3.3. Past pomalého adresáře¶
MicroPython VFS neindexuje obsah adresářů tak, jak to dělá souborový systém na počítači. os.listdir() a os.stat() procházejí podkladovou tabulku souborů lineárně. Adresář se stovkou souborů je v pořádku; adresář s deseti tisíci soubory je nepoužitelně pomalý, kdy každé os.listdir() trvá sekundy a každé open() kontroluje tabulku při svém průchodu.
Aplikace, které zapisují logy nebo záznamy na disk, na to narazí nejrychleji. Naivní schéma /sdcard/logs/<timestamp>.log, které otevírá jeden nový soubor každou minutu, zaplní adresář logs/ půl milionem souborů za rok nasazení. Dlouho předtím začne aplikace ztrácet svou snímkovou frekvenci, protože každé otevření souboru trvá déle než interval mezi snímky.
Správný vzor je rozdělit soubory do stromu datovaných podadresářů tak, aby žádný jednotlivý adresář nikdy neobsahoval více než pár stovek položek:
import os
import time
LOG_ROOT = '/sdcard/logs'
def log_path(now=None):
if now is None:
now = time.localtime()
year, month, day, hour = now[0], now[1], now[2], now[3]
directory = '{}/{:04d}/{:02d}/{:02d}'.format(
LOG_ROOT, year, month, day)
_makedirs(directory)
return '{}/{:02d}.log'.format(directory, hour)
def _makedirs(path):
# os.makedirs equivalent -- create each level if missing
parts = path.split('/')
for i in range(2, len(parts) + 1):
sub = '/'.join(parts[:i])
try:
os.mkdir(sub)
except OSError:
pass
Rok logování po jednom souboru za hodinu je nyní rozprostřen do 365 denních adresářů, z nichž každý obsahuje nejvýše 24 souborů; os.listdir() proti kterémukoli adresáři zůstává levné a smyčka zpracování snímků aplikace se nezaseká na souborových operacích, jak nasazení stárne.
Stejný princip platí pro záznamy obrazu, stopy senzoru nebo cokoli jiného, pro co aplikace zapisuje soubor na událost. Pokud je frekvence událostí vysoká, strom by měl být hlubší (rok/měsíc/den/hodina nebo rok/měsíc/den/hodina/minuta), aby každý koncový adresář zůstal malý. Pokud je frekvence událostí nízká, strom rok/měsíc stačí.
14.3.3.4. Cesty pro jednotlivá zařízení¶
Ve flotile více než jedné kamery musí log soubory identifikovat, ze které fyzické jednotky pocházejí. machine.unique_id() vrací hardwarový identifikátor zabudovaný do kamery ve výrobě; je to stejná hodnota napříč restarty, napříč aktualizacemi firmwaru a napříč výměnami SD karet. Vložte jej do cesty logu nebo do log záznamů a operátor, který se dívá na hromadu SD karet nebo na centralizovaný log, dokáže určit, která je která:
import binascii
import machine
UNIT_ID = binascii.hexlify(machine.unique_id()).decode()
LOG_ROOT = '/sdcard/logs/' + UNIT_ID
V kombinaci se vzorem datovaných podadresářů se rozvržení stane /sdcard/logs/<unit-id>/2026/06/09/14.log – hodina záznamů jedné jednotky, v adresáři dostatečně mělkém na procházení, na cestě, která pojmenovává jednotku přímo v souborovém systému.
14.3.3.5. Shrnutí¶
Zapisovatelné úložiště nasazené kamery vypadá zhruba takto:
/flash– konfigurace, kalibrace, značka zprovoznění. Zapisováno zřídka, čteno často. Vzor atomického přejmenování pro jakýkoli soubor, jehož ztráta by narušila příští spuštění./sdcard/logs/<unit-id>/<year>/<month>/<day>/<hour>.log– provozní log. Zapisován nepřetržitě, rotován cestou, nikdy zapisován do adresáře s tisíci sourozenců./sdcard/captures/<unit-id>/<year>/<month>/<day>/– záznamy obrazu nebo videa, které aplikace pořizuje. Stejný tvar stromu, stejný důvod.
Toto rozvržení stojí aplikaci asi dvacet řádků kódu a ušetří ji od režimů selhání, které kameru vyřadí z provozu měsíce po zahájení nasazení.