Červenec 2009
www.moxa.cz
Moxa Zpravodaj
 
 
Hlavní téma

Jak se vyhnout nástrahám při vývoji softwaru pro vestavné aplikace

Ačkoli psaní softwaru pro vestavné počítače může vypadat jednoduše, zvláště pro občasné programátory PC aplikací existuje několik úskalí, kterým by se programátoři vestavných systémů měli vyvarovat:

  • Nadměrné užívání interních flash pamětí počítače
  • Nedostatek paměti způsobený neuvolněním nevyužívané dynamické paměti
  • Vytváření aplikací, ve kterých nejsou ošetřeny všechny možné chyby

Vzhledem k tomu, že vestavné systémy běží často nepřetržitě i několik měsíců, bez dozoru a v odlehlých místech, jedním z hlavních cílů programátorů vestavných systémů je maximální stabilita systému.

Vestavné nebo osobní – rozdíl je hlavně v paměti

Nejvýznamnější problém při psaní kódu pro vestavné počítače je nepochopení úlohy vestavěného počítače. To platí zejména pro již zkušené PC programátory. Zatímco moderní počítače jsou velmi rychlé a PC aplikace mohou volně využívat obrovskou dostupnou paměť, vestavné systémy stále poskytují pouze omezené paměťové zdroje. Programátoři vestavných systémů jsou často překvapeni, když jsou jejich aplikace nestabilní a mnohdy si ani neuvědomí, že může mít problém nějakou spojitost s pamětí.

Zde je jednoduchý příklad. Při psaní softwaru pro PC není neobvyklé zapisovat 100MB datové soubory. Zejména pokud je kapacita disků v řádech GB. Srovnejme to třeba se zápisem 10MB dat na 15MB flash disk u vestavné aplikace. Přesto, že využití pouze 2/3 dostupné paměti se může zdát dostatečně konzervativní k tomu, aby nedocházelo k problémům, opakovaný zápis takového množství dat bude mít za následek vznik tzv. mrtvých bloků na flash disku. Je tomu tak proto, že flash paměťová zařízení mají omezený počet zapisovacích cyklů. Protože u různých oddílů paměťového zařízení nedochází k poškození za stejnou dobu, může takové zařízení zůstat aktivní do doby, než velikost funkční paměti je menší, než velikost potřebná pro spuštění aplikace. Když k tomu dojde, stane se aplikace nestabilní a může být ukončena.

Správný způsob použití vestavěných flash disku je ukládání programových souborů na disk a ukládání dat vytvářených programy na externí CF nebo SD kartu. Externí karta zajišťuje velkou kapacitu úložného prostoru a tím zabraňuje problému s omezeným počtem zapisovacích cyklů. Pokud je z nějakého důvodů nutné použít flash disk pro ukládání dat, doporučuje se použít nanejvýš polovinu volného prostoru flash disku.

Nedostatek paměti

Dalším úkolem je předcházet nedostatku paměti. U vestavných pamětí je potřeba věnovat velkou pozornost využívání paměti. Nedostatek paměti snižuje celkový výkon systému, protože důsledkem boje několika programů o dostupnou paměť je časté stránkování paměti. Může se také stát, že ani tak nedojde k uvolnění dostatečné kapacity paměti pro některou z aplikací a tato aplikace zhavaruje. V extrémním případě může dojít až k pádu samotného operačního systému.

Nedostatek paměti je často důsledkem nesprávného využívání přidělené paměti. Mějte na paměti, že C/C++ programy mohou kontrolovat velikost alokované dynamické paměti. K nedostatku paměti dochází pokud není alokovaná paměť po každém použití opět uvolněna, nebo pokud je přepsán ukazatel na alokovanou paměť.

Problém s dostupnou pamětí se může objevit taky v případě, pokud nejsou uzavřeny nepoužívané souborové handlery nebo deskriptory. Rovněž v komunikačních aplikacích musí být každé TCP nebo sériové spojení spojeno se souborovým deskriptorem, který zabírá určitou část paměti. Pokud takový souborový deskriptor není uzavřen a spojení je opakovaně vytvářeno, požadavky na paměť mohou vést až k jejímu nedostatku.

Aby se předcházelo problémům s dostupnou pamětí, musí vývojáři softwaru věnovat pozornost tomu, jak jejich programy s paměti zacházejí. Navíc musí být aplikace správně strukturovaná.

