Jak działają systemy operacyjne… bez… systemu operacyjnego?


167

Jestem teraz bardzo ciekawy. Jestem programistą Python, a to pytanie mnie zaskoczyło: piszesz system operacyjny. Jak to działa? Trzeba go jakoś uruchomić, a ten sposób jest w innym systemie operacyjnym?

Jak aplikacja może działać bez systemu operacyjnego? Jak nakazać komputerowi uruchomienie, powiedzmy, C i wykonanie tych poleceń na ekranie, jeśli nie ma systemu operacyjnego do uruchomienia?

Czy ma to związek z jądrem UNIX? Jeśli tak, to co to jest jądro systemu Unix, czy ogólnie jądro?

Jestem pewien, że systemy operacyjne są bardziej skomplikowane, ale jak to działa?


14
Jestem całkiem pewien, że po to jest BIOS - to naprawdę mały system operacyjny, który uruchamia się w większym systemie operacyjnym.
sevenseacat

64
System operacyjny jest wygodny , ale nie jest potrzebny do uruchamiania programów na komputerze.
Andres F.

10
Możliwe jest nawet pisanie oprogramowania innego niż system operacyjny bez systemu operacyjnego. Wielu tłumaczy Forth tradycyjnie działało bez systemu operacyjnego (lub można powiedzieć, że były to systemy operacyjne). To nie jest nawet takie trudne. Jeśli znasz C, możesz czerpać przyjemność z pisania takiego programu (być może małej gry) jako ćwiczenia edukacyjnego.
Maks.

44
To zamieszanie jest jednym z kosztów cudownych, bezpiecznych i wysoce abstrakcyjnych systemów komputerowych, których używamy w dzisiejszych czasach: ludzie mogą być bardzo dobrymi i kompetentnymi programistami i nie znają nawet podstawowych zasad działania komputera. Jak nisko chcesz zejść? Dla bardzo niskich, ale wciąż powyżej fizyki, patrz Jak zaprogramowano pierwsze mikroprocesory? na Electronics.SE.
dmckee

2
Programowanie przeprowadzono przed wynalezieniem obecnej koncepcji systemu operacyjnego. Oczywiście coś na tym poziomie uruchamia system operacyjny. Systemy operacyjne są ładowane. Zazwyczaj jest to co najmniej wspomniane w czteroletnim programie CS, ponieważ większość z nich wymaga komputerowej teorii systemów operacyjnych.
Rig

Odpowiedzi:


263

Istnieje wiele stron internetowych, które przechodzą proces rozruchu (np. Jak uruchomić komputery ). Krótko mówiąc, jest to wieloetapowy proces, który stopniowo buduje system, aż w końcu będzie mógł rozpocząć procesy systemu operacyjnego.

Zaczyna się od oprogramowania układowego na płycie głównej, które próbuje uruchomić procesor. Następnie ładuje BIOS, który jest jak mini system operacyjny, który uruchamia drugi sprzęt. Po zakończeniu wyszukuje urządzenie rozruchowe (dysk, dysk CD itp.), A po znalezieniu lokalizuje MBR (główny rekord rozruchowy), ładuje go do pamięci i wykonuje. Jest to mały fragment kodu, który następnie wie, jak zainicjować i uruchomić system operacyjny (lub inne programy ładujące, ponieważ sprawy stały się bardziej skomplikowane). W tym momencie rzeczy takie jak jądro zostaną załadowane i zaczną działać.

To niesamowite, że w ogóle działa!


108
+1 za ostatnie zdanie.
CVn

39
Istnieje powód, który nazywa się „uruchamianiem”; termin ten jest skrótem od „bootstrapping”, jak w „ciągnięcie się za bootstraps”.
KeithS

5
Był czas, kiedy ktoś musiał wpisać lub przełączyć kod bootstrap. Czasami był to prosty skok do pierwszej instrukcji programu w pamięci ROM. Innym razem był to kod do odczytu z urządzenia i przeskocz do pierwszej instrukcji programu w odczytanych danych. Sprawy są teraz znacznie prostsze.
BillThor,


15
@BillThor: Gdzie przez „znacznie prostsze” rozumiesz oczywiście „znacznie bardziej skomplikowane”. Są po prostu prostsze w użyciu .
Raphael Schweikert

173

System operacyjny „goły” nie działa w niczym. Obsługuje pełny zestaw instrukcji na maszynie fizycznej i ma dostęp do całej pamięci fizycznej, wszystkich rejestrów urządzeń i wszystkich instrukcji uprzywilejowanych, w tym tych, które sterują sprzętem obsługującym pamięć wirtualną.

(Jeśli system operacyjny działa na maszynie wirtualnej, może wydawać się , że znajduje się w takiej samej sytuacji jak powyżej. Różnica polega na tym, że niektóre rzeczy są emulowane lub w inny sposób obsługiwane przez hiperwizora, tj. Poziom, na którym działają maszyny wirtualne. .)

W każdym razie, chociaż system operacyjny może być zaimplementowany w (na przykład) C, nie będzie miał do dyspozycji wszystkich normalnych bibliotek C. W szczególności nie będzie mieć normalnych bibliotek „stdio”. Zamiast tego zaimplementuje (na przykład) sterownik urządzenia dyskowego, który pozwala na odczyt i zapis bloków dysku. Zaimplementuje system plików na wierzchu warstwy bloków dyskowych, a ponadto zaimplementuje wywołania systemowe, które biblioteki wykonawcze aplikacji użytkownika wykonują (na przykład) w celu tworzenia, odczytu i zapisu plików ... i tak dalej.

Jak aplikacja może działać bez systemu operacyjnego?

Musi to być specjalny rodzaj aplikacji (np. System operacyjny), który wie, jak bezpośrednio współpracować ze sprzętem we / wy itp.

Jak nakazać komputerowi uruchomienie, powiedzmy, C i wykonanie tych poleceń na ekranie, jeśli nie ma systemu operacyjnego do uruchomienia?

Ty nie.

Aplikacja (która była argumentem napisanym w C) jest kompilowana i łączona na innym komputerze w celu uzyskania natywnego obrazu kodu. Następnie obraz jest zapisywany na dysku twardym w miejscu, w którym BIOS może go znaleźć. BIOS ładuje obraz do pamięci i wykonuje instrukcję, aby przejść do punktu wejścia aplikacji.

W aplikacji (zwykle) nie ma „uruchomionego C i wykonywania poleceń”, chyba że jest to w pełni funkcjonalny system operacyjny. W takim przypadku do systemu operacyjnego należy wdrożenie całej wymaganej infrastruktury, aby tak się stało. Bez magii. Tylko dużo kodu.

