Fundamenteel onderzoek. Berekening van kenmerken van softwarebetrouwbaarheid

Gebruikt binnen in dit geval Betrouwbaarheidsmodellen zijn vooral van belang voor het voorspellen van fouten tijdens de werking en het debuggen van een programma. In dit geval worden de waarden van de modelparameters bepaald tijdens de werking of het debuggen van het programma op basis van gegevens over de momenten van storingen. Het gebrek aan algemene referentiegegevens wordt verklaard door het feit dat elke programmeur een uniek technologisch object is voor het maken van programma's, en elk van zijn programma's een exclusief product is.

Het meest ontwikkelde apparaat voor het beoordelen van is gebaseerd op het Dzelinsky-Moranda-betrouwbaarheidsmodel, dat hieronder zal worden besproken.

Rekenmethode voor het voorspellen van softwarefouten

Het beschouwde model is gebaseerd op de volgende aannames:

    de tijd tot de volgende storing wordt exponentieel verdeeld;

    het uitvalpercentage van een programma is evenredig met het aantal resterende fouten in het programma.

Volgens deze aannames is de waarschijnlijkheid van een storingsvrije werking van programma's als functie van de tijd T i is gelijk aan:

P(t i )=exp(-l i × T i ) , (1)

Waar l i = MET × (N-(i-1)). (2)

Hier MET– evenredigheidscoëfficiënt;

N– het initiële aantal programmafouten.

In uitdrukking (1) de timing T i begint vanaf het moment van de laatste (i-1) programmafout en de waarde l i verandert bij het voorspellen van verschillende mislukkingen.

Waarden C En N in uitdrukking (2) worden bepaald uit experimenteel geregistreerde tijdsintervallen DT i tussen de momenten waarop fouten optreden tijdens het debuggen van programma's. Gebaseerd op de techniek van maximale waarschijnlijkheid, de waarde N wordt verkregen als een oplossing voor de niet-lineaire vergelijking:

Waar NAAR– aantal experimenteel verkregen intervallen tussen storingen.

Echte waarde N verkregen door selectie op basis van het feit dat het een geheel getal is.

Proportionaliteitsfactorwaarde MET krijg zoiets als:

. (4)

Deze techniek werkt voor K³2, d.w.z. het is noodzakelijk om ten minste twee experimenteel verkregen intervallen te hebben tussen de momenten waarop fouten optreden.

Voorbeeld van voorspelling van softwarefouten

Laat tijdsintervallen registreren tijdens het debuggen van programma's DT 1 =10, DT 2 =20, DT 3 =25 tussen programmafouten. Waarden DT kan worden bepaald in tijdseenheden, of kan worden bepaald in het aantal runs van het programma tijdens het testen. Laten we de waarschijnlijkheid bepalen dat het programma werkt P(T 4 )= exp(- l 4 × T 4 ) , d.w.z. afwezigheid van de volgende, vierde storing, vanaf het moment dat de derde storing is geëlimineerd en de gemiddelde tijd T 4 tot de volgende programmafout.

We lossen vergelijking (3) op met betrekking tot N door middel van brute force-methode.

Voor N=4 wij hebben bij K=3

Voor N=5

Biedt de kleinste fout N=4 , vanwaar, in overeenstemming met uitdrukking (4):

.

De kans op een storingsvrije werking bij afwezigheid van de 4e storing is dus

P(T 4 )= exp(-0,02 × T 4 ) , A T 4 =1/ l 4 =50 .

Wij herinneren u eraan dat het aftellen T 4 begint nadat de derde fout optreedt en wordt bepaald in tijdseenheden of in het aantal programma-uitvoeringen.

Voorbeeld berekening van het sterrennetwerk:

Lokaal computernetwerk(LAN) omvat doorgaans een set gebruikerswerkstations, een netwerkbeheerderswerkstation (een van de gebruikersstations kan worden gebruikt), een serverkern (een set hardware serverplatforms met serverprogramma's: bestandsserver, WWW-server, databaseserver, mailserver, etc.), communicatieapparatuur (routers, switches, hubs) en gestructureerd bekabelingssysteem (kabelapparatuur).

De berekening van de LAN-betrouwbaarheid begint met de vorming van het concept van falen van een bepaald netwerk. Om dit te doen analyseren we de beheerfuncties die worden uitgevoerd in de onderneming die dit LAN gebruikt. Die functies worden geselecteerd waarvan de schending onaanvaardbaar is, en de LAN-apparatuur, betrokken bij de uitvoering ervan. Bijvoorbeeld: uiteraard moet het gedurende de werkdag mogelijk zijn om informatie uit de database op te roepen/op te nemen, evenals toegang tot internet.

Voor een reeks van dergelijke functies bepaalt het structurele elektrische schema de LAN-apparatuur, waarvan het falen direct ten minste één van de functies verstoort. gespecificeerde functies, en er wordt een logisch diagram voor het berekenen van de betrouwbaarheid opgesteld.

Hierbij wordt rekening gehouden met het aantal en de werkomstandigheden van reparatie- en restauratieteams. De volgende voorwaarden worden algemeen aanvaard:

Herstel is beperkt – d.w.z. Op elk gegeven moment kan meer dan één defect element niet worden hersteld, omdat er is één reparatieteam;

De gemiddelde hersteltijd van een defect element wordt vastgesteld op basis van toegestane onderbrekingen in de werking van het LAN, of op basis van technische mogelijkheden levering en opname in het werk van dit element.

In het kader van de bovenstaande berekeningsaanpak kan het bin de regel worden teruggebracht tot een serie-parallel circuit.

Laten we als criterium voor LAN-storingen het falen van apparatuur in de netwerkkern stellen: servers, schakelaars of kabelapparatuur.

Wij zijn van mening dat het uitvallen van gebruikerswerkstations niet leidt tot het uitvallen van het LAN, en aangezien het gelijktijdig uitvallen van alle werkstations een onwaarschijnlijke gebeurtenis is, blijft het netwerk functioneren in het geval van individuele uitval van werkstations.

Betrouwbaarheid van een sterrennetwerk.

Storingen hebben geen invloed op het falen van het hele netwerk. De betrouwbaarheid van het LAN wordt bepaald door de betrouwbaarheid van het centrale knooppunt.

Laten we aannemen dat het beschouwde lokale netwerk één server, twee switches en veertien kabelfragmenten omvat die tot de netwerkkern behoren. De intensiteit van mislukkingen en restauraties daarvoor wordt hieronder gegeven, zoals voorheen KG = 1 l/m.

De herstelintensiteitswaarden zijn maximaal voor kabels, waarvan de vervanging wordt uitgevoerd met behulp van reservekabels, en minimaal voor schakelaars, waarvan de reparatie wordt uitgevoerd door gespecialiseerde bedrijven.

De berekening van de kenmerken van subsystemen van servers, schakelaars en kabels wordt uitgevoerd met behulp van uitdrukkingen voor de seriële verbinding van elementen.

Serversubsysteem:

lC =2*l 1 =2*10 -5 ; K GS =1-2*10 -4 ;m C = =0,1 1/u.

Schakel subsysteem:

lk =2*10-5; K Gk =1-2*10 -3 ;m k =
1/u.

Kabelsubsysteem:

l l =14*10 -6; K Gl = 1-14*10 -6;ml = 1 1/u.

Voor het hele netwerk:

ls =6,5*10-5; KGs =1-2,4*10-3;ms =0,027 1/uur.

Berekeningsresultaat:

T = 15 duizend uur, KG = 0,998, TV » 37 uur.

Berekening van LAN-kosten:

14 netwerkkaarten: 1500 wrijven.

Kabel 1 km: 2000 wrijven.

Connectoren: 200 wrijven.

Server: 50 duizend. wrijven.

Totaal: 2.53.700 ton.

In de informatica en projectmanagement bestaan ​​momenteel geen modellen die softwarefouten nauwkeurig kunnen voorspellen. Er zijn verschillende theorieën en modellen, maar geen daarvan zal u gegarandeerde resultaten opleveren. Zie cyclische complexiteit als een voorbeeld waarbij er onenigheid bestaat over de maatregel correlatie met defecten.

In jouw geval probeer je dat te doen statistische analyse zonder dat er voldoende aandacht is besteed aan het testontwerp, de gecontroleerde variabelen of de nulhypothese. Je misleidt ook causaliteit en correlatie. Zelfs als je een goed ontworpen test hebt met adequate controles, en zelfs als je de nulhypothese kunt verwerpen, zul je het uiterst moeilijk hebben om een ​​van deze ontwerpen als direct bewijs van oorzaak en gevolg te gebruiken.

Bekijk uw projecten

Het beste gebruik van uw tijd is om Project 2 nader te bekijken om te begrijpen waarom u zo'n hoog defectpercentage heeft. Kijk naar uw processen, vorm een ​​hypothese en probeer vervolgens uw processen aan te passen om defecten te verminderen.

Een goede projectmanager zal geen tijd verspillen aan het creëren van een ‘universele theorie van alles’, gebaseerd op extrapolatie van twee projecten. In plaats daarvan besteedde een ervaren projectmanager hier tijd aan bevestigen Project 2 om uw kansen op succes te vergroten, of door de faalkans van de portefeuillemanager te communiceren, zodat u deze kunt accepteren strategische beslissing of het project moet worden beëindigd als kosten- of kwaliteitscontrolemaatregel.

Stel je voor dat je de waarde van een auto bepaalt op basis van hoe vaak deze is gewassen.

Ontwikkelaars die het bestand hebben verlaten

Ik heb geen idee wat je uit deze statistiek probeert af te leiden. Het lijkt erop dat je probeert de populariteit van fastfood te voorspellen op basis van het aantal kwartjes dat ze als wisselgeld hebben gegeven.

De regels over bugs is het testen vanaf de vroege ontwikkelingsfasen, en het handhaven van een verhouding van 1:1 of 2:1 tussen programmeurs en testers. Dan jij kunt Je kunt er gerust van uitgaan dat de fase van het testen en debuggen net zo lang zal duren als de oorspronkelijk geschatte tijd voor het schrijven van de code.

Hoe later je begint met testen, hoe minder testers je hebt meer fouten zullen leven en groeien in de software, en de debugging-fase zal langer duren. Vervolgens kunt u uw test-/foutopsporingstijd verdubbelen of verdrievoudigen.

    Omdat het repareren van code die onlangs (vandaag) is geschreven, gemakkelijker is dan het repareren van code die enige tijd geleden (dagen, weken of maanden) is geschreven. Code die niet vers in het geheugen van de programmeur zit, moet opnieuw worden gelezen en begrepen.

    Meer nieuwe code is vaak gebaseerd op eerdere code, dus als er eerder een bug was, kan deze volledig crashen en problemen veroorzaken.

Eindelijk: Aantal fouten is nergens een goede indicator voor, tenzij je de ernst, het belang en de impact ervan in ogenschouw neemt. Zowel typfout als intermitterend systeem zijn belangrijke fouten. Bij het ene probleem duurt het een paar minuten om het probleem op te lossen, bij het andere kan het erg lang duren, omdat periodieke storingen bijna onmogelijk opnieuw te creëren en te vinden zijn.

1

De bronnen van fouten in software zijn specialisten - specifieke mensen met hun individuele kenmerken, kwalificaties, talent en ervaring.

In de meeste gevallen kan de stroom softwarefouten worden beschreven door een inhomogeen Poisson-proces. Dit betekent dat softwarefouten op statistisch onafhankelijke tijdstippen optreden, dat de bedrijfstijd een exponentiële verdeling volgt en dat de intensiteit van de fouten in de loop van de tijd varieert. Meestal wordt gebruik gemaakt van een afnemende intensiteit van de foutmanifestatie. Dat wil zeggen dat fouten, eenmaal geïdentificeerd, effectief worden geëlimineerd zonder nieuwe fouten te introduceren.

Wat betreft betrouwbaarheid software Een fout is een fout of vervorming van de code van een programma, die er onbedoeld in wordt geïntroduceerd tijdens het ontwikkelingsproces, en die tijdens de werking van dit programma een storing of een afname van de operationele efficiëntie kan veroorzaken. In het algemene geval wordt onder een storing verstaan ​​een gebeurtenis die bestaat uit een verstoring van de functionaliteit van een object. In dit geval faalcriteria, als teken of reeks tekenen van een overtreding werkende staat software moet worden bepaald op basis van het doel ervan in de regelgevende en technische documentatie.

Over het algemeen kan een softwarefout worden gedefinieerd als:

  • stopzetting van het functioneren van het programma (vervorming van het normale verloop van de uitvoering ervan, cyclisch) gedurende een tijd die een bepaalde drempel overschrijdt;
  • stopzetting van het functioneren van het programma (vervorming van het normale verloop van de uitvoering ervan, cyclisch) gedurende een tijd die een bepaalde drempel niet overschrijdt, maar met verlies van alle of een deel van de verwerkte gegevens;
  • beëindiging van de werking van het programma (vervorming van het normale verloop van de uitvoering ervan, cyclus) waardoor een herstart nodig is van de computer waarop de software werkt.

Van deze definitie softwarefout Hieruit volgt dat fouten verschillende effecten kunnen hebben op de betrouwbaarheid van software en dat de ernst van de fout kwantitatief of kwantitatief kan worden bepaald kwalitatieve beoordeling gevolgen van deze fout. In dit geval zal de ernstcategorie van de gevolgen van een fout de classificatiegroep van fouten zijn op basis van de ernst van hun gevolgen. Hieronder vindt u mogelijke categorieën van ernst van softwarefouten: algemeen gebruik in overeenstemming met GOST 51901.12 - 2007 “Risicobeheer. Methode voor het analyseren van de soorten en gevolgen van storingen.”

Beschrijving van de gevolgen van de fout

Kritisch

het optreden van een fout met een grote waarschijnlijkheid brengt de beëindiging van het functioneren van de software met zich mee (het falen ervan)

Essentieel

het optreden van een fout leidt tot een afname van de efficiëntie van de software en kan ervoor zorgen dat de software niet meer functioneert (storing)

Irrelevant

het optreden van een fout kan leiden tot een afname van de efficiëntie van de software en leidt vrijwel niet tot een storing daarin (de kans dat er een storing optreedt is zeer laag)

Als indicator voor de ernst van de fout, zodat u deze kunt geven kwantificering de ernst van de gevolgen van een fout, kunt u gebruik maken van de voorwaardelijke kans op softwarefalen wanneer er een fout optreedt. Een beoordeling van de ernst van een fout als een voorwaardelijke waarschijnlijkheid van een storing kan worden gemaakt in overeenstemming met GOST 28195 - 89 “Beoordeling van de kwaliteit van software. Algemene bepalingen", met behulp van statistieken en evaluatie-elementen die de duurzaamheid van software karakteriseren. In dit geval moet de beoordeling voor elke fout afzonderlijk worden gemaakt, en niet voor de gehele software.

Bibliografische link

Drobotun E.B. KRITICITEIT VAN FOUTEN IN SOFTWARE EN ANALYSE VAN HUN GEVOLGEN // Fundamenteel onderzoek. – 2009. – Nr. 4. – Blz. 73-74;
URL: http://fundamental-research.ru/ru/article/view?id=4467 (toegangsdatum: 04/06/2019). Wij brengen tijdschriften onder uw aandacht die zijn uitgegeven door de uitgeverij "Academie voor Natuurwetenschappen"

Als we aannemen dat er enkele fouten in de software zullen voorkomen, dan is de beste strategie (na foutpreventie) het opnemen van foutdetectietools in de software zelf.

De meeste methoden zijn erop gericht om storingen zo snel mogelijk op te sporen. Onmiddellijke detectie heeft twee voordelen: het kan de impact van de fout minimaliseren en de daaropvolgende problemen voor de persoon die er informatie over moet opvragen, vinden en corrigeren.

(SITELINK-S405) Foutdetectiemaatregelen (/SITELINK) kunnen in twee subgroepen worden verdeeld: passief probeert symptomen van een fout te detecteren tijdens de “normale” werking van de software en actief pogingen softwaresysteem Onderzoek periodiek uw toestand op tekenen van fouten.

Passieve detectie. Foutdetectiemaatregelen kunnen op verschillende structurele niveaus van een softwaresysteem worden genomen. Hier zullen we het niveau van subsystemen of componenten bekijken, d.w.z. We zullen geïnteresseerd zijn in maatregelen om foutsymptomen op te sporen die optreden tijdens de overgang van de ene component naar de andere, maar ook binnen de component. Dit alles geldt uiteraard ook voor individuele modules binnen een component.

Bij het ontwikkelen van deze maatregelen zullen wij ons baseren op het volgende.

1. Wederzijds wantrouwen. Elke component moet ervan uitgaan dat alle andere fouten bevatten. Wanneer het bepaalde gegevens ontvangt van een ander onderdeel of van een bron buiten het systeem, moet het ervan uitgaan dat de gegevens mogelijk onjuist zijn en proberen daarin fouten te vinden.

2. Onmiddellijke detectie. Fouten moeten zo vroeg mogelijk worden ontdekt. Dit beperkt niet alleen de schade die ze veroorzaken, maar maakt het debuggen ook veel eenvoudiger.

3. Ontslag. Alle foutdetectietools zijn afhankelijk van een of andere vorm van redundantie (expliciet of impliciet).

Bij het ontwikkelen van (SITELINK-S405)foutdetectiemaatregelen(/SITELINK) is het belangrijk om een ​​consistente, systeembrede strategie te hanteren. Acties die worden ondernomen na het ontdekken van een fout in de software moeten uniform zijn voor alle componenten van het systeem. Dit roept de vraag op welke actie moet worden ondernomen als er een fout wordt ontdekt. De beste oplossing- beëindig onmiddellijk de uitvoering van het programma of (in het geval dat besturingssysteem) zet de centrale processor in een standby-status. Vanuit het oogpunt van het bieden van de persoon die het programma debugt, zoals een systeemprogrammeur, van de meest gunstige omstandigheden voor het diagnosticeren van fouten, lijkt onmiddellijke beëindiging de beste strategie. Natuurlijk is een dergelijke strategie in veel systemen ongepast (het kan bijvoorbeeld blijken dat het onmogelijk is om het systeem te pauzeren). Gebruik in dit geval de methode foutenregistratie. Beschrijving van foutsymptomen en " momentopname» systeemstatussen worden opgeslagen in een extern bestand, waarna het systeem kan blijven functioneren. Dit bestand zal later worden beoordeeld door het onderhoudspersoneel.

Waar mogelijk is het beter om de uitvoering van het programma te pauzeren in plaats van fouten te loggen (of ervoor te zorgen dat extra kans werking van het systeem in een van deze modi). Ik zal het verschil tussen deze methoden illustreren aan de hand van manieren om de oorzaken van het incidentele knarsende geluid in uw auto te identificeren. Zit de monteur op de achterbank, dan kan hij de staat van de auto onderzoeken op het moment dat het knarsende geluid optreedt. Als u een foutregistratiemethode kiest, wordt de diagnostische taak moeilijker.

Actieve foutdetectie. Niet alle fouten kunnen met passieve methoden worden gedetecteerd, aangezien deze methoden een fout alleen detecteren als de symptomen ervan op passende wijze worden geverifieerd. Als u speciaal ontwerpt, kunt u extra controles uitvoeren software Voor actief zoeken tekenen van fouten in het systeem. Dergelijke middelen worden genoemd middel van actieve foutdetectie.

Actieve foutdetectietools worden meestal gecombineerd in diagnostische monitor: een parallel proces dat periodiek de status van het systeem analyseert om een ​​fout te detecteren. Grote softwaresystemen die hulpbronnen beheren, bevatten vaak fouten die resulteren in verspilling van hulpbronnen. lange tijd. Het geheugenbeheer van het besturingssysteem verhuurt bijvoorbeeld geheugenblokken aan gebruikersprogramma's en andere delen van het besturingssysteem. Een fout in deze “andere delen” van het systeem kan soms leiden tot een onjuiste werking van de geheugenbeheereenheid, die verantwoordelijk is voor het retourneren van eerder geleasd geheugen, wat een langzame degeneratie van het systeem veroorzaakt.

De diagnostische monitor kan worden geïmplementeerd als een periodieke taak (deze wordt bijvoorbeeld elk uur gepland) of als een taak met lage prioriteit die wordt uitgevoerd wanneer het systeem in de stand-bymodus komt. Net als voorheen zijn de specifieke controles die de monitor uitvoert afhankelijk van de specifieke kenmerken van het systeem, maar sommige ideeën zullen duidelijk worden uit de voorbeelden. De monitor kan het hoofdgeheugen onderzoeken om geheugenblokken te detecteren die niet zijn toegewezen aan een actieve taak en die niet zijn opgenomen in de systeemlijst vrij geheugen. Het kan ook controleren op ongebruikelijke situaties: een proces was bijvoorbeeld niet gepland om gedurende een redelijke tijd te worden uitgevoerd. De monitor kan zoeken naar “verloren” berichten binnen het systeem of naar ongebruikelijke I/O-bewerkingen voor een lange tijd onvoltooid blijven, gebieden van schijfgeheugen die niet zijn gemarkeerd als toegewezen en niet zijn opgenomen in de lijst met vrij geheugen, evenals verschillende soorten eigenaardigheden in gegevensbestanden.

Soms is het wenselijk dat de monitor in noodsituaties systeemdiagnostische tests uitvoert. Het kan bepaalde veroorzaken systeem functies, waarbij het resultaat wordt vergeleken met een vooraf bepaald resultaat en wordt gecontroleerd of de uitvoeringstijd redelijk is. De monitor kan het systeem ook periodiek ‘lege’ of ‘lichte’ taken presenteren om ervoor te zorgen dat het systeem op zijn minst op de meest primitieve manier functioneert.

Invoering
Dit werk is gewijd aan het beschrijven van methoden voor het detecteren en elimineren van fouten die de kwaliteit van ingebedde systeemsoftware aanzienlijk kunnen verbeteren en materiaal en tijd kunnen besparen die worden besteed aan het debuggen van systemen. De onderzochte methoden kunnen zonder veel moeite worden gebruikt bij het ontwikkelen van een grote verscheidenheid aan softwareprojecten voor ingebedde systemen, en de opgebouwde ervaring behoudt volledig zijn waarde bij het implementeren van andere projecten en doeltechnologieën. Bovendien maken ze het mogelijk om het gemak van onderhoud, wijziging en overdracht van gemaakte programma's naar nieuwe soorten apparaten te garanderen. In een notendop stellen de technieken die we bespreken u niet alleen in staat uw bestaande embedded applicaties en ontwikkelingsprocessen te verbeteren, maar zorgen ze er ook voor dat naarmate nieuwe embedded apparaten zich verspreiden, u al over de expertise beschikt die nodig is om op tijd goed presterende applicaties voor deze technologieën te ontwikkelen. en binnen budget.
Het is geen geheim dat het debuggen van programma's voor embedded systemen uiterst moeilijk is. Debuggen op zichzelf is verre van een toevluchtsoord, maar het debuggen van software voor embedded systemen vereist hetzelfde speciale eisen. Allereerst is het erg lastig om de benodigde informatie uit embedded systemen te halen. Het foutopsporingsproces is meestal gebaseerd op de informatie die door de applicatie wordt geproduceerd en de bijbehorende informatie feedback van de kant van de programmeur, en embedded systeemprogramma's hebben niet de mogelijkheid om schermafbeeldingen af ​​te drukken die ontwikkelaars van andere soorten software kunnen gebruiken.
We moeten op de een of andere manier uit deze onaangename situatie komen. Een van mogelijke oplossingen het verbinden van speciale apparatuur met een module, een set hardware waarvoor de software waarvoor fouten worden opgespoord, is geschreven. Deze speciale hardware geeft de ontwikkelaar de mogelijkheid om te zien wat er met zijn software gebeurt. Met zogenaamde geheugenmonitors kunt u bijvoorbeeld informatie in afzonderlijke geheugengebieden opslaan, de geheugeninhoud in de monitor lezen en de geheugeninhoud van de monitor gebruiken om de toestand van het systeem te analyseren op het moment van de crash. Bovendien kunnen ingebedde systemen worden gedebugd met behulp van simulatiesystemen software-omgevingen, waarin de programma's waarvoor fouten worden opgespoord, op dezelfde manier worden uitgevoerd als waarin ze zullen worden uitgevoerd doelsysteem.
Simulatiesystemen hebben veel voordelen. Meestal bevatten ze debuggers en printtools, maar modelleringssystemen zijn slechts simulatoren. Het programma waarvan fouten worden opgespoord, kan met succes worden uitgevoerd in het simulatiesysteem en volledig onbruikbaar zijn echte omstandigheden. Modelleringssystemen zijn dus slechts een gedeeltelijke oplossing. Softwarefouten kunnen het modelleringssysteem omzeilen en opduiken echte uitrusting.
Dit is waar het verborgen is voornaamste probleem: Zoals weergegeven in afb. 1 is het corrigeren van fouten die niet in de testfase, maar tijdens het gebruik worden geïdentificeerd, veel duurder. Als er een bug wordt gevonden in een programma voor niet-ingebedde systemen, kun je deze vrijgeven bijgewerkte versie programma's met patches zijn de kosten van dergelijke updates doorgaans relatief laag. Als er een fout wordt gevonden in een ingebed systeem, is het noodzakelijk om de apparaten zelf met dit systeem terug te sturen en aan te passen om deze te corrigeren. De kosten van een dergelijk rendement kunnen astronomische waarden bereiken en de ondergang van bedrijven veroorzaken.

Rijst. 1. Kosten voor het elimineren van fouten in embedded systemen

Naar mijn mening verdubbelen de tijd en kosten voor het identificeren en herstellen van fouten voor ingebedde systemen ongeveer (vanwege de hierboven beschreven problemen). In het licht van zulke ongelooflijke kosten is elke methode die fouten überhaupt voorkomt, van onschatbare waarde. Gelukkig voor embedded-ontwikkelaars kunnen enkele nieuwe technologieën worden gebruikt om fouten te voorkomen software ontwikkeling. De twee meest aanbevolen zijn programmeerstandaarden en unit-testen.
Het is waar dat beide methoden tegenwoordig niet zozeer worden gebruikt als wel verheerlijkt. Bijna elke softwareontwikkelaar is het eens met de hoge waarde ervan, maar slechts enkelen gebruiken ze. Deze inconsistentie wordt in de meeste gevallen verklaard door twee redenen. Allereerst vinden veel mensen het volgen van programmeerstandaarden en het testen van eenheden behoorlijk vervelend. Als je bedenkt hoeveel tijd en moeite deze benaderingen in de toekomst kunnen besparen, zouden ontwikkelaars er goed aan doen een beetje geduld te hebben en enorme hoeveelheden werk (en mogelijke weigering van het project) vervolgens.
Ontwikkelaars van real-time systemen hebben het zelfs nog moeilijker, omdat ze ook te maken krijgen met de problemen die gepaard gaan met het respecteren van verschillende timingafhankelijkheden. Aan het einde van het artikel zullen we kijken naar de moeilijkheden die we tegenkomen bij het debuggen van real-time systemen en enkele debugtechnieken introduceren die zijn ontworpen om deze moeilijkheden te overwinnen en die ook kunnen worden gebruikt bij de ontwikkeling van welke software dan ook.
Methoden voor het debuggen van programma's
Het debuggen van programma's bestaat uit het controleren van de juiste werking van het programma en de hardware. Een programma dat niet bevat syntaxisfouten het kan echter logische fouten bevatten die voorkomen dat het programma de beoogde functies uitvoert. Logische fouten kunnen verband houden met het programma-algoritme of met een misverstand over de werking van de apparatuur die op de microcontrollerpoorten is aangesloten.
Met de debugger die in de geïntegreerde programmeeromgeving is ingebouwd, kunt u fouten in die delen van de programmacode debuggen die niet afhankelijk zijn van de werking van apparatuur die geen deel uitmaakt van de microcontrollerchip. Dit verwijst doorgaans naar de evaluatie van wiskundige uitdrukkingen of de conversie van datarepresentatieformaten.
Er worden gewoonlijk drie methoden gebruikt om programma's te debuggen: Stap voor stap debuggen programma's met toegang tot subroutines; Stapsgewijze debuggen van programma's met uitvoering van een subroutine als één enkele instructie; Voer het programma uit tot een breekpunt.
Het stapsgewijs debuggen van programma's bestaat uit het uitvoeren van één programma-instructie en het vervolgens monitoren van de variabelen die door deze instructie zouden moeten worden beïnvloed.
Als het programma al subprogramma's heeft gedebugd, kan het subprogramma worden beschouwd als één programma-instructie en de tweede methode voor het debuggen van programma's gebruiken.
Als er een voldoende groot gedeelte van het programma in het programma aanwezig is dat al eerder is gedebugd, dan kan het worden uitgevoerd zonder controle over de variabelen waarop het van invloed is. Door gebruik te maken van breekpunten kunt u een reeds gedebugd deel van het programma overslaan. Breekpunten worden ingesteld op plaatsen waar het nodig is om de inhoud van variabelen te controleren of eenvoudigweg te controleren of de controle wordt overgedragen aan deze exploitant.
Bijna alle debuggers ondersteunen deze eigenschap (evenals programma-uitvoering tot aan de cursor en het verlaten van de subroutine). Vervolgens gaat het debuggen van het programma verder stap voor stap modus met controle van lokale en globale variabelen, evenals interne registers van de microcontroller en spanningen op de pinnen van deze microschakeling. Volg de programmeerstandaarden!

De beste manier om de softwarekwaliteit te verbeteren is door fouten tijdens het invoerproces te voorkomen brontekst.
De eerste stap op weg naar het voorkomen van fouten is het besef dat fouten inderdaad te voorkomen zijn. De grootste barrière voor foutbeheersing is de algemene overtuiging dat fouten onvermijdelijk zijn. Dit is een misvatting! Fouten verschijnen niet vanzelf; ze worden door de ontwikkelaar in de tekst geïntroduceerd. Fouten maken is menselijk, dus zelfs het meest beste programmeurs maken van tijd tot tijd fouten als ze de kans krijgen. Om het aantal fouten te verminderen, is het daarom noodzakelijk om de kans op optreden ervan te verkleinen. Een van de beste manieren hier wordt vastgehouden aan programmeerstandaarden, waardoor een vruchtbare voedingsbodem voor fouten in de eerste fasen wordt geëlimineerd.
Programmeerstandaarden zijn taalspecifieke ‘regels’ die, indien gevolgd, de kans op het introduceren van fouten tijdens de ontwikkeling van applicaties aanzienlijk verkleinen. Programmeerstandaarden moeten worden gevolgd in de fase van het schrijven van programma's, voordat ze worden overgedragen naar doelplatforms, en standaardisatie moet voor alle talen bestaan. Omdat de meeste ontwikkelaars van embedded systemen de C-taal gebruiken, zullen we meer aandacht besteden aan de C-programmeerstandaarden, hoewel dezelfde standaarden bestaan ​​voor andere talen, waaronder C++ en Java.
Normaal gesproken vallen programmeerstandaarden in twee categorieën:
industriële programmeerstandaarden: regels die door alle programmeurs worden geaccepteerd gegeven taal(bijvoorbeeld het verbieden van toegang tot een lus, niet via de header ervan).
specifieke programmeerstandaarden: regels die worden gevolgd door een specifieke groep ontwikkelaars, binnen een specifiek project of zelfs door een enkele programmeur. Er zijn drie soorten specifieke standaarden die een ontwikkelaar van embedded softwaresystemen kan gebruiken: interne standaarden, persoonlijke standaarden en door het doelplatform gedefinieerde standaarden.
Interne programmeerstandaarden zijn regels die specifiek zijn voor uw organisatie of ontwikkelteam. Naamgevingsregels die uniek zijn voor een organisatie zijn dus een voorbeeld van interne programmeerstandaarden.
Persoonlijke normen zijn regels die u zullen helpen uw meest te vermijden veelvoorkomende fouten. Elke keer dat er een fout optreedt, moet de programmeur de reden voor het optreden ervan analyseren en zijn eigen regel ontwikkelen om herhaling ervan te voorkomen. Als u in een voorwaardelijke verklaring bijvoorbeeld vaak een toewijzingsteken schrijft in plaats van een gelijkheidscontroleteken (d.w.z. "als (a=b)" in plaats van "als (a= =b)"), dan moet u voor uzelf een volgende standaard: "Pas op voor het gebruik van een toewijzingsteken in een voorwaardelijke verklaring."
De normen die door het doelplatform zijn gedefinieerd, zijn de regels die, indien geschonden, tot bepaalde problemen op dat platform kunnen leiden. Dergelijke standaarden kunnen bijvoorbeeld betrekking hebben op geheugengebruik of limieten voor variabele grootte die door het doelplatform worden opgelegd.
Om beter te begrijpen wat programmeerstandaarden zijn en hoe ze werken, laten we er kennis mee maken op specifieke voorbeelden. Laten we eens overwegen volgende invoer in C-taal:
{
.
.
.
}
Hier wordt de grootte van een eendimensionale array aangegeven in de functieargumentlijst. Dit is een gevaarlijke constructie omdat in C het array-argument wordt doorgegeven als een verwijzing naar het eerste element, en verschillende aanroepen van de functie arrays van verschillende grootten onder de feitelijke argumenten kunnen bevatten. Als je zo'n constructie hebt gemaakt, verwacht je een buffer te gebruiken vaste maat voor 80 elementen, aangezien het juist deze buffer is die aan de functie wordt doorgegeven, en dit kan leiden tot geheugenvernietiging. Als de auteur van deze verklaring de programmeerstandaard "verklaar de grootte van een eendimensionale array niet als een functieargument" had gevolgd (ontleend aan een set C-programmeerstandaarden van een van de toonaangevende telecommunicatiebedrijven), dan zou deze tekst er zo uitzagen en problemen met geheugencorruptie zouden zijn vermeden:
char *subtekenreeks ( tekenreeks, int start_pos, int lengte)
{
.
.
.
}
Met programmeerstandaarden kunt u ook problemen vermijden die mogelijk pas optreden als de code naar een ander platform wordt geporteerd. Het volgende stukje code werkt bijvoorbeeld prima op sommige platforms, maar genereert fouten wanneer het naar andere platforms wordt geporteerd:
#erbij betrekken
ongeldige test(char c) (
als (een<= c && c <= z) { // Неправильно
}
if(islager(c)) (// Correct
}
terwijl (A<= c && c <= Z) { // Неправильно
}
while (isupper(c)) ( // Correct
}
}
Portatieproblemen kunnen verband houden met symbolische tests die geen gebruik maken van de ctype.h-functies (isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper). De ctype.h-functies voor tekencontrole en het omzetten van hoofdletters naar kleine letters en vice versa werken met een grote verscheidenheid aan tekensets, zijn doorgaans zeer efficiënt en zorgen voor internationale toepasbaarheid van het softwareproduct.
De beste manier om deze en andere programmeerstandaarden te implementeren is om ze automatisch toe te passen als onderdeel van een programmeertechnologie, samen met een reeks gerichte industriestandaarden en mechanismen voor het creëren en onderhouden van systeemspecifieke programmeerstandaarden. Wanneer u een dergelijke technologie kiest, moet u eerst antwoorden vinden op vragen, waaronder de volgende:
Geldt dit voor dit programma en/of deze compiler?
Bevat het een reeks industriële programmeerstandaarden?
Kunt u hiermee aangepaste programmeerstandaarden creëren en onderhouden (inclusief de standaarden die door het doelplatform zijn gedefinieerd)?
Is het eenvoudig om rapporten te structureren op basis van uw team- en projectprioriteiten?
Hoe gemakkelijk integreert het in uw bestaande ontwikkelingsproces?
Eenheid testen

Wanneer ontwikkelaars horen over unit-testen, beschouwen ze dit vaak als synoniem met unit-testen. Met andere woorden: bij het testen van een enkele module of subroutine van een grotere software-eenheid denken ontwikkelaars dat ze unit-tests uitvoeren. Natuurlijk is unit-testen erg belangrijk en zou zeker gedaan moeten worden, maar het is niet de methode waar ik me op zou willen concentreren. Als ik het heb over ‘unit testen’, bedoel ik testen op een nog lager niveau: het testen van de kleinst mogelijke programma-eenheden waaruit een applicatieprogramma bestaat, terwijl deze zich in het geval van C nog in de hostomgeving (het hostsysteem) bevinden. be functies , die onmiddellijk worden gecontroleerd nadat ze zijn gecompileerd.
Unit-testen verbeteren de softwarekwaliteit en de efficiëntie van het ontwikkelingsproces aanzienlijk. Bij testen op objectniveau bent u veel dichter bij deze techniek en heeft u een veel groter vermogen om invoersets samen te stellen die fouten met 100% dekking detecteren (Afbeelding 2). Door een codeblok onmiddellijk te testen nadat het is geschreven, vermijdt u bovendien dat u door lagen van fouten heen moet waden om het enige originele blok te vinden en te repareren. In dit geval elimineert u het onmiddellijk en is het hele probleem opgelost . Dit versnelt en vergemakkelijkt het ontwikkelingsproces aanzienlijk, omdat aanzienlijk minder materiaal en tijd worden besteed aan het opsporen en elimineren van fouten.

Rijst. 2. Gemakkelijk fouten vinden tijdens het testen van eenheden

Unit-testen kunnen worden onderverdeeld in ten minste twee afzonderlijke processen. De eerste is black box-testen, oftewel het proces van het identificeren van functionele problemen. Op blokniveau bestaat black box-testen uit het verifiëren van functionele kenmerken door te bepalen in welke mate de open interface-parameters van een functie voldoen aan de specificatie ervan; een dergelijke controle wordt uitgevoerd zonder rekening te houden met de implementatiemethoden. Het resultaat van black box-testen op blokniveau is het vertrouwen dat een bepaalde functie zich precies gedraagt ​​zoals gedefinieerd en dat een kleine functionele fout niet zal leiden tot een lawine van hardnekkige problemen.

Rijst. 3. Black box-testen

Het tweede proces wordt white box-testen genoemd en is ontworpen om ontwerpfouten te identificeren. Op het niveau van individuele blokken wordt gecontroleerd of het hele programma crasht bij het doorgeven van onverwachte parameters aan de functie. Dit type testen moet worden uitgevoerd door een specialist die volledig begrijpt hoe de geteste functie wordt geïmplementeerd. Na zo'n controle kunt u er zeker van zijn dat er geen fouten zijn die tot de ineenstorting van het systeem leiden en dat de functie onder alle omstandigheden stabiel zal werken (dat wil zeggen, voorspelbare resultaten zal produceren, zelfs als er onverwachte invoerparameters worden ingevoerd).

Rijst. 4. Whitebox-testen

Beide bovenstaande processen kunnen dienen als basis voor een derde, regressietest. Door black-box- en white-box-testgevallen op te slaan, kunt u deze gebruiken voor regressietests op blokniveau en de integriteit van uw code controleren terwijl u deze wijzigt. Het concept van regressietesten op dit niveau is een nieuwe en originele benadering. Wanneer u regressietests uitvoert op blokniveau, kunt u vaststellen of er nieuwe problemen zijn opgetreden zodra u de tekst wijzigt en deze direct nadat ze zich hebben voorgedaan, herstellen, waardoor wordt voorkomen dat de fout zich naar hogere niveaus verspreidt.
Het grootste probleem met unit-testen is dat tenzij geautomatiseerde unit-testtechnieken worden gebruikt, het moeilijk, vervelend en tijdrovend is. Laten we even kort kijken naar de redenen waarom het moeilijk (zo niet onmogelijk) is om handmatige unit-tests in de huidige ontwikkelingsprocessen op te nemen.
De eerste fase van het testen van ingebedde systeemsoftware bestaat uit het creëren van een omgeving waarin de gewenste functie kan worden uitgevoerd en getest op het hostsysteem. Hiervoor zijn de volgende twee stappen nodig:
ontwikkeling van programmatekst die de functie zal uitvoeren,
het schrijven van dummymodules die resultaten retourneren in plaats van externe bronnen waartoe de functie toegang heeft en die momenteel ontbreken of niet toegankelijk zijn.
De tweede fase is de ontwikkeling van testkits. Om het ontwerp en de functionele kenmerken van een functie volledig af te dekken, is het noodzakelijk om testsets van twee typen te maken: voor een “black box” en voor een “white box”.
De basis voor het ontwikkelen van black box-testgevallen zou de functiespecificatie moeten zijn. In het bijzonder moet voor elke vermelding in de specificatie minimaal één testgeval worden aangemaakt, en het is wenselijk dat deze sets rekening houden met de in de specificatie gespecificeerde randvoorwaarden. Het is niet voldoende om te controleren of sommige inputs de verwachte resultaten opleveren; het is noodzakelijk om het bereik van de relaties tussen inputs en outputs te bepalen, waardoor we een conclusie kunnen trekken over de juiste implementatie van de gespecificeerde functionele kenmerken, en vervolgens testsets kunnen maken die dit bereik volledig bestrijken. U kunt ook testen die buiten de specificaties vallen en foutieve omstandigheden testen.
Het doel van white box-testgevallen is om alle verborgen gebreken te detecteren door de functie uitgebreid te testen met een verscheidenheid aan invoerparameters. Deze kits moeten de volgende mogelijkheden hebben:
de hoogst mogelijke (100%) dekking van een functie bieden: zoals eerder vermeld is dit niveau van dekking op blokniveau mogelijk omdat het veel eenvoudiger is om testsuites te maken voor elk kenmerk van een functie buiten de applicatie (100% dekking is niet in alle gevallen mogelijk, maar het is wel een doel om naar te streven);
omstandigheden voor functiestoring identificeren.
Opgemerkt moet worden dat het zelf maken van dergelijke sets, zonder de technologieën voor hun constructie te kennen, een ongelooflijk moeilijke taak is. Om effectieve white-box-testgevallen te creëren, moet u eerst een volledig inzicht krijgen in de interne structuur van de functie, testgevallen schrijven die een maximale dekking van de functie bieden, en de set inputs vinden die ervoor zorgen dat de functie mislukt. Het verkrijgen van de dekking die vereist is voor high-performance white-box-testen is alleen mogelijk door een aanzienlijk aantal functiepaden te onderzoeken. In een typisch programma van 10.000 uitspraken zijn er bijvoorbeeld ongeveer honderd miljoen mogelijke traversal-paden; Het is niet mogelijk om handmatig testgevallen aan te maken om al deze paden te testen.
Na het maken van testgevallen is het noodzakelijk om de functie volledig te testen en de resultaten te analyseren om de oorzaken van fouten, crashes en zwakke punten te identificeren. U moet een manier hebben om alle testgevallen te doorlopen en snel te bepalen welke problemen veroorzaken. Het is ook noodzakelijk om over een dekkingsmeetinstrument te beschikken om de volledigheid van het testen van functies te evalueren en de behoefte aan aanvullende testsuites te bepalen.
Telkens wanneer een functie verandert, moeten regressietests worden uitgevoerd om er zeker van te zijn dat er geen nieuwe bugs zijn en/of dat eerdere bugs zijn opgelost. Het opnemen van blokregressietesten in het ontwikkelingsproces beschermt tegen veel fouten; deze worden onmiddellijk nadat ze zich voordoen gedetecteerd en kunnen er niet voor zorgen dat fouten zich door de applicatie verspreiden.
Regressietesten kunnen op twee manieren worden uitgevoerd. De eerste is dat de ontwikkelaar of tester elke testcase analyseert en bepaalt welke van hen mogelijk door de gewijzigde code wordt beïnvloed. Deze aanpak wordt gekenmerkt door het besparen van machinetijd ten koste van menselijk werk. De tweede, effectievere, is om na elke tekstwijziging automatisch alle testsets op de computer uit te voeren. Deze aanpak zorgt voor een grotere efficiëntie voor de ontwikkelaar, omdat hij geen tijd hoeft te besteden aan het analyseren van de hele set testgevallen om te bepalen welke sets moeten worden uitgevoerd en welke niet.
Als u het unit-testproces kunt automatiseren, verbetert u niet alleen de kwaliteit van het testen, maar maakt u ook aanzienlijk meer tijd en materiële middelen vrij dan u aan dit proces zou besteden. Als je programma's in C schrijft, kun je bestaande technologieën gebruiken om unit-tests te automatiseren. Hoe meer processen u kunt automatiseren, hoe meer voordelen u krijgt.
Wanneer u een unit-testtechnologie kiest, moet u eerst de volgende vragen beantwoorden:
Is deze technologie geschikt voor uw tekst en/of compiler?
Kan het automatisch testcircuits genereren?
Kan het automatisch testgevallen genereren?
Staat het de introductie toe van door de gebruiker gemaakte testgevallen en dummymodules?
Zijn regressietesten geautomatiseerd?
Bevat het technologie voor het automatisch herkennen van fouten tijdens de run, of is er een link naar?
Foutopsporingstools die de werkingsmodus van programma's niet veranderen

Omdat real-time besturingssystemen bepaalde taken moeten uitvoeren onder vooraf bepaalde timingbeperkingen, wordt timing een kritische parameter waarmee ontwikkelaars rekening moeten houden bij het opzetten van testsoftware. Normaal gesproken vinden er veel verschillende interrupts plaats tijdens de uitvoering van een programma, en het is van cruciaal belang dat de toepassing correct reageert wanneer de interrupt optreedt. De situatie wordt zelfs nog ingewikkelder wanneer er meerdere interrupts tegelijk plaatsvinden of wanneer het systeem meerdere applicaties draait waarbij meerdere threads met elkaar interacteren. In wezen zijn dit applicaties met meerdere gelijktijdige uitvoeringspaden; verschillende codereeksen lijken tegelijkertijd te worden uitgevoerd, zelfs als er maar één centrale processor in het systeem is. Het is interessant om op te merken dat als deze applicaties op meerdere processors zouden draaien, er in de praktijk verschillende threads op verschillende processors zouden worden geladen.
Als er fouten optreden in real-time toepassingen in de interactie tussen het programma en interrupts, zullen deze zeer tijdgevoelig zijn. In dit geval is het van cruciaal belang om de volgorde waarin fouten optreden vast te leggen, omdat u hierdoor de oorzaak en het gevolg van elke fout kunt begrijpen. Dit is precies het grootste probleem bij het debuggen van real-time systemen: er zijn voldoende moeilijk te detecteren fouten die alleen bij bepaalde timingrelaties optreden.
Dit probleem wordt gecompliceerd door het feit dat dergelijke fouten niet gemakkelijk kunnen worden gereproduceerd. Het is erg moeilijk om de situatie opnieuw te creëren met dezelfde timingrelaties die tot de fout hebben geleid in een echt programma. Het mechanisme voor het debuggen van dergelijke toepassingen moet zo zacht mogelijk zijn. Elke interventie in de uitvoering van programma's kan leiden tot een verandering in de timingkarakteristieken en de afwezigheid van foutcondities. Natuurlijk is het goed om omstandigheden te creëren waaronder fouten niet optreden, maar in dit geval vormt het een obstakel voor het debuggen van het programma.
De theoretische basis voor het probleem van het debuggen van real-time systemen kan het onzekerheidsprincipe zijn van de Duitse natuurkundige Werner Heisenberg, bij iedereen bekend van natuurkundecursussen, volgens welke het onmogelijk is om tegelijkertijd de snelheid en locatie van een bewegend deeltje te bepalen. Heisenberg geloofde dat door het bepalen van de coördinaten van een deeltje, de onderzoeker daardoor zijn locatie verandert, waardoor de coördinaten niet nauwkeurig kunnen worden bepaald. De meetbewerking heeft invloed op het te meten object en vervormt de meetresultaten. Het onzekerheidsprincipe is een van de axioma's van de kwantummechanica.
Zoals toegepast op ons onderwerp betekent dit principe dat het debuggen van een systeem het verzamelen van informatie over de staat ervan vereist. Het verzamelen van informatie over de status van het systeem verandert echter de timingkarakteristieken en maakt het veel moeilijker om foutcondities betrouwbaar te reproduceren.
De essentie van dit probleem is dus dat we een manier moeten vinden om real-time fouten te detecteren en programmagedrag te analyseren zonder de bestaande timingrelaties te beïnvloeden. Je eerste instinct zou waarschijnlijk zijn om je tot een debugger te wenden, maar debuggers onderbreken in de regel de uitvoering van het programma en veranderen dienovereenkomstig de timingkarakteristieken. Simulatiesystemen hebben ook weinig nut, omdat ze de tijdskarakteristieken van echte technische middelen niet kunnen reproduceren. Niemand heeft nog een simulatiesysteem gemaakt dat realtime kan simuleren; tijdelijke parameters kunnen alleen worden bepaald door het programma in de hardware zelf te laden.
Dit laatste vereist een speciaal mechanisme voor vereenvoudigde registratie van de systeemstatus. Een van de mogelijke en geschikte mechanismen is het opnemen van informatie in RAM, aangezien een dergelijke bewerking extreem snel wordt uitgevoerd. Eén manier om dit mechanisme te gebruiken is door ergens in het geheugen een speciale buffer te organiseren en in uw programma een verwijzing naar deze buffer te gebruiken. De aanwijzer wijst altijd naar het begin van de buffer. Het programma voegt schrijfbewerkingen in de cel in die door de aanwijzer wordt geïdentificeerd. Na elke schrijfbewerking verandert de pointerwaarde dienovereenkomstig. Soms is het handig om een ​​ringbuffer te gebruiken (dat wil zeggen: na het schrijven naar de laatste cel van de buffer begint de aanwijzer naar het begin van de buffer te wijzen), waarmee u de situaties kunt volgen die tot het probleem hebben geleid. Het is noodzakelijk om een ​​manier te bieden om de inhoud van de buffer op te slaan na normale of abnormale beëindiging van het programma, om er vervolgens toegang toe te hebben en zogenaamde “post-mortem debugging” uit te voeren. De implementatiemethode is afhankelijk van de hardware, maar kan doorgaans worden uitgevoerd zonder de hardware opnieuw te initialiseren.
Nu heb je een mechanisme nodig om dit geheugen te lezen. Hier kunt u een debugger en andere middelen gebruiken om informatie uit het RAM te extraheren. U kunt met name een eenvoudig programma schrijven dat deze gegevens naar een bestand of naar een printer stuurt. Welke tool u ook gebruikt, de laatste stap zal hoogstwaarschijnlijk een handmatige analyse van de bufferinhoud zijn. Als uw buffer een ringbuffer is, moet u nauwkeurige kennis hebben van de waarde van de aanwijzer; gebeurtenissen waarmee de reeks begon, zullen onmiddellijk vóór de aanwijzer plaatsvinden, gebeurtenissen die vlak voor de crash plaatsvonden, zullen onmiddellijk na de aanwijzer plaatsvinden.

Rijst. 5. Volgorde van gebeurtenissen in de ringbuffer

Nu is het uw belangrijkste taak om te proberen de volgorde van de gegevens die in de buffer zijn geschreven te begrijpen. Deze taak is vergelijkbaar met het bestuderen van de oorzaken van een vliegtuigongeluk met behulp van instrumentmetingen die zijn vastgelegd door de ‘zwarte doos’ van het vliegtuig. In dit geval wordt de analyse van de kenmerken van het programma achteraf uitgevoerd, wat uiteraard veel minder impact heeft op de uitvoering ervan dan monitoring tijdens bedrijf.
Soms kan het erg moeilijk zijn om de gebeurtenissen die tot de crash hebben geleid te reconstrueren, en is er geen duidelijk idee wanneer de fout is opgetreden. Het kan vele maanden duren om de oorzaak van de fout te achterhalen. In dergelijke gevallen kunt u de logaritmische foutopsporingsmethode gebruiken om de foutieve verklaring te vinden. Op verschillende plaatsen in de code die wordt opgespoord, worden markeringen geplaatst (bijvoorbeeld operatoren zoals exit), en daarvoor staan ​​geheugenschrijfoperatoren. Vervolgens voer je het programma uit en wacht je op het moment van de crash. Bij een crash weet je tussen welke markeringen deze heeft plaatsgevonden. Deze methode kan ook timingproblemen identificeren omdat codesegmenten kunnen worden gevonden waar timingovertredingen optreden.
Een andere oplossing is het gebruik van zogenaamde firewalls als debugging-technologie. Een firewall is een punt in de logische stroom van een programma waarop de geldigheid van de aannames waarop de daaropvolgende code berust, wordt bewezen. Het controleren van deze aannames verschilt van de normale foutcontrole. Activering van de firewall is een signaal voor de ontwikkelaar dat de interne toestand van het systeem instabiel is. Dit kan bijvoorbeeld gebeuren als een functie die een strikt positief argument verwacht, een nul- of negatieve waarde krijgt. Voor onervaren ontwikkelaars lijken de meeste firewalls triviaal en onnodig. De ervaring met de ontwikkeling van grote projecten leert echter dat naarmate softwaresystemen zich ontwikkelen en verbeteren, impliciete aannames met betrekking tot de uitvoeringsomgeving steeds vaker worden geschonden. In veel gevallen vindt zelfs de auteur zelf het moeilijk om te formuleren wat de juiste voorwaarden zijn voor het uitvoeren van een bepaald stuk code.
Firewalls die in ingebedde systemen zijn geïmplementeerd, vereisen speciale communicatiemiddelen om berichten naar de buitenwereld te verzenden; een discussie over hoe dergelijke transmissiekanalen tot stand kunnen worden gebracht valt buiten het bestek van dit artikel.
Conclusie

De hierboven besproken methoden voor foutpreventie en -detectie, evenals debug-technologieën, kunnen de kwaliteit van ingebedde systeemsoftware aanzienlijk verbeteren en de hoeveelheid materiaal en tijd die aan het debuggen wordt besteed, verminderen. De bovenstaande methoden kunnen gemakkelijk worden gebruikt bij de ontwikkeling van een grote verscheidenheid aan softwareprojecten voor embedded systemen, en de opgebouwde ervaring behoudt volledig zijn waarde bij het implementeren van andere projecten en doeltechnologieën. Bovendien maken ze het mogelijk om het gemak van onderhoud, wijziging en portering van gemaakte programma's naar nieuwe soorten apparaten te garanderen. Kortom, de technieken die we behandelen stellen u niet alleen in staat uw bestaande embedded applicaties en ontwikkelingsprocessen te verbeteren, maar zorgen er ook voor dat naarmate nieuwe embedded devices zich verspreiden, u al over de expertise beschikt die nodig is om op tijd en op tijd hoog presterende applicaties voor deze technologieën te ontwikkelen. tijd.
Literatuur

1. M. Aivazis en W. Hicken. "C++ defensief programmeren: firewalls en foutopsporingsinformatie." C++-rapport (juli-augustus 1999): 34 40.