Správný postup programování znamená návrh směrem shora dolů a implementaci naopak zdola nahoru. Aplikace je rozdělena do vrstev modulů, které jsou co nejvíce od sebe izolovány a poté je každý modul rozdělen do několika funkcí. V průběhu implementační fáze, by měly být nejdříve vytvořeny jednotlivé funkce, před jejich sloučením do kompletních modulů.

V ideálním případě jsou odděleny funkce pro vytvoření, vstup/výstup a ukončení modulu. Následující úsek kódu ukazuje takový příklad.


typedef struct _YYYCONN
{
int fd;
char *packet_data;
int packet_size;
} YYYCONN;

/* the death of a module */
void yyy_close(YYYCONN *con)
{
if (con)
{
if (con->fd > 0) close(con->fd); /* close the file descriptor */
if (con->packet_data) free(con->packet_data); /* free the data buffer */
free(con); /* be sure to structure body */
}
}

/* the birth of a module */
YYYCONN* yyy_open(char *host, int port)
{
int fd;
YYYCONN *con;

con = (YYYCONN *) malloc(sizeof(YYYCONN)); /* memory allocation */
if (con==NULL)
return NULL:
con->fd = make_tcp_client(host, port); /* API call to connect to a TCP server */
If (con->fd < 0)
{
yyy_close(con) ;
return NULL;
}
con->packet_data = (char*) malloc(1024); /* memory allocation */
if (con->packet_data==NULL)
{
yyy_close(con) ;
return NULL;
}
con->packet_size=0;
return con;
}


Funkce yyy_open vytvoří TCP spojovací modul spolu s otevřením souborového deskriptoru. Tělo modulu a jeho člen packet_data jsou alokovány v paměti. Pokud již není modul potřebný, zavolá se funkce yyy_close, která je určená k uzavření souborového deskriptoru a správnému uvolnění alokované paměti. Pro správu více takovýchto propojovacích modulů je potřeba globální oblast, kterou je pole nebo seznam pro dohledání těchto modulů. Užitečné mohou být taky následující funkce pro správu modulů:

  • yyy_connection_add: přidání spojení do globálního seznamu
  • yyy_connection_remove: odstranění spojení z globálního seznamu
  • yyy_connection_lookup: vyhledání vybraného spojení

Ošetření výjimek

Závěrečným tématem tohoto článku je odolnost, o kterou bychom měli usilovat ve všech aplikacích. Každá výjimka, která se v programu může vyskytnout, musí být správně ošetřena. Lehkomyslně vytvořené programy implicitně předpokládají, že budou běžet hladce a podle zadání. Příkladem je následující úsek kódu:


while(1)
{
if (select(fd+1, read_fds, NULL, NULL, NULL) > 0)
{
…;
}
}


Tento příklad předpokládá, že spojení se souborovým deskriptorem fd bude trvalé. Spojení ale může být vynuceně ukončeno druhou stranou, což způsobí, že funkce „select“ ihned vrátí -1. Program pak bude spotřebovávat CPU výkon a nikdy se už nevrátí do normálního stavu.

Závěr

Programátoři, kteří se nevyhnou třem úskalím popisovaným v tomto článku, narazí s velkou pravděpodobností na problémy projevující se nestabilitou dlouhodobě běžících aplikací. Tyto problémy mohou být velmi těžko řešitelné zejména v případech, kdy je projekt vyvíjen pod tlakem, aby byl co nejdřív připraven k předání. Z tohoto důvodu většina vývojářů implementuje navíc WatchDog časovač, který běží souběžně s jejich aplikací. Pokud do jde k nedostatku volné paměti, nebo se logika programu dostane do neočekávaného stavu, nedojde k vynulování WatchDog časovače a provede se restartování systému.

Více informací

Rcore – nástroje pro rychlý vývoj softwaru pro vestavné počítače
Application Partner Community (APC)

 


» Zpět na zpravodaj
 

Kontakt Moxa
box

 

Dozvědět se více
Expansion that's up to you
line
Industrial-grade cellular router
line
Simplify your industrial network connections
box

 

Odkazy na zdrojové články
box

Naší snahou je Vás informovat o zajímavých a cenově výhodných akcích naší firmy. E-maily jsou Vám rozesílány na základě kontaktů s naší firmou v minulosti. V případě, že si nepřejete nadále zasílat tyto informace, prosím, odpovězte na tento email a do předmětu napište NEZASÍLAT ELVAC NEWS. Děkujeme.

Copyright © 2009 Moxa Inc. All rights reserved.