Odpowiedź Billa obejmuje ładowanie, czyli proces przejścia z wyłączonej maszyny na maszynę, na której działa normalny system operacyjny. Warto jednak zauważyć, że kiedy BIOS wykonuje swoje zadania, (zwykle) daje pełną kontrolę nad sprzętem głównemu systemowi operacyjnemu i nie odgrywa żadnej dalszej roli - aż do następnego uruchomienia systemu. Główny system operacyjny z pewnością nie działa w „BIOS” w konwencjonalnym sensie.

Czy ma to związek z jądrem UNIX? Jeśli tak, co to jest jądro unixowe, czy ogólnie jądro?

Tak.

Jądro UNIX jest rdzeniem systemu operacyjnego UNIX. Jest to część systemu UNIX, która wykonuje wszystkie opisane powyżej „elementy bez metalu”.

Idea „jądra” polega na tym, że próbujesz rozdzielić oprogramowanie systemowe na podstawowe rzeczy (które wymagają fizycznego dostępu do urządzenia, całej pamięci itp.) I inne niż podstawowe rzeczy. Jądro składa się z podstawowych rzeczy.

W rzeczywistości rozróżnienie między jądrem / rdzeniem a jądrem / rdzeniem jest bardziej skomplikowane. Dyskutowano o tym, co naprawdę należy do jądra, a co nie. (Wyszukaj na przykład mikro-jądro.)


6
Fenomenalna odpowiedź. W miarę możliwości dałbym wam jeszcze kilka pozytywnych opinii.
weberc2

7
Wiele dobrych odpowiedzi tutaj, więc dodam to jako komentarz, ponieważ nikt dotąd o tym nie wspominał: Jedną z kluczowych cech systemu operacyjnego jest umożliwienie wielu aplikacjom wykonywania „jednocześnie” z perspektywy użytkownika. Zdolność do planowania procesów i ochrony procesów przed wzajemną zmianą zachowania to zazwyczaj funkcje występujące tylko w systemie operacyjnym, a nie w oprogramowaniu układowym lub systemie BIOS.
Sean Barbeau

2
The idea of a "kernel" is that you try to separate the system software into core stuffŁatwo zapamiętać, zauważając, że termin kernelpochodzi z niemieckiego Kern, co oznacza rdzeń / jądro.
deed02392,

1
Uwielbiam tę odpowiedź tutaj, ponieważ wspomina, że ​​jest skompilowany i połączony kod binarny nie działa C.
Travis Pessetto,

3
„Odejście od tego uczyniło użytkowników komputerów mniej inteligentnymi”. - Nie mniej sprytny ... mniej umiejętności obsługi komputera. Można również powiedzieć, że zwiększyło to liczbę użytkowników komputerów PC.
Stephen C

62

Na początku procesor nie miał zasilania.

Mężczyzna powiedział: „niech będzie moc”, a procesor zaczął czytać z podanego adresu w pamięci i wykonać instrukcje tam zawarte. Potem następny i tak dalej, aż do końca mocy.

To był boot. Jego zadaniem było załadowanie innego oprogramowania, aby uzyskać dostęp do środowiska, w którym znajdowało się główne oprogramowanie, i załadowanie go.

Wreszcie przyjazny ekran zaprosił Cię do zalogowania.


58
Ta odpowiedź powinna zostać przeniesiona na christianity.stackexchange.com
Coomie

6
co to jest „dany adres”, skąd pochodzi. Przepraszamy za grę Charlesa Darwina tutaj.
Midhat

7
@Midhat - Pierwszy adres, który ma zostać pobrany przez procesor, jest wewnątrz niego wbudowany. Zazwyczaj jest to 0.
mouviciel

17
... A siódmego dnia Mężczyzna odpoczywał ze swoimi grami
Kanadyjczyk Łukasz

9
@mouviciel Adres w pamięci dotyczy 0x7C00dowolnej x86kompatybilnej architektury i najpierw musi zostać wypełniony przez BIOS, który zwykle ładuje pierwszy sektor dowolnego urządzenia rozruchowego, które preferuje ... Ładna odpowiedź: -7
Tobias Kienzler

29

Przepraszam za spóźnienie, ale opiszę to tak:

  • Płyta główna zyskuje moc.

  • Obwody czasowe uruchamiają się i stabilizują w razie potrzeby, wyłącznie na podstawie ich właściwości elektrycznych. Niektóre nowsze urządzenia mogą faktycznie używać bardzo ograniczonego mikroprocesora lub sekwencera.

    Należy zauważyć, że wiele rzeczy takich jak „układy czasowe uruchamiają się i stabilizują w razie potrzeby” tak naprawdę nie mają już miejsca w sprzęcie. Ogromną ilością tej pracy jest w rzeczywistości wyjątkowo specjalistyczne oprogramowanie działające na bardzo ograniczonych podprocesorach / sekwencerach.

    - jkerian o 5:20 25 października

  • Zasilanie jest dostarczane do procesora i pamięci RAM.

  • Procesor ładuje (w oparciu o wewnętrzne okablowanie) dane z systemu BIOS. Na niektórych komputerach BIOS może być dublowany do pamięci RAM, a następnie uruchamiany stamtąd, ale jest to rzadkie IIRC.

    Po włączeniu procesory zgodne z x86 zaczynają się pod adresem 0xFFFFFFF0 w przestrzeni adresowej ...

    -Micheal Steil, 17 błędów Microsoft popełnionych w systemie zabezpieczeń Xbox ( archiwum )

  • BIOS wykonuje połączenia z portami sprzętowymi i adresami używanymi przez płytę główną dla operacji dyskowych i innych sprzętowych operacji we / wy, a także obraca dyski i uruchamia resztę pamięci RAM.

  • Kod BIOS (poprzez ustawienia CMOS, przechowywany w sprzęcie) używa niskopoziomowych poleceń IDE lub SATA do odczytu sektora rozruchowego każdego dysku, w kolejności określonej przez CMOS lub zastąpienie menu przez użytkownika.

  • Pierwszy dysk z sektorem rozruchowym zostaje uruchomiony. Ten sektor rozruchowy to zestaw NTLDR, który zawiera instrukcje ładowania większej ilości danych z dysku, ładowania większych , późniejszych etapów GRUBitp.

  • Wreszcie kod maszynowy systemu operacyjnego jest wykonywany przez program ładujący, bezpośrednio lub pośrednio poprzez ładowanie łańcuchowe ładujące sektor rozruchowy z lokalizacji alternatywnej lub przesuniętej.

Wtedy panika zaprzyjaźnia się z jądrem, duszący się pingwin lub dysk zatrzymuje się z powodu wypadku głowy. =) W alternatywnym scenariuszu jądro konfiguruje tabele procesów, struktury w pamięci i montuje dyski, ładuje sterowniki, moduły oraz GUI lub zestaw usług (jeśli jest na serwerze). Następnie programy są wykonywane, gdy ich nagłówki są odczytywane, a ich zestaw jest wprowadzany do pamięci i odpowiednio mapowany.


2
Należy zauważyć, że wiele rzeczy, takich jak „obwody czasowe uruchamiają się i stabilizują, jeśli to konieczne”, tak naprawdę nie dzieje się już w sprzęcie. Ogromną ilością tej pracy jest tak naprawdę wyjątkowo specjalistyczne oprogramowanie działające na bardzo ograniczonych podprocesorach / sekwencerach. - Inżynier oprogramowania przyjaznego dla sąsiedztwa
Jkerian

@jkerian Czy masz coś przeciwko, że zacytowałem twój komentarz w moim poście?
ζ--

heh, wcale nie.
jkerian

BIOS nie jest systemem operacyjnym. BIOS jest skrótem podstawowy system wejścia / wyjścia, a to jest to, co robi BIOS. Umożliwia programistom korzystanie z zasobów niskiego poziomu ze sterownikami dostarczonymi przez producenta. Kiedy system operacyjny przechodzi w tryb chroniony (32-bitowy) lub długi (64-bitowy), system BIOS nie jest już dostępny, a system operacyjny korzysta z własnych sterowników, które w zasadzie zastępują funkcje zapewniane przez system BIOS na „niższych” poziomach. Nowoczesne systemy operacyjne, na przykład Linux i Windows, używają systemu BIOS tylko do wykrywania użytecznych sekcji pamięci RAM i ładowania własnego bardziej zaawansowanego modułu ładującego, który może załadować wymagane sterowniki.
Hannes Karppila

1
@ HannesKarppila Zaktualizowano; ma to teraz około czterech lat i nie jestem już aktywny na tej stronie.
ζ--

15

Istnieje wiele dobrych odpowiedzi, ale chciałem to dodać: Wspomniałeś, że pochodzisz z języka Python. Python jest językiem interpretowanym (lub „interpolowanym” lub dowolnym innym, przynajmniej w typowych przypadkach użycia CPython). Oznacza to, że masz inne oprogramowanie (interpreter języka Python), które patrzy na źródło i wykonuje je w jakiś sposób. Jest to dobry model i pozwala na całkiem niezłe języki wysokiego poziomu, dobrze oderwane od rzeczywistego sprzętu. Minusem jest to, że zawsze potrzebujesz najpierw tego oprogramowania tłumacza.

Takie oprogramowanie interpretera jest zwykle napisane w języku kompilującym się z kodem maszynowym, na przykład C lub C ++. Kod maszynowy jest tym, co CPU może obsłużyć. Procesor może jedynie odczytać niektóre bajty z pamięci iw zależności od wartości bajtów rozpocząć określoną operację. Tak więc jedna bajtowa sekwencja to polecenie, aby załadować niektóre dane z pamięci do rejestru, kolejna sekwencja, aby dodać dwie wartości, inna, aby zapisać wartość z rejestru z powrotem do pamięci głównej i wkrótce (rejestr jest specjalnym obszarem pamięci, który jest częścią procesora, w którym może działać najlepiej), większość tych poleceń jest dość niska na tym poziomie. Dla tych instrukcji kodu maszynowego czytelny dla człowieka jest kod asemblera. Zasadniczo ten kod maszynowy jest przechowywany w plikach .exe lub.com w systemie Windows lub w plikach binarnych Linux / Unix.

Teraz, gdy komputer jest uruchamiany, jest głupi, ma jednak pewne okablowanie, które czyta takie instrukcje kodu maszynowego. Na komputerze PC zwykle (obecnie) jest to układ EEPROM na płycie głównej zawierający BIOS (system wyjściowy BasicInput), ten system nie może wiele zrobić, może ułatwić dostęp do niektórych urządzeń itp., A następnie wykonać kluczową operację: przejdź do uruchom i skopiuj kilka pierwszych bajtów (czyli główny rekord rozruchowy, MBR) do pamięci, a następnie powiedz procesorowi „tutaj, masz program”, a następnie procesor potraktuje te bajty jako kod maszynowy i uruchomi go. Zazwyczaj jest to moduł ładujący system operacyjny, który załaduje jądro z niektórymi parametrami, a następnie przekaże sterowanie temu jądrem, które następnie załaduje cały jego sterownik, aby uzyskać dostęp do całego sprzętu, załadować jakiś program pulpitu lub powłoki lub cokolwiek innego i pozwolić użytkownikowi na zalogowanie się i użyj systemu.


6
„interpolowany”? Nigdy wcześniej nie słyszałem tego terminu.
Bryan Oakley,

3
Termin ten był używany około 5 lat temu, aby opisać „współczesnych” tłumaczy, którzy mają odrębną fazę kompilacji, która jest niezależna od wykonania. Nie mam pojęcia, czy ten termin przetrwał gdziekolwiek ;-)
John

1
„ninterpreted”? Nigdy wcześniej nie słyszałem tego terminu.
Cole Johnson

12

Pytasz „Jak aplikacja może działać bez systemu operacyjnego”. Łatwa odpowiedź brzmi: „OS nie jest aplikacją”. Chociaż system operacyjny można utworzyć za pomocą tych samych narzędzi co aplikacja i zbudować z tego samego surowca, nie są one tym samym. System operacyjny nie musi grać według tych samych zasad co aplikacja.

OTOH, rzeczywisty sprzęt i oprogramowanie sprzętowe można traktować jako „system operacyjny”, w którym działa „aplikacja” systemu operacyjnego. Sprzęt jest bardzo prostym systemem operacyjnym - umie uruchamiać instrukcje zapisane w kodzie maszynowym i wie, że po uruchomieniu powinien sprawdzić bardzo konkretny adres pamięci dla swojej pierwszej instrukcji. Tak więc uruchamia się, a następnie natychmiast uruchamia tę pierwszą instrukcję, a następnie drugą i tak dalej.

Tak więc system operacyjny to po prostu kod maszynowy, który istnieje w znanej lokalizacji i który może bezpośrednio wchodzić w interakcje ze sprzętem.


1
+1 Myślę, że to najlepsza odpowiedź. Jeśli chodzi o abstrakty, myślę, że przybijacie je na właściwych poziomach.
Preet Sangha,

6

Odpowiedź na twoje pytanie wymaga wiedzy o tym, jak wygląda kod natywny (dla procesora) i jak jest interpretowany przez procesor.

Zwykle cały proces kompilacji opiera się na tłumaczeniu rzeczy, które piszesz w C, Pascalu, a nawet Pythonie (za pomocą pypy) i C # na rzeczy rozumiane przez procesor, tj. Proste instrukcje, takie jak „przechowuj coś pod [adres pamięci]”, „dodaj liczby przechowywane pod rejestrem eax i ebx ”,„ funkcja wywołania foo ”,„ porównaj eax do 10 ”. Te instrukcje, wykonywane jeden po drugim, robią rzeczy, które chcesz zrobić ze swoim kodem.

Pomyśl o tym: tak naprawdę nie potrzebujesz systemu operacyjnego, aby wykonać ten natywny kod! Wystarczy załadować ten kod do pamięci i powiedzieć procesorowi, że tam jest, i chcesz go wykonać. Ale nie przejmuj się tym zbytnio. Właśnie o to BIOS powinien się martwić - ładuje twój kod (tylko jeden i jeden sektor), zaraz po uruchomieniu CPU, pod fizycznym adresem 0x7C00. Następnie procesor zaczyna wykonywać ten jeden sektor (512 B) kodu. I możesz robić, co sobie wyobrażasz! Bez żadnego wsparcia ze strony systemu operacyjnego. To dlatego, że TY jesteś systemem operacyjnym. Fajne hę? Bez standardowej biblioteki, bez doładowania, bez Pythona, bez programów, bez sterowników! Musisz napisać wszystko sam.

A jak komunikujesz się ze sprzętem? Masz dwie możliwości:

  1. Pozostajesz w „trybie rzeczywistym” - trybie wykonywania procesora z zaledwie 1 MB pamięci (a nawet mniej), bez zaawansowanych funkcji procesora, takich jak rozszerzenia procesora, ochrona pamięci, wielozadaniowość; 16-bitowy kod wykonywalny, starożytny tryb adresowania ... Ale z niektórymi procedurami zapewnianymi przez BIOS, w tym prostym wyjściem ekranu, obsługą klawiatury, we / wy dysku i zarządzaniem energią. Jednym słowem powracasz do czasów MS-DOS i 16-bitowych procesorów.
  2. Przejdziesz do „Trybu chronionego” ze wszystkimi funkcjami twojego procesora, całą zainstalowaną pamięcią i tak dalej. Ale w trybie chronionym jesteś całkowicie sam i musisz zrobić WSZYSTKO samodzielnie (i komunikujesz się ze sprzętem za pomocą instrukcji „wejściowych” i „wyjściowych”, aby wprowadzić / wyprowadzić dane do portów we / wy i użyć przerwań). / O). Czy muszę powiedzieć, że każdy system operacyjny od Windows 95 i od pierwszego Linuksa wybiera tę opcję?

Teraz pytasz, co to jest jądro. Krótko mówiąc, jądro to wszystko, czego nie widzisz i czego bezpośrednio nie doświadczasz. Zarządza, wraz ze sterownikami, wszystkim, od klawiatury po prawie każdy element sprzętu w komputerze. Komunikujesz się z nim za pomocą powłoki graficznej lub terminala. Lub funkcje w twoim kodzie, teraz wykonane, na szczęście, z obsługą systemu operacyjnego.

Dla lepszego zrozumienia mogę dać ci jedną radę: spróbuj napisać własny system operacyjny. Nawet jeśli ma napisać „Witaj świecie” na ekranie.


3

Istnieją pewne różnice w działaniu systemu operacyjnego, które są bardzo zależne od systemu. Aby system był użyteczny, musi mieć pewne przewidywalne zachowanie podczas uruchamiania, takie jak „rozpocznij wykonywanie pod adresem X”. W przypadku systemów, które mają nieulotną pamięć (taką jak pamięć Flash) zamapowaną w przestrzeni programów, jest to dość łatwe, ponieważ wystarczy upewnić się, że umieścisz kod startowy w odpowiednim miejscu w przestrzeni programu procesora. Jest to niezwykle powszechne w przypadku mikrokontrolerów. Niektóre systemy muszą pobrać swoje programy startowe z innej lokalizacji przed ich uruchomieniem. W tych systemach niektóre operacje będą na stałe (lub prawie na stałe). Istnieje kilka procesorów, które pobierają kod startowy przez i2c z innego układu,

Systemy korzystające z rodziny procesorów x86 zwykle używają wieloetapowego procesu rozruchu, który jest dość złożony ze względu na jego ewolucję i problemy ze zgodnością wsteczną. System wykonuje oprogramowanie wewnętrzne (zwane BIOS - Basic Input / Output System lub podobne), które znajduje się w pewnej nieulotnej pamięci na płycie głównej. Czasami część lub całość tego oprogramowania układowego jest kopiowana (przenoszona) do pamięci RAM, aby przyspieszyć jej działanie. Ten kod został napisany ze świadomością, jaki sprzęt będzie obecny i nadaje się do rozruchu.

Startowe oprogramowanie układowe jest zwykle pisane z założeniami o tym, jaki sprzęt będzie obecny w systemie. Wiele lat temu na maszynie 286 prawdopodobnie istniałoby założenie, że będzie istniał kontroler napędu dyskietek pod adresem We / Wy X i ładowałby sektor 0 do określonego miejsca w pamięci, gdyby otrzymał pewien zestaw poleceń (i kod w sektorze 0 wie, jak korzystać z własnych funkcji BIOS-u, aby załadować więcej kodu, a następnie załadować wystarczającą ilość kodu, aby był to system operacyjny) Na mikrokontrolerze może być założenie, że istnieje port szeregowy działający z pewnymi ustawieniami, że powinien czekać na polecenia (w celu zaktualizowania bardziej skomplikowanego oprogramowania układowego) przez X czasu przed kontynuowaniem procesu rozruchu.

Dokładny proces uruchamiania danego systemu nie jest dla Ciebie tak ważny, jak świadomość, że różni się on w różnych systemach, ale także, że wszystkie mają ze sobą wiele wspólnego. Często w kodzie startowym (bootstrapping), gdy trzeba wykonać operacje we / wy, urządzenia we / wy są odpytywane, a nie polegają na przerwaniach. Wynika to z faktu, że przerwania są złożone, używaj pamięci RAM stosu (która może nie być jeszcze w pełni skonfigurowana) i nie musisz się martwić blokowaniem innych operacji, gdy jesteś jedyną operacją.

Po pierwszym załadowaniu jądro systemu operacyjnego (jądro jest główną częścią większości systemów operacyjnych) początkowo będzie działać podobnie jak oprogramowanie układowe. Będzie trzeba go zaprogramować ze znajomością lub odkryć obecny sprzęt, ustawić pamięć RAM jako przestrzeń stosu, wykonać różne testy, skonfigurować różne struktury danych, ewentualnie odkryć i zamontować system plików, a następnie prawdopodobnie uruchomić program, który jest bardziej jak programy, do których przywykłeś pisać (program, który polega na obecności systemu operacyjnego).

Kod systemu operacyjnego jest zwykle zapisywany w kombinacji C i asemblera. Pierwszy kod dla jądra systemu operacyjnego jest prawdopodobnie zawsze w asemblerze i wykonuje takie czynności, jak konfigurowanie stosu, na którym opiera się kod C, a następnie wywołuje funkcję C. Będą tam również inne odręczne asemblery, ponieważ niektóre operacje, które musi wykonać system operacyjny, często nie są wyrażalne w języku C (takie jak przełączanie kontekstu / zamiana stosów). Często należy przekazać specjalne kompilatory do kompilatora C, aby poinformować go, że nie należy polegać na standardowych bibliotekach używanych przez większość programów w języku C i nie oczekiwać, że istniejeint main(int argc, char *argv[])w programie. Dodatkowo należy użyć specjalnych opcji linkera, których większość programistów aplikacji nigdy nie używa. Może to spowodować, że program jądra będzie oczekiwał na załadowanie pod określonym adresem lub skonfiguruje rzeczy, które wyglądają tak, jakby w niektórych lokalizacjach były zmienne zewnętrzne, chociaż te zmienne nigdy nie zostały zadeklarowane w żadnym kodzie C (jest to przydatne w przypadku operacji we / wy mapowanych w pamięci lub inne specjalne lokalizacje pamięci).

Cała operacja na początku wydaje się magią, ale po przyjrzeniu się jej i zrozumieniu, magia staje się tylko zestawem programów, których wdrożenie wymaga dużo więcej planowania i wiedzy systemowej. Debugowanie ich wymaga jednak magii.


3

Aby zrozumieć, jak działają systemy operacyjne, pomocne może być podzielenie ich na dwie kategorie: te, które po prostu dostarczają usługi aplikacjom na żądanie, oraz te, które używają funkcji sprzętowych w CPU, aby uniemożliwić aplikacjom wykonywanie czynności, których nie powinny. MS-DOS był w dawnym stylu; wszystkie wersje systemu Windows od wersji 3.0 były tym drugim stylem (przynajmniej gdy działa coś potężniejszego niż 8086).

Oryginalny komputer IBM z systemem PC-DOS lub MS-DOS byłby przykładem dawnego stylu „OS”. Gdyby aplikacja chciała wyświetlić postać na ekranie, byłoby na to kilka sposobów. Może wywołać procedurę, która prosi MS-DOS o wysłanie go na „standardowe wyjście”. Gdyby to zrobił, MS-DOS sprawdziłby, czy dane wyjściowe były przekierowywane, a jeśli nie, wywołałby procedurę przechowywaną w pamięci ROM (w zbiorze procedur nazywanych przez system Basic Input / Output System), która wyświetli znak przesuń kursor i przesuń kursor („napisz teletype”) Ta procedura BIOS zapisuje następnie parę bajtów gdzieś w zakresie od 0xB800: 0 do 0xB800: 3999; sprzęt karty graficznej Color wielokrotnie pobiera pary bajtów w tym zakresie, używając pierwszego bajtu z każdej pary, aby wybrać kształt znaku, a drugiego, aby wybrać kolory pierwszego planu i tła. Bajty są pobierane i przetwarzane na sygnały czerwony, zielony i niebieski w sekwencji zapewniającej czytelny tekst.

Programy na komputerze IBM mogą wyświetlać tekst przy użyciu procedury „standardowego wyjścia” DOS lub przy użyciu procedury BIOS „zapisu typu teletekstu” lub zapisując go bezpośrednio w pamięci wyświetlacza. Wiele programów, które musiały wyświetlać dużo tekstu, szybko wybrało to drugie podejście, ponieważ może być dosłownie setki razy szybsze niż korzystanie z procedur DOS. Nie było tak, ponieważ procedury DOS i BIOS były wyjątkowo nieefektywne; chyba że wyświetlacz był wygaszony, można go było zapisać tylko w określonych momentach. Procedura BIOS wyprowadzania znaku została zaprojektowana tak, aby można go było wywołać w dowolnym momencie; każde żądanie musiało więc zacząć od nowa, czekając na odpowiedni czas na wykonanie operacji zapisu. Natomiast kod aplikacji, który wiedział, co powinien zrobić, mógł zorganizować się wokół dostępnych możliwości napisania wyświetlacza.

Kluczową kwestią jest to, że podczas gdy DOS i BIOS zapewniały sposób wyświetlania tekstu na wyświetlaczu, nie było nic szczególnie „magicznego” w takich umiejętnościach. Aplikacja, która chciała napisać tekst na wyświetlaczu, mogłaby to zrobić równie skutecznie, przynajmniej jeśli sprzęt wyświetlacza działałby zgodnie z oczekiwaniami aplikacji (jeśli ktoś zainstalował Monochromatyczny adapter ekranu, który był podobny do CGA, ale miał pamięć znaków znajdujący się pod 0xB000: 0000-0xB000: 3999), BIOS automatycznie wyprowadzał tam znaki; aplikacja, która została zaprogramowana do pracy z MDA lub CGA, mogłaby to również zrobić, ale aplikacja, która została zaprogramowana tylko dla CGA, byłaby całkowicie bezużyteczna na MDA.

W nowszych systemach sytuacja wygląda nieco inaczej. Procesory mają różne tryby „uprawnień”. Zaczynają w najbardziej uprzywilejowanym trybie, w którym kod może robić wszystko, co chce. Następnie mogą przejść do trybu ograniczonego, w którym dostępne są tylko wybrane zakresy pamięci lub urządzenia we / wy. Kod nie może przejść bezpośrednio z trybu ograniczonego z powrotem do trybu uprzywilejowanego, ale procesor zdefiniował punkty wejścia w trybie uprzywilejowanym, a kod trybu ograniczonego może poprosić procesor o uruchomienie kodu w jednym z tych punktów wejścia w trybie uprzywilejowanym. Ponadto istnieją punkty wejścia w trybie uprzywilejowanym związane z wieloma operacjami, które byłyby zabronione w trybie ograniczonym. Załóżmy na przykład, że ktoś chciał uruchomić wiele aplikacji MS-DOS jednocześnie, każda z nich ma własny ekran. Gdyby aplikacje mogły pisać bezpośrednio do kontrolera wyświetlania pod 0xB800: 0, nie byłoby sposobu, aby jedna aplikacja nie nadpisała ekranu innej aplikacji. Z drugiej strony, system operacyjny może uruchomić aplikację w trybie ograniczonym i przechwycić dowolny dostęp do pamięci wyświetlacza; jeśli odkryje, że aplikacja, która miała znajdować się w „tle”, próbuje zapisać 0xB800: 160, może zapisać dane w pewnej pamięci, którą odłożyła jako bufor ekranu aplikacji w tle. Jeśli ta aplikacja zostanie później przełączona na pierwszy plan, bufor można następnie skopiować na prawdziwy ekran. system operacyjny może uruchomić aplikację w trybie ograniczonym i zablokować dowolny dostęp do pamięci ekranu; jeśli odkryje, że aplikacja, która miała znajdować się w „tle”, próbuje zapisać 0xB800: 160, może zapisać dane w pewnej pamięci, którą odłożyła jako bufor ekranu aplikacji w tle. Jeśli ta aplikacja zostanie później przełączona na pierwszy plan, bufor można następnie skopiować na prawdziwy ekran. system operacyjny może uruchomić aplikację w trybie ograniczonym i zablokować dowolny dostęp do pamięci ekranu; jeśli odkryje, że aplikacja, która miała znajdować się w „tle”, próbuje zapisać 0xB800: 160, może zapisać dane w pewnej pamięci, którą odłożyła jako bufor ekranu aplikacji w tle. Jeśli ta aplikacja zostanie później przełączona na pierwszy plan, bufor można następnie skopiować na prawdziwy ekran.

