logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ARM] ARM – uruchamianie skompilowanych programów z różnych adresów, wielowątkowość

xŁolesxxx 09 Kwi 2012 21:19 3880 29
REKLAMA
  • #1 10776381
    xŁolesxxx
    Poziom 14  
    Posty: 163
    Ocena: 2
    Witam.
    Zastanawiam się nad realizacją wielowątkowości. Che napisać taki mini system zarządzający procesami, lądował by je z karty i uruchamiał. Ale nie za bardzo wiem czy to się uda i nie wiem jak szukać informacji o tym. Mianowicie czy da się uruchamiać jakiś skompilowany program z pod rożnych adresów. W sensie że raz jest gdzieś tam załadowany a innym razem gdzieś kawałek dalej ? Bo problem chyba ze skokami się pojawi, bo wydaje mi się że w momencie kompilacji jest to ustawione na sztywno ? Proszę o wyjaśnienie mi tego lub o jakiś link gdzie mogę o tym poczytać. Jeśli dubluje jakiś temat to przepraszam ale nie udało mi się nic znaleźć.
    Dzięki.
  • REKLAMA
  • #2 10776618
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Wbrew pozorom instrukcje skoków nie są problemem. Każdy procesor ma skoki względne, dzięki czemu można program dowolnie przemieszczać w pamięci. Problemem są struktury danych - program w C zakłada pewną strukturę segmentów pamięci i trzyma tam m.in. zmienne globalne. Także twój program musiałby korzystać wyłącznie ze zmiennych lokalnych (i nie wykorzystywać zmiennych statycznych), dodatkowo musiałby być pozbawiony kodu startowego, za odwiednią inicjalizację procesora i struktur danych odpowiedzialny byłby program wywołujący. Temat jest oczywiście szerszy.
  • #3 10777017
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Skoki względne skokami względnymi, ale funkcje wywoływane są po adresie... Też się zastanawiałem nad tym tematem i też mnie on bardzo ciekawi. Opcja kompilatora -fPIC niewiele zmienia, albo ja nie umiem jej obsługiwać <:

    4\/3!!
  • #4 10777064
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Bo nie wywołuje się funkcji od nowa. Skok z i do funkcji może nastąpić w jej połowie. Wygląda to tak, że robi się gdzieś zrzut PC, rejestrów, czegoś tam jeszcze, dla każdego taska i potem na tej podstawie się skacze gdzieś z powrotem.

    Jest to oczywiście dużo bardziej skomplikowane niż takie sobie. Gość który wymyślił uC/OS pierwszą podstawową wersję pisał chyba rok.
  • #5 10777083
    xŁolesxxx
    Poziom 14  
    Posty: 163
    Ocena: 2
    Trzeba jakiś zegar który będzie generował przerwania. W momencie przerwania trzeba zapisać stany rejestrów w wydzielonej pamięci procesu, załadować inne związywane z kolejnym procesem i uruchomić od momentu zatrzymania. Każdy proces miałby swój stos i pozostaje tylko kwestia adresowania. Chaba że może da się jakieś adresy wirtualne, to by sprawę załatwiło całkowicie ?
  • #6 10777107
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Freddie Chopin napisał:
    Skoki względne skokami względnymi, ale funkcje wywoływane są po adresie... Też się zastanawiałem nad tym tematem i też mnie on bardzo ciekawi. Opcja kompilatora -fPIC niewiele zmienia, albo ja nie umiem jej obsługiwać <:

    4\/3!!


    A nie ma w ARM instrukcji wywołania funkcji z adresem względnym? Powinna być. A jeśli nie ma to wystarczy dodawać adres początku programu do offsetu wyliczonego przez linker.
  • REKLAMA
  • #7 10777167
    Byron
    Poziom 11  
    Posty: 12
    Pomógł: 1
    Witam.

    Oczywiscie ze fpic dziala.
    Drodzy koledzy poczytajcie sobie o Global offset table (sekcja .got)
    Wystaczy ja przerelokowac i problem rozwiazany.

    Pozdrawiam
    Marcin
  • #8 10777368
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    tmf napisał:
    A nie ma w ARM instrukcji wywołania funkcji z adresem względnym? Powinna być. A jeśli nie ma to wystarczy dodawać adres początku programu do offsetu wyliczonego przez linker.

    Wszystko jest, tylko kompilator i linker generuje kod w którym adresy wywoływania funkcji są na sztywno...

    Byron napisał:
    Oczywiscie ze fpic dziala.
    Drodzy koledzy poczytajcie sobie o Global offset table (sekcja .got)
    Wystaczy ja przerelokowac i problem rozwiazany.

    Sprawdziłeś? Bo ja sprawdziłem. Dodanie tej opcji (albo -fpie) nie zmienia generalnie NIC... Funkcje w każdym przypadku wywoływane są "na sztywno" po adresie. Kiedyś udało mi się zrobić tak, że stałe i zmienne są wywoływane przez rejestr R12, ale teraz nie mogę tego powtórzyć.

    4\/3!!
  • REKLAMA
  • #9 10777381
    Konto nie istnieje
    Konto nie istnieje  
  • #10 10777538
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Freddie a nie można gdzieś w tablicy przechowywać tychże adresów do funkcji jako wskaźników do nich ?

    Jeśli chodzi o używanie zmiennych lokalnych, to do komunikacji między wątkami z takowymi można zaimplementować kolejkę.
    Btw, jeśli ktoś napisze system operacyjny, to jego pierwsza wersja będzie pewnie migała diodami a nie wymieniała dane między wątkami :)
  • #11 10777576
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    gaskoin napisał:
    Freddie a nie można gdzieś w tablicy przechowywać tychże adresów do funkcji jako wskaźników do nich ?

    No ale zapanujesz nad WSZYSTKIM? Nad funkcjami wywoływanymi "z ukrycia" (np. konwersja z liczby całkowitej na floata, dzielenie na architekturze która nie ma do tego rozkazu, ...) też? Nie chodzi mi o funkcje które sobie wywołuję ja, bo wtedy sprawa jest dosyć prosta, ale właśnie o takie funkcje biblioteczne - a przecież zwykle każda z nich wywołuje ze sto innych...

    4\/3!!
  • #12 10777618
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Wydaje mi się, że ważny będzie tylko start tych funkcji, ponieważ potem przeskakując pomiędzy taskami wystarczyło by zapisać sobie PC + resztę rejestrów i stos, po czym je odtwarzać w odpowiedniej kolejności (taski).

    Niektóre ARMy mają specjalne timery, instrukcje i przerwania pod systemy operacyjne, ale tyle, to pewnie też wiecie :)
  • #13 10777668
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    No ale wtedy każdy "task" musiałbyś mieć w postaci kompletnej aplikacji, ładowanej tylko i wyłącznie pod JEDEN (wybrany na etapie linkowania) adres.

    4\/3!!
  • #14 10777977
    Konto nie istnieje
    Konto nie istnieje  
  • #15 10777986
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Najbardziej interesującą opcją byłoby mieć mozliwość wrzucenia funkcji gdziekolwiek, funkcje "systemowe" żeby sobie były zupełnie gdzie indziej - taki system operacyjny jak na PC (; Gdyby faktycznie udało się zmusić GCC do korzystania z jumptable przy każdym wywołaniu funkcji i np tego offsetu do stałych to byłoby idealnie, ale chyba nie da rady tego zrobić...

    4\/3!!
  • #16 10778019
    Konto nie istnieje
    Konto nie istnieje  
  • #17 10778052
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Bo Freddie chciał pokonać system i mieć system operacyjny, do którego pewnie wrzuca taski, jako osobne pliki wykonywalne, choćby z np karty SD, wtedy nie może znać adresu. Jednak jest to o tyle trudne, że będziesz musiał najpierw sobie napisać taki system "taskowy" o którym piszę :) Generalnie jest tak, że trzeba zająć odpowiednią ilość pamięci i wrzucić w nią cały program. Coś jak malloc dla zmiennej - od razu masz adres gdzie jest program, a reszta wygląda już tak samo, więc też możesz sobie dorzucić start programu do tablicy :)
  • #18 10778074
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    albertb napisał:
    Jeśli tak, to nie rozumiem zastrzeżeń z #11 do metody gaskoina.
    Na etapie tworzenia "appletu" znasz przecież adresy wszystkich funkcji systemowych.
    Więc czemu nie mogą być wywołane na sztywno po adresie?
    A wszystkie swoje, które mogą trafić w nieznane miejsce poprzez tablicę jak pisał gaskoin?

    No ale jak zmusić kompilator, do wywołania funkcji "ukrytych" spod jakiegoś konkretnego adresu?

    4\/3!!
  • #19 10778100
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Freddie Chopin napisał:
    No ale wtedy każdy "task" musiałbyś mieć w postaci kompletnej aplikacji, ładowanej tylko i wyłącznie pod JEDEN (wybrany na etapie linkowania) adres.

    4\/3!!


    No niekoniecznie. Aplikację można przecież zlinkować z własnymi bibliotekami, w szczególności z wersją libc użytą przez OS, wtedy będziesz miał automatycznie wszystkie wywołania funkcji bibliotecznych poprawne. W ramach programu z definicji wszystkie wywołania będą poprawne, bo o to zadba linker. A poszczególne taski przecież wzajemnie nie wywołują funkcji z innego tasku. Jedyne co trzeba zapewnić to zamianę wszystkich wywołań na wywołania względne, no albo ładować elfa i robić translację adresów. To w sumie nie jest takie trudne o ile mówimy o C, jeśli to będzie C++ to sprawa się znacznie komplikuje.
    Swoją drogą, nie lepiej przeanalizować kod jakiegoś RTOS, będzie widać jak to jest zrobione.
  • #20 10778136
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Pewnie jest to robione pamięcią wirtualną, bo niby jak inaczej zrobić to prosto i wydajnie? (; No i na takie "duże" systemy operacyjne kod jest faktycznie "PIC" i "PIE", a jakoś na bare-metal ARM niezbyt wychodzi taka kombinacja...

    4\/3!!
  • #21 10778166
    Konto nie istnieje
    Konto nie istnieje  
  • #22 10778213
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    albertb napisał:

    tmp napisał:

    Aplikację można przecież zlinkować z własnymi bibliotekami, w szczególności z wersją libc użytą
    ...


    W szczególności podoba mi się tyle printf -ów ile tasków ;-)

    Albert


    A niby dlaczego miałby ich tyle być? Przecież linkuje z biblioteką, która jest już w tym "OSie", a nie dołącza jej do każdego tasku.
  • #23 10778232
    Konto nie istnieje
    Konto nie istnieje  
  • #24 10778324
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    A kto mówi o dynamicznym linkowaniu? Na etapie kompilacji tego "tasku" się linkuje z biblioteką. Tyle, że zostawia się sam kod "tasku", a bibliotekę wywala, będzie ona w OS i linkowanie ciągle będzie poprawne, o ile ktoś nie zmieni miejsca samej biblioteki, co nie jest problemem, bo segmenty można ustawiać na sztywno. Nie wiem z czym tu masz problem.

    albertb napisał:
    Napisz jak w tasku zlinkować dynamicznie bibliotekę z systemu, a ci odpuszczę grzechy,
    Albert


    Ksiądz, czy co?
  • #25 10778418
    Konto nie istnieje
    Konto nie istnieje  
  • #26 10778586
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Akurat sposób działa doskonale, nie testowałem tego z ARM , ale z AVR (myślę, że procesor nie ma tu nic do rzeczy). Zresztą opisałem go z działającymi przykładami w swojej książce. Ale po kolei. Linker nie stanowi problemu - on ma za zadanie uzupełnić adresy wywołań funkcji bibliotecznych w aplikacji. Może z biblioteki wywalać funkcje, ale nie musi. Linker w ogóle samej biblioteki ma "nie dotykać", jedynie ma zająć się kodem aplikacji. Jak to zrobić? Ano wywalanie funkcji jest opcjonalne, dwa, że nadając funkcji atrybut used zablokujemy możliwość jej wywalenia. Mamy bibliotekę - zmieniając adresy segmentu .text możemy spowodować, że zostanie umieszczona pod konkretnym adresem. Ok, mamy już stałe adresy funkcji bibliotecznych. Linkujemy teraz aplikację z taką biblioteką. W efekcie mamy plik wynikowy składający się z dwóch części - pierwsza to biblioteka (dla wszystkich aplikacji umieszczona pod tym samym adresem - relokowaliśmy segment .text). Będzie ona identyczna dla wszystkich aplikacji i ją wywalamy. Druga - to właściwa aplikacja, zawierająca kod odwołujący się do biblioteki. Aby to zadziałało ten "OS" musi umieścić bibliotekę pod adresem pod którym się jej spodziewa aplikacja. Ale biblioteka będzie współdzielona przez wszystkie aplikacje. Po wczytaniu kodu aplikacji wszystko wygląda dla niej tak jak powinno. Z kolei do samych funkcji aplikacji (o ile zachodzi taka potrzeba) można się odwołać poprzez tablicę wektorów, którą też można wygenerować automatycznie (jak to odsyłam znowu do książki, bo za długo by pisać). Jedyny kłopot jest z funkcjami bibliotecznymi, które nie są reentrant (niektóre funkcje IO i alokacja pamięci dynamicznej). Trzeba jeszcze zadbać aby aplikacja nie bruździała w pamięci - ale nie ma problemu o ile nie używamy zmiennych globalnych.
  • #27 10781038
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #28 10781772
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2205
    Problem leży w tym jak standardowo zbudowana jest libc, a właściwie to jest kilka problemów. Pierwszy - przykłady z mnożeniem i innymi prostymi operacjami nie są najlepsze, bo odpowiedni kod może nie pochodzić z libc tylko być generowany bezpośrednio przez kompilator. Tak jest np. na AVR w przypadku operacji na liczbach long, wtedy każda aplikacja i tak będzie miała swoją wersję, chyba, że odpowiednie symbole pojawią się w linkowanej bibliotece. Ale to akurat małoistotne dla naszych rozważań. Drugi problem jest poważniejszy. Libc, podobnie jak wiele innych bibliotek ma każdą funkcję w osobnym pliku obj, w efekcie linker wywala niepotrzebne funkcje w całości, co powoduje przesunięcie adresu innych funkcji. I tu niestety dotykamy tematu kopilatorospecyficznego lub musimy stworzyć własne libc. To drugie jest bardziej uniwersalne, ale i kłopotliwe. Trzeba przekompilować całe libc tak, aby wszystkie funkcje znalazły się w jednym pliku obj, dzięki temu linker (bez specjalnych opcji - data-sections, function-sections) ich nie usunie, co zapewni stałe adresy dla wszystkich aplikacji. To o ile się nie mylę zapewnia atrybut gcc combine. Możemy też usunąć linkowanie z libc (-nodefaultlibs) i zapewnić własną bibliotekę mającą potrzebne funkcje. To jest fajne jeśli tworzysz własny OS, bo możesz podmienić funkcje, potencjalnie problematyczne (np. malloc, free itd). Kolejna możliwość to parametr linkera --relocatable - umożliwia połączenie wielu polików obj w jeden, w ten sposób libc możesz przerobić na jeden plik obj, co zapobiegnie wywalaniu nieużywanych funkcji. Co ważne, nie wymaga rekompilacji libc, a jedynie częściowego linkowania libc.a. Inna możliwość to rekompilacja libc tak, aby każda funkcja była skompilowana z atrybutem used - w ten sposób zawsze znajdzie się w kodzie wynikowym i będziesz miał stałe adresy. IMHO akurat libc nie warto ruszać, bo jest krótka i często używana, lepiej więc pozwolić kompilatorowi na cyrki, kosztem nawet zwiększenia długości aplikacji. Natomiast warto się z pewnością w ten sposób zabawić z libprintf czy libm (jeśli nie mamy FPU).
  • #29 10782079
    Konto nie istnieje
    Konto nie istnieje  
  • #30 10863679
    przemekbary
    Poziom 16  
    Posty: 102
    Pomógł: 19
    Ocena: 7
    Witam
    A koprocesor CP15 i tablica translacji w ARM9?

Podsumowanie tematu

✨ W dyskusji poruszono temat realizacji wielowątkowości w kontekście systemów operacyjnych na architekturze ARM. Użytkownik zastanawia się nad możliwością uruchamiania skompilowanych programów z różnych adresów w pamięci, co wiąże się z problemem skoków i adresowania funkcji. Odpowiedzi wskazują, że skoki względne są możliwe, a kluczowym zagadnieniem są struktury danych oraz sposób zarządzania pamięcią. Wskazano na konieczność używania zmiennych lokalnych oraz na rolę zegarów i przerwań w kontekście przełączania kontekstu procesów. Dyskutowano również o możliwościach kompilacji z użyciem opcji -fPIC oraz o problemach związanych z linkowaniem funkcji z bibliotek. Wspomniano o Global Offset Table (GOT) oraz o konieczności relokacji segmentów pamięci. Uczestnicy podkreślili, że implementacja wymaga zrozumienia działania systemów operacyjnych i architektury ARM.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA