{
    "id": 683,
    "date": "2018-04-16T21:23:40",
    "date_gmt": "2018-04-16T21:23:40",
    "guid": {
        "rendered": "http:\/\/hayperek.pl\/?p=683"
    },
    "modified": "2018-04-16T21:23:40",
    "modified_gmt": "2018-04-16T21:23:40",
    "slug": "alokacja-pamieci-w-systemach-wbudowanych",
    "status": "publish",
    "type": "post",
    "link": "https:\/\/hayperek.pl\/pl_pl\/2018\/04\/16\/alokacja-pamieci-w-systemach-wbudowanych\/",
    "title": {
        "rendered": "Alokacja pami\u0119ci w systemach wbudowanych"
    },
    "content": {
        "rendered": "<p>Dzisiejszy temat to pr\u00f3ba powrotu do stylu pierwszych artyku\u0142\u00f3w, nieco bardziej teoretycznych i przegadanych \ud83d\ude42 Tym razem chcia\u0142bym poruszy\u0107 temat szeroko poj\u0119tego zarz\u0105dzania pami\u0119ci\u0105 w systemach wbudowanych.<\/p>\n<h5>Harward czy von Neumann?<\/h5>\n<p>Te dwie nazwy brzmi\u0105 znajomo dla czytelnik\u00f3w zaznajomionych nieco z dzia\u0142aniem procesor\u00f3w. <a href=\"https:\/\/pl.wikipedia.org\/wiki\/Architektura_von_Neumanna\">Architektura von Neumanna<\/a> zak\u0142ada, \u017ce zar\u00f3wno program jak i przetwarzane dane umieszczone s\u0105 w tej samej pami\u0119ci. Mo\u017cna powiedzie\u0107, \u017ce te s\u0142owa czytacie dzi\u0119ki typowemu przedstawicielowi tej rodziny \ud83d\ude42 Tak &#8211; komputery, tablety, telefony kom\u00f3rkowe &#8211; wszystkie te urz\u0105dzenia nale\u017c\u0105 w\u0142a\u015bnie do niej.<\/p>\n<p><a href=\"https:\/\/pl.wikipedia.org\/wiki\/Architektura_harwardzka\">Architektura harwardzka<\/a> wymusza z kolei rozdzielenie pami\u0119ci danych od pami\u0119ci programu &#8211; s\u0105 to ca\u0142kowicie odr\u0119bne przestrzenie adresowe. Pozornie mo\u017ce wydawa\u0107 si\u0119 ona przez to bardziej skomplikowana, jednak w rzeczywisto\u015bci \u00f3w podzia\u0142 r\u00f3l znacznie upraszcza budow\u0119 CPU. Najcz\u0119\u015bciej kod programu znajduje si\u0119 w nieulotnej pami\u0119ci typu ROM\/Flash, natomiast dane l\u0105duj\u0105 w pami\u0119ci typu RAM\/SDRAM. Z tego wzgl\u0119du architektura ta dominuje w \u015bwiecie embedded &#8211; zdecydowana wi\u0119kszo\u015b\u0107 najpopularniejszych mikrokontroler\u00f3w dzia\u0142a w\u0142a\u015bnie wed\u0142ug tej zasady.<\/p>\n<blockquote><p>A jak to jest u nas?<\/p><\/blockquote>\n<p>W projekcie u\u017cywamy procesora STM32F407, nale\u017c\u0105cego do rodziny ARM Cortex-M4. Jego CPU stanowi po\u0142\u0105czenie obu idei &#8211; posiada on odr\u0119bne magistrale dla danych i kodu programu, jednak przechowywane s\u0105 one we wsp\u00f3lnej przestrzeni adresowej. Tego rodzaju struktur\u0119 systemu nazywa si\u0119 tzw. zmodyfikowan\u0105 architektur\u0105 harwardzk\u0105. Teoretycznie mamy zar\u00f3wno mo\u017cliwo\u015b\u0107 uruchomienia kodu aplikacji z pami\u0119ci RAM, jak i odczytania danych z pami\u0119ci nieulotnej Flash. W naszym projekcie nie b\u0119dziemy jednak korzysta\u0107 z tej pierwszej opcji.<\/p>\n<blockquote><p>Dlaczego?<\/p><\/blockquote>\n<p>Najzwyczajniej w \u015bwiecie nie ma takiej potrzeby &#8211; ca\u0142y kod zostanie umieszczony we wbudowanej pami\u0119ci nieulotnej, co pozwoli uruchomi\u0107 procesor bez konieczno\u015bci korzystania z dodatkowych, zewn\u0119trznych ko\u015bci Flash czy karty SD.<\/p>\n<h5>Alokowanie pami\u0119ci RAM<\/h5>\n<p>W systemach wbudowanych zasadniczo korzysta si\u0119 z tzw. statycznej alokacji. Innymi s\u0142owy wszystkie dane maj\u0105 sta\u0142e i niezmienne po\u0142o\u017cenie w pami\u0119ci RAM. Ka\u017cda zmienna, tablica czy struktura istnieje <em>&#8222;od pocz\u0105tku do ko\u0144ca \u015bwiata&#8221;<\/em>, czyli od uruchomienia urz\u0105dzenia a\u017c do wy\u0142\u0105czenia zasilania lub resetu. Pozwala to zaoszcz\u0119dzi\u0107 ogromn\u0105 ilo\u015b\u0107 czasu jak\u0105 poch\u0142on\u0119\u0142aby tradycyjna alokacja pami\u0119ci na <a href=\"https:\/\/pl.wikipedia.org\/wiki\/Alokacja_pami%C4%99ci\">stercie<\/a>. <\/p>\n<blockquote><p>Hmm&#8230; Czyli wszystkie widgety, okna, itd. b\u0119d\u0105 stworzone statycznie?<\/p><\/blockquote>\n<p>Tu sytuacja nieco si\u0119 komplikuje, gdy\u017c do akcji wkracza C++. Oczywi\u015bcie, mo\u017cemy tworzy\u0107 ka\u017cd\u0105 instancj\u0119 klasy statyczne, jako np. zmienn\u0105 globaln\u0105. Jest to jednak skrajnie nieefektywne podej\u015bcie:<\/p>\n<ul>\n<li>powstaje spora ilo\u015b\u0107 kodu, definiuj\u0105cego ca\u0142\u0105 chmur\u0119 obiekt\u00f3w oraz okre\u015blaj\u0105ca relacje mi\u0119dzy nimi,<\/li>\n<li>przy tworzeniu obiektu jeste\u015bmy ograniczeni do zakresu parametr\u00f3w przekazywanych statycznie do konstruktora klasy,<\/li>\n<li>wszystkie obiekty s\u0105 tworzone tu\u017c przy starcie systemu, co wp\u0142ywa na wyd\u0142u\u017cenie czasu uruchomienia aplikacji,<\/li>\n<li>ka\u017cdy obiekt trzeba nazwa\u0107 (<em>Brzmi absurdalnie? Droga Czytelniczko\/Drogi Czytelniku, spr\u00f3buj zatem wymy\u015bli\u0107 kilkadziesi\u0105t niepowtarzalnych nazw, jasno opisuj\u0105cych czym dany obiekt si\u0119 zajmuje, a kt\u00f3re nie b\u0119d\u0105 d\u0142u\u017csze ni\u017c 20 znak\u00f3w \ud83d\ude42<\/em> )<\/li>\n<\/ul>\n<p>W takiej sytuacji jedynym rozwi\u0105zaniem jest dynamiczne przydzielanie pami\u0119ci dla nowo tworzonych obiekt\u00f3w. <\/p>\n<blockquote><p>Jak zrobi\u0107 to efektywnie i zgodnie ze sztuk\u0105?<\/p><\/blockquote>\n<p>Dobr\u0105 praktyk\u0105, spotykan\u0105 w systemach wbudowanych, jest tworzenie odr\u0119bnych stert <em>(ang. heap)<\/em> dla poszczeg\u00f3lnych rodzaj\u00f3w obiekt\u00f3w tworzonych w systemie. Minimalizuje to ryzyko potencjalnego wzajemnego nadpisywania si\u0119 s\u0105siaduj\u0105cych ze sob\u0105 obiekt\u00f3w czy struktur. Znacz\u0105co upraszcza to r\u00f3wnie\u017c debugowanie i u\u0142atwia \u015bledzenie zu\u017cycia pami\u0119ci przez poszczeg\u00f3lne komponenty. Dodatkowo je\u015bli w systemie mamy wi\u0119cej ni\u017c dwa banki pami\u0119ci <em>(zazwyczaj szybszy, ale mniejszy i wolniejszy, za to o wiele bardziej pojemny)<\/em>, mo\u017cemy niezale\u017cnie przydziela\u0107 ich kawa\u0142ki, wed\u0142ug realnych potrzeb danej aplikacji.<\/p>\n<h5>Gonimy w\u0142asny ogon, czyli cykliczny alokator<\/h5>\n<p>Standardowa implementacja sterty pozwala zar\u00f3wno alokowa\u0107 kawa\u0142ki pami\u0119ci, jak i zwalnia\u0107 je do ponownego u\u017cycia. Wprowadza to dodatkowy nak\u0142ad obliczeniowy oraz wymaga po\u015bwi\u0119cenia obszaru pami\u0119ci na przechowywanie informacji o strukturze zaalokowanych fragment\u00f3w. Projektuj\u0105c system, warto zada\u0107 sobie pytanie, czy na pewno b\u0119dziemy w jakikolwiek spos\u00f3b zwalnia\u0107 pami\u0119\u0107&#8230;<\/p>\n<p>W naszym przypadku, alokacja zostanie przeprowadzona tylko raz, w czasie budowania interfejsu graficznego. P\u00f3\u017aniej wszystkie niezb\u0119dne obiekty b\u0119d\u0105 istnia\u0142y w pami\u0119ci a\u017c do momentu wy\u0142\u0105czenia urz\u0105dzenia. <\/p>\n<blockquote><p>Czy w zwi\u0105zku z tym mo\u017cna jako\u015b zoptymalizowa\u0107 zarz\u0105dzanie pami\u0119ci\u0105?<\/p><\/blockquote>\n<p>Oczywi\u015bcie! Niezwykle prostym i popularnym rozwi\u0105zaniem jest tzw. cykliczny alokator. Na \u017c\u0105danie przydziela on kolejny fragment, o okre\u015blonym rozmiarze, a\u017c dojdzie do ko\u0144ca dost\u0119pnej pami\u0119ci. I tyle! \ud83d\ude42 Jest to typowy przyk\u0142ad optymalizacji w systemach wbudowanych, kt\u00f3re przyspieszaj\u0105 dzia\u0142anie systemu kosztem nieco wi\u0119kszego nak\u0142adu pracy i uwagi developera. To w gestii programisty le\u017cy dbanie, aby zawsze wystarczy\u0142o miejsca, aby\u015bmy nie weszli w szkod\u0119 s\u0105siadowi i nie &#8222;zjedli w\u0142asnego ogona&#8221;&#8230; Co zar\u00f3wno dos\u0142ownie jak i w przeno\u015bni nie oznacza nic dobrego.<\/p>\n<p>Tyle rozwa\u017ca\u0144 na dzi\u015b! Do zobaczenia jutro \ud83d\ude42<\/p>",
        "protected": false
    },
    "excerpt": {
        "rendered": "<p>Dzisiejszy temat to pr\u00f3ba powrotu do stylu pierwszych artyku\u0142\u00f3w, nieco bardziej teoretycznych i przegadanych \ud83d\ude42 Tym razem chcia\u0142bym poruszy\u0107 temat szeroko poj\u0119tego zarz\u0105dzania pami\u0119ci\u0105 w systemach wbudowanych. Harward czy von Neumann? Te dwie nazwy brzmi\u0105 znajomo dla czytelnik\u00f3w zaznajomionych nieco z dzia\u0142aniem procesor\u00f3w. Architektura von Neumanna zak\u0142ada, \u017ce zar\u00f3wno program jak i przetwarzane dane umieszczone [&hellip;]<\/p>",
        "protected": false
    },
    "author": 1,
    "featured_media": 693,
    "comment_status": "closed",
    "ping_status": "open",
    "sticky": false,
    "template": "",
    "format": "standard",
    "meta": {
        "footnotes": ""
    },
    "categories": [
        3
    ],
    "tags": [],
    "class_list": {
        "0": "post-683",
        "1": "post",
        "2": "type-post",
        "3": "status-publish",
        "4": "format-standard",
        "5": "has-post-thumbnail",
        "6": "hentry",
        "7": "category-stodni",
        "9": "post-with-thumbnail",
        "10": "post-with-thumbnail-large"
    },
    "_links": {
        "self": [
            {
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/posts\/683",
                "targetHints": {
                    "allow": [
                        "GET"
                    ]
                }
            }
        ],
        "collection": [
            {
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/posts"
            }
        ],
        "about": [
            {
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/types\/post"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/users\/1"
            }
        ],
        "replies": [
            {
                "embeddable": true,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/comments?post=683"
            }
        ],
        "version-history": [
            {
                "count": 9,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/posts\/683\/revisions"
            }
        ],
        "predecessor-version": [
            {
                "id": 692,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/posts\/683\/revisions\/692"
            }
        ],
        "wp:featuredmedia": [
            {
                "embeddable": true,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/media\/693"
            }
        ],
        "wp:attachment": [
            {
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/media?parent=683"
            }
        ],
        "wp:term": [
            {
                "taxonomy": "category",
                "embeddable": true,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/categories?post=683"
            },
            {
                "taxonomy": "post_tag",
                "embeddable": true,
                "href": "https:\/\/hayperek.pl\/pl_pl\/wp-json\/wp\/v2\/tags?post=683"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https:\/\/api.w.org\/{rel}",
                "templated": true
            }
        ]
    }
}