Najważniejsze rzeczy do zapamiętania to (1), chociaż często przydatne jest posiadanie standardowego zestawu procedur do wykonywania różnych standardowych usług, takich jak wyświetlanie tekstu, nie robią nic, czego nie mogła zrobić aplikacja działająca w „trybie uprzywilejowanym” jeśli został odpowiednio zaprogramowany do obsługi zainstalowanego sprzętu; (2) chociaż większość działających dzisiaj aplikacji byłaby uniemożliwiana przez ich system operacyjny bezpośrednio wykonując takie operacje wejścia / wyjścia, program, który uruchamia się w trybie uprzywilejowanym, robi wszystko, co chce, i może skonfigurować dowolne reguły dla trybu ograniczonego programy.


2

Jak powiedział Stephen C., nie chodzi tylko o uruchomienie systemu operacyjnego, ale także o to, jak działa, współpracuje ze sprzętem i oprogramowaniem na nim.

Dodam tylko do jego odpowiedzi, że możesz rzucić okiem na „Elementy systemów obliczeniowych” . Jest to książka i niektóre narzędzia, które wyjaśniają interakcje komputera, systemu operacyjnego i kompilatorów. Unikalną cechą tego narzędzia jest to, że zapewnia narzędzia do bardzo szybkiego opracowania własnego systemu operacyjnego w symulowanym środowisku, ignorując wiele szczegółów wymaganych w prawdziwym systemie, dzięki czemu można zrozumieć pojęcia . Świetnie sobie radzi, pozwalając zobaczyć las zamiast drzew.

Jeśli chcesz dowiedzieć się więcej na temat interakcji systemu operacyjnego ze sprzętem, sprawdź Minix .


1

Piszesz system operacyjny. Trzeba go jakoś uruchomić, a ten sposób jest w innym systemie operacyjnym?

Twoja aplikacja działa w systemie operacyjnym. Ten system operacyjny zapewnia obsługę aplikacji, np. Otwieranie pliku i zapisywanie w nim bajtów. Usługi te są zwykle świadczone za pośrednictwem wywołań systemowych.

System operacyjny działa na sprzęcie. Sprzęt zapewnia usługi dla systemu operacyjnego, takie jak ustawianie szybkości transmisji portu szeregowego i zapisywanie w nim bajtów. Usługi te są zazwyczaj świadczone za pośrednictwem rejestrów mapowanych w pamięci lub portów I / O.


Aby podać bardzo uproszczony przykład tego, jak to działa:

Twoja aplikacja mówi systemowi operacyjnemu, aby napisał coś do pliku. Do aplikacji system operacyjny udostępnia pojęcia takie jak pliki i katalogi.

Na sprzęcie te pojęcia nie istnieją. Sprzęt zapewnia pojęcia takie jak dyski podzielone na stałe bloki 512 bajtów. System operacyjny decyduje, których bloków użyć dla pliku, a także niektórych innych bloków metadanych, takich jak nazwa pliku, rozmiar i lokalizacja na dysku. Następnie mówi sprzętowi: zapisz te 512 bajtów do sektora o tym numerze na dysku o tym numerze; zapisz te 512 512 bajtów do sektora o tym innym numerze na dysku o tym samym numerze; i tak dalej.

Sposób, w jaki system operacyjny mówi sprzętowi, że jest bardzo zróżnicowany. Jedną z funkcji systemu operacyjnego jest ochrona aplikacji przed tymi różnicami. Na przykład na dysku na jednym sprzęcie system operacyjny musiałby zapisać numer dysku i sektora na porcie we / wy, a następnie zapisać bajty jeden po drugim na osobnym porcie we / wy. Na innym sprzęcie system operacyjny musiałby skopiować całe 512 bajtów sektora do obszaru pamięci, zapisać lokalizację tego obszaru pamięci w specjalnej lokalizacji pamięci oraz zapisać dysk i numer sektora na jeszcze innym specjalna lokalizacja pamięci.


Dzisiejszy sprzęt wysokiej klasy jest niezwykle skomplikowany. Instrukcje zawierające wszystkie szczegóły dotyczące programowania są odbojnikami z tysiącami stron; na przykład najnowsza instrukcja obsługi procesora Intel obejmuje siedem tomów, w sumie ponad 4000 stron - i to tylko dla procesora. Większość innych komponentów ujawnia bloki pamięci lub porty I / O, które system operacyjny może nakazać procesorowi mapować na adresy w przestrzeni adresowej. Kilka z tych komponentów ujawnia jeszcze więcej rzeczy za kilkoma portami I / O lub adresami pamięci; na przykład RTC (zegar czasu rzeczywistego, komponent, który utrzymuje czas komputera, gdy jest on wyłączony) odsłania kilkaset bajtów pamięci za parą portów I / O, i jest to bardzo prosty komponent pochodzący z oryginalny PC / AT. Rzeczy takie jak dyski twarde mają całe oddzielne procesory, z którym system operacyjny rozmawia za pomocą standardowych poleceń. Procesory graficzne są jeszcze bardziej skomplikowane.

Kilka osób w powyższych komentarzach zasugerowało Arduino. Zgadzam się z nimi, o wiele łatwiej jest to zrozumieć - ATmega328, który robi wszystko w Arduino Uno, z wyjątkiem odsłonięcia złącza USB jako portu szeregowego, ma instrukcję z zaledwie kilkuset stron. Na Arduino działasz bezpośrednio na sprzęcie, bez żadnego systemu operacyjnego pomiędzy; tylko kilka małych procedur bibliotecznych, których nie musisz używać, jeśli nie chcesz.


1

Przykłady możliwe do uruchomienia

Z technicznego punktu widzenia program działający bez systemu operacyjnego to system operacyjny. Zobaczmy więc, jak stworzyć i uruchomić kilka maleńkich systemów operacyjnych witaj na świecie.

Kod wszystkich poniższych przykładów znajduje się w tym repozytorium GitHub .

Sektor rozruchowy

Na x86 najprostszym i najniższym poziomem, co możesz zrobić, jest utworzenie głównego sektora rozruchowego (MBR) , który jest rodzajem sektora rozruchowego , a następnie zainstalowanie go na dysku.

Tutaj tworzymy jedną za pomocą jednego printfpołączenia:

printf '\364%509s\125\252' > main.img
sudo apt-get install qemu-system-x86
qemu-system-x86_64 -hda main.img

Wynik:

wprowadź opis zdjęcia tutaj

Testowane na Ubuntu 18.04, QEMU 2.11.1.

main.img zawiera następujące elementy:

  • \364in octal == 0xf4in hex: kodowanie hltinstrukcji, która mówi CPU, aby przestał działać.

    Dlatego nasz program nic nie zrobi: zacznij i zatrzymaj.

    Używamy ósemki, ponieważ \xliczby szesnastkowe nie są określone przez POSIX.

    Możemy łatwo uzyskać to kodowanie za pomocą:

    echo hlt > a.asm
    nasm -f bin a.asm
    hd a
    

    ale 0xf4kodowanie jest również udokumentowane w podręczniku Intela.

  • %509swyprodukuj 509 miejsc. Konieczne do wypełnienia pliku do bajtu 510.

  • \125\252in octal ==, 0x55po którym następuje 0xaa: magiczne bajty wymagane przez sprzęt. Muszą to być bajty 511 i 512.

    Jeśli nie jest obecny, sprzęt nie będzie traktował tego jako dysku rozruchowego.

Pamiętaj, że nawet bez robienia kilku znaków jest już wydrukowanych na ekranie. Są one drukowane przez oprogramowanie układowe i służą do identyfikacji systemu.

Uruchom na prawdziwym sprzęcie

Emulatory są fajne, ale sprzęt to prawdziwa okazja.

Zauważ jednak, że jest to niebezpieczne i możesz pomyłkowo wyczyścić dysk: rób to tylko na starych komputerach, które nie zawierają krytycznych danych! Lub jeszcze lepiej, devboardy takie jak Raspberry Pi, patrz przykład ARM poniżej.

W przypadku typowego laptopa musisz zrobić coś takiego:

  • Wypal obraz na pamięci USB (zniszczy twoje dane!):

    sudo dd if=main.img of=/dev/sdX
    
  • podłącz USB do komputera

  • włącz to

  • każ mu uruchomić z USB.

    Oznacza to, że oprogramowanie układowe wybiera USB przed dyskiem twardym.

    Jeśli nie jest to domyślne zachowanie twojego komputera, po włączeniu naciskaj Enter, F12, ESC lub inne takie dziwne klawisze, aż pojawi się menu rozruchu, w którym możesz wybrać rozruch z USB.

    Często w tych menu można skonfigurować kolejność wyszukiwania.

Na przykład na moim starym Lenovo Thinkpad T430, UEFI BIOS 1.16 widzę:

Witaj świecie

Teraz, gdy stworzyliśmy minimalny program, przejdźmy do cześć świata.

Oczywiste pytanie brzmi: jak zrobić IO? Kilka opcji:

  • poproś oprogramowanie układowe, np. BIOS lub UEFI, aby zrobiło to dla nas
  • VGA: specjalny region pamięci, który zostanie wydrukowany na ekranie, jeśli zostanie zapisany. Może być używany w trybie chronionym.
  • napisz sterownik i porozmawiaj bezpośrednio ze sprzętem wyświetlającym. Jest to „właściwy” sposób na zrobienie tego: mocniejszy, ale bardziej złożony.
  • port szeregowy . Jest to bardzo prosty znormalizowany protokół, który wysyła i pobiera znaki z terminala hosta.

    Źródło .

    Niestety nie jest narażony na większość współczesnych laptopów, ale jest powszechną drogą do tworzenia płyt deweloperskich, patrz przykłady ARM poniżej.

    To naprawdę szkoda, ponieważ takie interfejsy są naprawdę przydatne na przykład do debugowania jądra Linuksa .

  • użyj funkcji debugowania układów. ARM na przykład nazywa ich semihosting . Na prawdziwym sprzęcie wymaga dodatkowej obsługi sprzętu i oprogramowania, ale na emulatorach może być bezpłatną wygodną opcją. Przykład .

Tutaj zrobimy przykład BIOS-u, ponieważ jest prostszy na x86. Pamiętaj jednak, że nie jest to najbardziej niezawodna metoda.

sieć elektryczna

.code16
    mov $msg, %si
    mov $0x0e, %ah
loop:
    lodsb
    or %al, %al
    jz halt
    int $0x10
    jmp loop
halt:
    hlt
msg:
    .asciz "hello world"

link.ld

SECTIONS
{
    . = 0x7c00;
    .text :
    {
        __start = .;
        *(.text)
        . = 0x1FE;
        SHORT(0xAA55)
    }
}

Złóż i połącz z:

gcc -c -g -o main.o main.S
ld --oformat binary -o main.img -T linker.ld main.o

Wynik:

wprowadź opis zdjęcia tutaj

Testowane na: Lenovo Thinkpad T430, UEFI BIOS 1.16. Dysk wygenerowany na hoście Ubuntu 18.04.

Oprócz standardowych instrukcji montażu dla użytkownika, mamy:

  • .code16: informuje GAS, aby wyprowadził 16-bitowy kod

  • cli: wyłącz przerwania programowe. Mogą one spowodować, że procesor zacznie ponownie działać pohlt

  • int $0x10: wykonuje połączenie BIOS. To właśnie drukuje znaki jeden po drugim.

Ważne flagi linków to:

  • --oformat binary: wypisuje nieprzetworzony kod binarnego zestawu, nie wypaczaj go w pliku ELF, jak ma to miejsce w przypadku zwykłych plików wykonywalnych dla użytkownika

Użyj C zamiast montażu

Ponieważ C kompiluje się w asemblerze, używanie C bez standardowej biblioteki jest dość proste, w zasadzie potrzebujesz:

  • skrypt linkera, aby umieścić rzeczy w pamięci we właściwym miejscu
  • flagi, które mówią GCC, aby nie korzystał ze standardowej biblioteki
  • mały punkt wejścia zespołu, który ustawia wymagany stan C main, w szczególności:
    • stos
    • zerować BSS

DO ZROBIENIA: link, więc przykład x86 na GitHub. Oto ARM, który stworzyłem .

Sprawa staje się jeszcze przyjemniejsza, jeśli chcesz korzystać ze standardowej biblioteki, ponieważ nie mamy jądra Linux, które implementuje większość standardowych funkcji biblioteki C za pośrednictwem POSIX .

Kilka możliwości, bez przechodzenia na w pełni funkcjonalny system operacyjny, taki jak Linux, to:

RAMIĘ

W ARM ogólne pomysły są takie same. Przesłałem:

W przypadku Raspberry Pi https://github.com/dwelch67/raspberrypi wygląda jak najpopularniejszy dostępny obecnie samouczek.

Niektóre różnice w stosunku do x86 obejmują:

  • IO odbywa się poprzez bezpośrednie pisanie na magiczne adresy, nie ma instrukcji ini outinstrukcji.

    Nazywa się to We / Wy mapowanym na pamięć .

  • w przypadku niektórych prawdziwych urządzeń, takich jak Raspberry Pi, możesz samodzielnie dodać oprogramowanie układowe (BIOS) do obrazu dysku.

    To dobrze, ponieważ sprawia, że ​​aktualizacja oprogramowania układowego jest bardziej przejrzysta.

Oprogramowanie układowe

W rzeczywistości sektor rozruchowy nie jest pierwszym oprogramowaniem działającym na procesorze systemu.

Najpierw działa tak zwane oprogramowanie układowe , które jest oprogramowaniem:

  • wykonane przez producentów sprzętu
  • zwykle zamknięte źródło, ale prawdopodobnie oparte na C.
  • przechowywane w pamięci tylko do odczytu, a zatem trudniejsze / niemożliwe do modyfikacji bez zgody dostawcy.

Dobrze znane oprogramowanie wewnętrzne obejmuje:

  • BIOS : stare, wszechstronne oprogramowanie x86. SeaBIOS jest domyślną implementacją open source używaną przez QEMU.
  • UEFI : następca systemu BIOS, lepiej ustandaryzowany, ale bardziej wydajny i niesamowicie rozdęty.
  • Coreboot : szlachetna próba otwartego oprogramowania typu cross arch

Oprogramowanie wewnętrzne działa na przykład:

  • zapętlaj każdy dysk twardy, USB, sieć itp., aż znajdziesz coś rozruchowego.

    Kiedy uruchamiamy QEMU, -hdamówi, że main.imgjest to dysk twardy podłączony do sprzętu i

    hda jest pierwszą próbą i jest używana.

  • załaduj pierwsze 512 bajtów na adres pamięci RAM 0x7c00, umieść tam RIP procesora i pozwól mu działać

  • pokaż na ekranie takie rzeczy jak menu startowe lub wywołania drukowania BIOS-u

Oprogramowanie układowe oferuje funkcje podobne do systemu operacyjnego, od których zależy większość systemów operacyjnych. Np. Podzestaw Python został przeniesiony do działania w systemie BIOS / UEFI: https://www.youtube.com/watch?v=bYQ_lq5dcvM

Można argumentować, że oprogramowanie układowe jest nierozróżnialne od systemów operacyjnych i że oprogramowanie układowe jest jedynym „prawdziwym” programowaniem bez systemu operacyjnego.

Jak to ujął to deweloper CoreOS :

Trudna część

Po włączeniu komputera układy scalone (mostek północny, mostek południowy i SuperIO) nie są jeszcze poprawnie zainicjowane. Mimo że ROM ROM BIOS jest tak daleko od procesora, jak to możliwe, jest on dostępny dla procesora, ponieważ tak musi być, w przeciwnym razie procesor nie miałby instrukcji do wykonania. Nie oznacza to, że pamięć ROM systemu BIOS jest całkowicie zmapowana, zwykle nie. Ale tylko tyle jest zmapowane, aby rozpocząć proces rozruchu. Wszelkie inne urządzenia, po prostu zapomnij.

Po uruchomieniu Coreboot w QEMU możesz eksperymentować z wyższymi warstwami Coreboot i ładunkami, ale QEMU oferuje niewiele możliwości eksperymentowania z kodem startowym niskiego poziomu. Po pierwsze, pamięć RAM działa od samego początku.

Stan początkowy po BIOS

Podobnie jak wiele rzeczy w sprzęcie, standaryzacja jest słaba, a jedną z rzeczy, na których nie należy polegać, jest stan początkowy rejestrów, gdy kod zaczyna działać po BIOS.

Więc zrób sobie przysługę i użyj kodu inicjalizacji, takiego jak: https://stackoverflow.com/a/32509555/895245

Rejestruje się %dsi %esma ważne skutki uboczne, więc powinieneś je wyzerować, nawet jeśli nie używasz ich wyraźnie.

Zauważ, że niektóre emulatory są ładniejsze niż prawdziwy sprzęt i zapewniają dobry stan początkowy. Potem, gdy idziesz na prawdziwym sprzęcie, wszystko się psuje.

GNU GRUB Multiboot

Sektory rozruchowe są proste, ale nie są zbyt wygodne:

  • możesz mieć tylko jeden system operacyjny na dysk
  • kod ładowania musi być naprawdę mały i zmieścić się w 512 bajtach. Można to rozwiązać za pomocą wewnętrznego wywołania BIOS 0x13 .
  • musisz sam dużo uruchomić, na przykład przejść do trybu chronionego

Z tych powodów GNU GRUB stworzył wygodniejszy format pliku o nazwie multiboot.

Minimalny przykład działania: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/hello-world

Używam go również w moim repozytorium przykładów GitHub, aby móc z łatwością uruchamiać wszystkie przykłady na prawdziwym sprzęcie bez milionowego spalania USB. Na QEMU wygląda to tak:

wprowadź opis zdjęcia tutaj

Jeśli przygotujesz system operacyjny jako plik z wieloma uruchomieniami, GRUB będzie mógł go znaleźć w zwykłym systemie plików.

To właśnie robi większość dystrybucji, umieszczając obrazy systemu operacyjnego /boot.

Pliki Multiboot są w zasadzie plikiem ELF ze specjalnym nagłówkiem. Są one określone przez GRUB pod adresem : https://www.gnu.org/software/grub/manual/multiboot/multiboot.html

Możesz zmienić plik z wieloma uruchomieniami na dysk rozruchowy za pomocą grub-mkrescue.

El Torito

Format, który można wypalić na płytach CD: https://en.wikipedia.org/wiki/El_Torito_%28CD-ROM_standard%29

Możliwe jest również utworzenie obrazu hybrydowego działającego na ISO lub USB. Można to zrobić za pomocą grub-mkrescue( przykład ), a także przy make isoimageużyciu jądra Linux isohybrid.

Zasoby

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.