Jaka jest różnica między przestrzenią jądra a przestrzenią użytkownika? Czy przestrzeń jądra, wątki jądra, procesy jądra i stos jądra oznaczają to samo? Dlaczego potrzebujemy tego zróżnicowania?
Jaka jest różnica między przestrzenią jądra a przestrzenią użytkownika? Czy przestrzeń jądra, wątki jądra, procesy jądra i stos jądra oznaczają to samo? Dlaczego potrzebujemy tego zróżnicowania?
Odpowiedzi:
Bardzo uproszczona odpowiedź jest taka, że jądro działa w przestrzeni jądra, a normalne programy działają w przestrzeni użytkownika. Przestrzeń użytkownika jest w zasadzie formą piaskownicy - ogranicza programy użytkownika, aby nie mogły zepsuć pamięci (i innych zasobów) należących do innych programów lub jądra systemu operacyjnego. Ogranicza to (ale zwykle nie całkowicie eliminuje) ich zdolność do robienia złych rzeczy, takich jak awarie maszyny.
Jądro jest rdzeniem systemu operacyjnego. Zwykle ma pełny dostęp do całej pamięci i sprzętu maszyny (i wszystkiego innego na komputerze). Aby maszyna była jak najbardziej stabilna, zwykle chcesz, aby tylko najbardziej zaufany, dobrze przetestowany kod działał w trybie jądra / w przestrzeni jądra.
Stos jest po prostu kolejną częścią pamięci, więc naturalnie jest on oddzielony wraz z resztą pamięci.
Random Access Memory (RAM) może być logicznie podzielone na dwa odrębne regiony tj. - w przestrzeni jądra i przestrzeni użytkownika ( The fizyczne adresy pamięci RAM nie są faktycznie podzielone tylko wirtualne adresy , wszystko to realizowane przez MMU )
Jądro działa w uprawnionej do tego części pamięci. Ta część pamięci nie może być dostępna bezpośrednio przez procesy zwykłych użytkowników, podczas gdy jądro może uzyskać dostęp do wszystkich części pamięci. Aby uzyskać dostęp do niektórych części jądra, procesy użytkownik musiał użyć predefiniowany układ połączeń tj open
, read
, write
itd. Ponadto, C
funkcje biblioteczne, takie jak printf
wezwanie wywołania systemowego write
z kolei.
Wywołania systemowe działają jako interfejs między procesami użytkownika a procesami jądra. Prawa dostępu są umieszczane w przestrzeni jądra, aby uniemożliwić użytkownikom nieświadome manipulowanie jądrem.
Tak więc, gdy pojawia się wywołanie systemowe, do jądra wysyłane jest przerwanie programowe. CPU może tymczasowo przekazać sterowanie do powiązanej procedury obsługi przerwań. Proces jądra, który został zatrzymany przez przerwanie, zostaje wznowiony po zakończeniu działania procedury obsługi przerwań.
Przestrzeń jądra i przestrzeń wirtualna to pojęcia pamięci wirtualnej… nie oznacza to, że Ram (twoja rzeczywista pamięć) jest podzielony na jądro i przestrzeń użytkownika. Każdy proces otrzymuje pamięć wirtualną, która jest podzielona na jądro i przestrzeń użytkownika.
Mówiąc to: „Pamięć o dostępie swobodnym (RAM) można podzielić na dwa odrębne obszary, a mianowicie - przestrzeń jądra i przestrzeń użytkownika”. jest źle.
& odnośnie kwestii "przestrzeń jądra a przestrzeń użytkownika"
Kiedy proces jest tworzony, a jego pamięć wirtualna jest podzielona na przestrzeń użytkownika i przestrzeń jądra, gdzie obszar przestrzeni użytkownika zawiera dane, kod, stos, stertę procesu, a przestrzeń jądra zawiera takie rzeczy, jak tablica stron procesu , struktury danych jądra i kod jądra itp. Aby uruchomić kod przestrzeni jądra, sterowanie musi przejść do trybu jądra (używając przerwania programowego 0x80 dla wywołań systemowych), a stos jądra jest zasadniczo współdzielony między wszystkimi procesami aktualnie wykonywanymi w przestrzeni jądra.
Pierścienie procesora są najbardziej wyraźnym rozróżnieniem
W trybie chronionym x86 procesor jest zawsze w jednym z 4 pierścieni. Jądro Linuksa używa tylko 0 i 3:
Jest to najtrudniejsza i najszybsza definicja jądra i przestrzeni użytkownika.
Dlaczego Linux nie używa pierścieni 1 i 2: Pierścienie uprawnień procesora: Dlaczego pierścienie 1 i 2 nie są używane?
Jak jest określany obecny pierścień?
Aktualny dzwonek jest wybierany przez kombinację:
globalna tablica deskryptorów: tablica wpisów GDT w pamięci, a każdy wpis ma pole, Privl
które koduje pierścień.
Instrukcja LGDT ustawia adres na bieżącą tablicę deskryptorów.
Zobacz także: http://wiki.osdev.org/Global_Descriptor_Table
rejestry segmentu CS, DS itp., które wskazują indeks wpisu w GDT.
Na przykład CS = 0
oznacza, że pierwszy wpis GDT jest obecnie aktywny dla kodu wykonawczego.
Co może zrobić każdy pierścionek?
Układ procesora jest fizycznie zbudowany tak, że:
ring 0 może zrobić wszystko
pierścień 3 nie może uruchomić kilku instrukcji i zapisać do kilku rejestrów, w szczególności:
nie może zmienić własnego pierścienia! W przeciwnym razie może ustawić się na dzwonek 0, a pierścienie byłyby bezużyteczne.
Innymi słowy, nie może modyfikować deskryptora bieżącego segmentu , który określa bieżący pierścień.
nie można modyfikować tabel stron: Jak działa stronicowanie x86?
Innymi słowy, nie może modyfikować rejestru CR3, a samo stronicowanie zapobiega modyfikowaniu tabel stron.
Dzięki temu jeden proces nie widzi pamięci innych procesów ze względów bezpieczeństwa / łatwości programowania.
nie można zarejestrować programów obsługi przerwań. Są one konfigurowane przez zapisywanie w lokalizacjach pamięci, czemu zapobiega również stronicowanie.
Programy obsługi działają w pierścieniu 0 i złamałyby model zabezpieczeń.
Innymi słowy, nie może używać instrukcji LGDT i LIDT.
nie mogą wykonywać instrukcji IO, takich jak in
i out
, a zatem mają arbitralny dostęp do sprzętu.
W przeciwnym razie, na przykład, uprawnienia do plików byłyby bezużyteczne, gdyby jakikolwiek program mógł bezpośrednio czytać z dysku.
Dokładniej dzięki Michaelowi Petchowi : w rzeczywistości system operacyjny może zezwolić na instrukcje IO na pierścieniu 3, jest to w rzeczywistości kontrolowane przez segment stanu zadania .
Nie jest możliwe, aby pierścień 3 udzielił sobie na to pozwolenia, jeśli w ogóle go nie miał.
Linux zawsze tego zabrania. Zobacz też: Dlaczego Linux nie używa sprzętowego przełączania kontekstu za pośrednictwem TSS?
W jaki sposób programy i systemy operacyjne przechodzą między pierścieniami?
kiedy procesor jest włączony, zaczyna uruchamiać program początkowy w pierścieniu 0 (no cóż, ale jest to dobre przybliżenie). Możesz myśleć, że ten program początkowy jest jądrem (ale zwykle jest to program ładujący, który następnie wywołuje jądro nadal w pierścieniu 0 ).
kiedy proces użytkownika chce, aby jądro zrobiło coś dla niego, na przykład zapis do pliku, używa instrukcji, która generuje przerwanie, takie jak int 0x80
lub,syscall
aby zasygnalizować jądro. x86-64 Linux syscall hello world przykład:
.data
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
.text
.global _start
_start:
/* write */
mov $1, %rax
mov $1, %rdi
mov $hello_world, %rsi
mov $hello_world_len, %rdx
syscall
/* exit */
mov $60, %rax
mov $0, %rdi
syscall
skompiluj i uruchom:
as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out
Kiedy tak się dzieje, CPU wywołuje procedurę obsługi wywołania zwrotnego przerwania, którą jądro zarejestrowało podczas uruchamiania. Oto konkretny przykład baremetalu, który rejestruje program obsługi i używa go .
Ten program obsługi działa w pierścieniu 0, który decyduje, czy jądro zezwoli na to działanie, wykona akcję i zrestartuje program przestrzeni użytkownika w pierścieniu 3. x86_64
gdy exec
używane jest wywołanie systemowe (lub gdy jądro się uruchamia/init
), jądro przygotowuje rejestry i pamięć nowego procesu użytkownika, a następnie przeskakuje do punktu wejścia i przełącza procesor na pierścień 3
Jeśli program próbuje zrobić coś niegrzecznego, jak zapis do zabronionego rejestru lub adresu pamięci (z powodu stronicowania), procesor wywołuje również program obsługi wywołań zwrotnych jądra w pierścieniu 0.
Ale ponieważ obszar użytkownika był niegrzeczny, jądro może tym razem zabić proces lub dać mu ostrzeżenie za pomocą sygnału.
Kiedy jądro uruchamia się, ustawia zegar sprzętowy z pewną stałą częstotliwością, która okresowo generuje przerwania.
Ten zegar sprzętowy generuje przerwania, które uruchamiają pierścień 0 i pozwalają mu zaplanować, które procesy użytkownika mają się wybudzić.
W ten sposób planowanie może się odbywać nawet wtedy, gdy procesy nie wykonują żadnych wywołań systemowych.
Jaki jest sens posiadania wielu dzwonków?
Istnieją dwie główne zalety oddzielenia jądra od obszaru użytkownika:
Jak się tym bawić?
Stworzyłem konfigurację gołego metalu, która powinna być dobrym sposobem na bezpośrednie manipulowanie pierścieniami: https://github.com/cirosantilli/x86-bare-metal-examples
Niestety nie miałem cierpliwości, aby stworzyć przykład przestrzeni użytkownika, ale posunąłem się do konfiguracji stronicowania, więc przestrzeń użytkownika powinna być wykonalna. Bardzo chciałbym zobaczyć prośbę o wycofanie.
Alternatywnie, moduły jądra Linuksa działają w pierścieniu 0, więc możesz ich użyć do wypróbowania uprzywilejowanych operacji, np. Odczytu rejestrów kontrolnych: Jak uzyskać dostęp do rejestrów kontrolnych cr0, cr2, cr3 z programu? Uzyskanie błędu segmentacji
Oto wygodna konfiguracja QEMU + Buildroot, aby wypróbować ją bez zabijania hosta.
Wadą modułów jądra jest to, że inne kthreads działają i mogą przeszkadzać w twoich eksperymentach. Ale teoretycznie możesz przejąć wszystkie programy obsługi przerwań swoim modułem jądra i posiadać system, to byłby właściwie interesujący projekt.
Pierścienie ujemne
Chociaż w podręczniku Intela nie ma odniesień do pierścieni ujemnych, w rzeczywistości istnieją tryby procesora, które mają większe możliwości niż sam pierścień 0, więc dobrze pasują do nazwy „pierścień ujemny”.
Jednym z przykładów jest tryb hiperwizora używany w wirtualizacji.
Aby uzyskać więcej informacji, patrz:
RAMIĘ
W ARM pierścienie nazywane są zamiast tego poziomami wyjątków, ale główne pomysły pozostają takie same.
Istnieją 4 poziomy wyjątków w ARMv8, powszechnie używane jako:
EL0: obszar użytkownika
EL1: jądro („nadzorca” w terminologii ARM).
Wprowadzono z svc
instrukcją (wywołanie SuperVisor), wcześniej znaną jako swi
przed ujednoliconym asemblacją , która jest instrukcją używaną do wykonywania wywołań systemu Linux. Witaj, świecie, przykład ARMv8:
przywitania
.text
.global _start
_start:
/* write */
mov x0, 1
ldr x1, =msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
Przetestuj z QEMU na Ubuntu 16.04:
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-as -o hello.o hello.S
arm-linux-gnueabihf-ld -o hello hello.o
qemu-arm hello
Oto konkretny przykład baremetalu, który rejestruje program obsługi SVC i wywołuje SVC .
EL2: hiperwizory , na przykład Xen .
Wprowadzono z hvc
instrukcją (połączenie HyperVisor).
Hiperwizor jest dla systemu operacyjnego, czym system operacyjny dla obszaru użytkownika.
Na przykład Xen pozwala na jednoczesne uruchamianie wielu systemów operacyjnych, takich jak Linux lub Windows w tym samym systemie, i izoluje systemy operacyjne od siebie w celu zapewnienia bezpieczeństwa i łatwości debugowania, tak jak Linux robi to w przypadku programów w przestrzeni użytkownika.
Hiperwizory są kluczową częścią dzisiejszej infrastruktury chmurowej: pozwalają wielu serwerom działać na jednym sprzęcie, utrzymując zużycie sprzętu na poziomie bliskim 100% i oszczędzając dużo pieniędzy.
Na przykład AWS używał Xen do 2017 roku, kiedy jego przejście na KVM pojawiło się w wiadomościach .
EL3: kolejny poziom. Przykład TODO.
Wprowadzono z smc
instrukcją (połączenie w trybie bezpiecznym)
ARMv8 Architektura Model referencyjny DDI 0487C.a - Rozdział D1 - na poziomie systemu AArch64 programisty Model - Rysunek D1-1 ilustruje to pięknie:
Sytuacja ARM zmieniła się nieco wraz z pojawieniem się rozszerzeń hosta wirtualizacji ARMv8.1 (VHE) . To rozszerzenie umożliwia wydajne działanie jądra w EL2:
VHE zostało stworzone, ponieważ rozwiązania wirtualizacji w jądrze Linuksa, takie jak KVM, zyskały przewagę nad Xen (patrz np. Przejście AWS na KVM wspomniane powyżej), ponieważ większość klientów potrzebuje tylko maszyn wirtualnych z systemem Linux i, jak możesz sobie wyobrazić, wszystko w jednym projekt KVM jest prostszy i potencjalnie bardziej wydajny niż Xen. Więc teraz jądro Linuksa-hosta działa w takich przypadkach jako hiperwizor.
Zwróć uwagę, że ARM, być może z perspektywy czasu, ma lepszą konwencję nazewnictwa poziomów uprawnień niż x86, bez potrzeby stosowania poziomów ujemnych: 0 oznacza niższy, a 3 najwyższy. Wyższe poziomy są zwykle tworzone częściej niż niższe.
Bieżący EL można zapytać za pomocą MRS
instrukcji: jaki jest bieżący tryb wykonywania / poziom wyjątku itp.?
ARM nie wymaga obecności wszystkich poziomów wyjątków, aby umożliwić implementacje, które nie wymagają funkcji oszczędzania obszaru chipa. ARMv8 „Poziomy wyjątków” mówi:
Implementacja może nie obejmować wszystkich poziomów wyjątków. Wszystkie implementacje muszą zawierać EL0 i EL1. EL2 i EL3 są opcjonalne.
Na przykład QEMU domyślnie ustawia się na EL1, ale EL2 i EL3 można włączyć za pomocą opcji wiersza poleceń: qemu-system-aarch64 wpisuje el1 podczas emulacji zasilania a53
Fragmenty kodu przetestowane na Ubuntu 18.10.
Przestrzeń jądra i przestrzeń użytkownika to oddzielenie uprzywilejowanych funkcji systemu operacyjnego i zastrzeżonych aplikacji użytkownika. Oddzielenie jest konieczne, aby uniemożliwić aplikacjom użytkownika przeszukiwanie komputera. Byłoby źle, gdyby jakikolwiek stary program użytkownika mógł zacząć zapisywać losowe dane na dysku twardym lub czytać pamięć z przestrzeni pamięci innego programu użytkownika.
Programy w przestrzeni użytkownika nie mają bezpośredniego dostępu do zasobów systemowych, więc dostęp jest obsługiwany w imieniu programu przez jądro systemu operacyjnego. Programy przestrzeni użytkownika zazwyczaj wysyłają takie żądania do systemu operacyjnego za pośrednictwem wywołań systemowych.
Wątki jądra, procesy, stos nie oznaczają tego samego. Są analogicznymi konstrukcjami dla przestrzeni jądra, jak ich odpowiedniki w przestrzeni użytkownika.
Każdy proces ma własne 4 GB pamięci wirtualnej, która jest mapowana na pamięć fizyczną za pomocą tabel stron. Pamięć wirtualna jest w większości podzielona na dwie części: 3 GB na potrzeby procesu i 1 GB na potrzeby jądra. Większość tworzonych zmiennych znajduje się w pierwszej części przestrzeni adresowej. Ta część nazywa się przestrzenią użytkownika. Ostatnia część to miejsce, w którym znajduje się jądro i jest ono wspólne dla wszystkich procesów. Nazywa się to przestrzenią jądra i większość tej przestrzeni jest odwzorowywana na początkowe lokalizacje pamięci fizycznej, w których obraz jądra jest ładowany podczas rozruchu.
Maksymalny rozmiar przestrzeni adresowej zależy od długości rejestru adresowego w CPU.
W systemach z 32-bitowymi rejestrami adresowymi maksymalny rozmiar przestrzeni adresowej wynosi 2 32 bajty lub 4 GiB. Podobnie w systemach 64-bitowych można zaadresować 2 64 bajty.
Taka przestrzeń adresowa nazywana jest pamięcią wirtualną lub wirtualną przestrzenią adresową . W rzeczywistości nie jest to związane z fizycznym rozmiarem pamięci RAM.
Na platformach Linux wirtualna przestrzeń adresowa jest podzielona na przestrzeń jądra i przestrzeń użytkownika.
Stała specyficzna dla architektury zwana limitem rozmiaru zadania lub TASK_SIZE
oznacza miejsce, w którym następuje podział:
zakres adresów od 0 do TASK_SIZE
-1 jest przydzielany do przestrzeni użytkownika;
reszta z TASK_SIZE
maksymalnie 2 32 -1 (lub 2 64 -1) jest przydzielana do przestrzeni jądra.
Na przykład w konkretnym systemie 32-bitowym 3 GiB może być zajęte na przestrzeń użytkownika i 1 GiB na przestrzeń jądra.
Każda aplikacja / program w uniksopodobnym systemie operacyjnym jest procesem; każdy z nich ma unikalny identyfikator zwany identyfikatorem procesu (lub po prostu identyfikatorem procesu , tj. PID). Linux zapewnia dwa mechanizmy tworzenia procesu: 1. fork()
wywołanie systemowe lub 2. exec()
wywołanie.
Wątek jądra to lekki proces, a także program w trakcie wykonywania. Pojedynczy proces może składać się z kilku wątków udostępniających te same dane i zasoby, ale przebiegających różnymi ścieżkami przez kod programu. Linux udostępnia clone()
wywołanie systemowe do generowania wątków.
Przykładowe zastosowania wątków jądra to: synchronizacja danych w pamięci RAM, pomoc harmonogramowi w dystrybucji procesów między procesorami itp.
W skrócie: jądro działa w przestrzeni jądra, przestrzeń jądra ma pełny dostęp do całej pamięci i zasobów, można powiedzieć, że pamięć jest podzielona na dwie części, część dla jądra i część dla własnego procesu użytkownika, (przestrzeń użytkownika) uruchamia normalne programy, użytkownik space nie może uzyskać bezpośredniego dostępu do przestrzeni jądra, więc żąda od jądra użycia zasobów. przez syscall (predefiniowane wywołanie systemowe w glibc)
jest stwierdzenie, które upraszcza różne „ Przestrzeń użytkownika to tylko testowe obciążenie jądra ” ...
Dla jasności: architektura procesora pozwala procesorowi działać w dwóch trybach, trybie jądra i trybie użytkownika , instrukcja sprzętowa umożliwia przełączanie z jednego trybu do drugiego.
pamięć może być oznaczona jako część przestrzeni użytkownika lub jądra.
Kiedy procesor działa w trybie użytkownika, procesor może uzyskać dostęp tylko do pamięci znajdującej się w przestrzeni użytkownika, podczas gdy procesor próbuje uzyskać dostęp do pamięci w przestrzeni jądra, wynikiem jest „wyjątek sprzętowy”, gdy procesor działa w trybie jądra, procesor ma bezpośredni dostęp do przestrzeni jądra i przestrzeni użytkownika ...
Przestrzeń jądra oznacza, że przestrzeń pamięci może zostać dotknięta tylko przez jądro. W 32-bitowym Linuksie jest to 1G (od 0xC0000000 do 0xffffffff jako adres pamięci wirtualnej) Każdy proces tworzony przez jądro jest również wątkiem jądra, więc dla jednego procesu są dwa stosy: jeden stos w przestrzeni użytkownika dla tego procesu i drugi w jądrze miejsce na wątek jądra.
stos jądra zajmował 2 strony (8k w 32-bitowym Linuksie), zawiera task_struct (około 1k) i prawdziwy stos (około 7k). Ta ostatnia jest używana do przechowywania niektórych zmiennych automatycznych lub parametrów wywołań funkcji lub adresu funkcji w funkcjach jądra. Oto kod (Processor.h (linux \ include \ asm-i386)):
#define THREAD_SIZE (2*PAGE_SIZE)
#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
#define free_task_struct(p) free_pages((unsigned long) (p), 1)
__get_free_pages (GFP_KERNEL, 1)) oznacza alokację pamięci jako 2 ^ 1 = 2 strony.
Ale stos procesu to inna sprawa, jego adres jest poniżej 0xC0000000 (32-bitowy linux), jego rozmiar może być znacznie większy, używany do wywołań funkcji przestrzeni użytkownika.
Więc tutaj pojawia się pytanie do wywołania systemowego, działa w przestrzeni jądra, ale został wywołany przez proces w przestrzeni użytkownika, jak to działa? Czy linux umieści swoje parametry i adres funkcji w stosie jądra lub stosie procesów? Rozwiązanie Linuksa: wszystkie wywołania systemowe są wyzwalane przez przerwanie oprogramowania INT 0x80. Zdefiniowano we wpisie S (linux \ arch \ i386 \ kernel), oto kilka linii, na przykład:
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
.long SYMBOL_NAME(sys_close)
Przez Sunil Yadav, na Quora:
Jądro Linuksa odnosi się do wszystkiego, co działa w trybie jądra i składa się z kilku odrębnych warstw. W najniższej warstwie jądro współdziała ze sprzętem za pośrednictwem warstwy HAL. Na średnim poziomie jądro UNIX jest podzielone na 4 odrębne obszary. Pierwszy z czterech obszarów dotyczy urządzeń znakowych, surowego i gotowanego TTY oraz obsługi terminala. Drugi obszar obsługuje sterowniki urządzeń sieciowych, protokoły routingu i gniazda. Trzeci obszar obejmuje sterowniki urządzeń dyskowych, pamięci podręczne stron i buforów, system plików, pamięć wirtualną, nazewnictwo i mapowanie plików. Czwarty i ostatni obszar zajmuje się wysyłaniem, planowaniem, tworzeniem i kończeniem procesów, a także obsługą sygnałów. Przede wszystkim mamy górną warstwę jądra, która zawiera wywołania systemowe, przerwania i pułapki. Ten poziom służy jako interfejs dla każdej z funkcji niższego poziomu. Programista używa różnych wywołań systemowych i przerwań do interakcji z funkcjami systemu operacyjnego.
IN krótka przestrzeń jądra to część pamięci, w której działa jądro systemu Linux (górne 1 GB przestrzeni wirtualnej w przypadku systemu Linux), a przestrzeń użytkownika to część pamięci, w której działa aplikacja użytkownika (dolne 3 GB pamięci wirtualnej w przypadku systemu Linux. chcesz dowiedzieć się więcej, zobacz link podany poniżej :)
http://learnlinuxconcepts.blogspot.in/2014/02/kernel-space-and-user-space.html
Próbuję podać bardzo uproszczone wyjaśnienie
Pamięć wirtualna jest podzielona na przestrzeń jądra i przestrzeń użytkownika. Przestrzeń jądra to obszar pamięci wirtualnej, w którym będą działać procesy jądra, a przestrzeń użytkownika to obszar pamięci wirtualnej, w którym będą działać procesy użytkownika.
Podział ten jest wymagany do ochrony dostępu do pamięci.
Za każdym razem, gdy bootloader uruchamia jądro po załadowaniu go do lokalizacji w pamięci RAM (zwykle na kontrolerze opartym na ARM), musi się upewnić, że kontroler jest w trybie nadzorcy z wyłączonymi FIQ i IRQ.
Przestrzeń jądra i przestrzeń użytkownika to przestrzenie logiczne.
Większość nowoczesnych procesorów jest zaprojektowana do pracy w innym trybie uprzywilejowanym. Maszyny x86 mogą działać w 4 różnych trybach uprzywilejowanych.
A konkretna instrukcja maszynowa może być wykonana w / powyżej określonego trybu uprzywilejowanego.
Dzięki temu projektowi zapewniasz ochronę systemu lub środowisko wykonawcze.
Jądro to fragment kodu, który zarządza sprzętem i zapewnia abstrakcję systemu. Dlatego musi mieć dostęp do wszystkich instrukcji maszyny. Jest to najbardziej zaufany program. Więc powinienem zostać stracony z najwyższym przywilejem. I poziom Pierścień 0 jest najbardziej tryb uprzywilejowany. Więc poziom pierścienia 0 jest również nazywany trybem jądra .
Aplikacje użytkownika to oprogramowanie pochodzące od dowolnego zewnętrznego dostawcy i nie można im całkowicie ufać. Ktoś ze złymi zamiarami może napisać kod powodujący awarię systemu, gdyby miał pełny dostęp do wszystkich instrukcji maszynowych. Dlatego aplikacja powinna mieć dostęp do ograniczonego zestawu instrukcji. I poziom dzwonka 3 to najmniej uprzywilejowany tryb. Więc wszystkie aplikacje działają w tym trybie. Stąd ten poziom pierścienia 3 jest również nazywany trybem użytkownika .
Uwaga: Nie otrzymuję poziomów pierścienia 1 i 2. Są to w zasadzie tryby z uprawnieniami pośrednimi. Może więc kod sterownika urządzenia jest wykonywany z tym uprawnieniem. AFAIK, linux używa tylko Ring Level 0 i 3 odpowiednio do wykonywania kodu jądra i aplikacji użytkownika.
Zatem każda operacja wykonywana w trybie jądra może być traktowana jako przestrzeń jądra. Każda operacja wykonywana w trybie użytkownika może być traktowana jako przestrzeń użytkownika.
Prawidłowa odpowiedź brzmi: Nie ma czegoś takiego jak przestrzeń jądra i przestrzeń użytkownika. Zestaw instrukcji procesora ma specjalne uprawnienia do ustawiania destrukcyjnych elementów, takich jak katalog główny mapy tabeli stron, dostęp do pamięci urządzenia itp.
Kod jądra ma najwyższe uprawnienia, a kod użytkownika najniższe. Zapobiega to awarii systemu przez kod użytkownika, modyfikowaniem innych programów itp.
Ogólnie kod jądra jest przechowywany pod inną mapą pamięci niż kod użytkownika (tak jak przestrzenie użytkownika są przechowywane w innych mapach pamięci niż inne). Stąd pochodzą terminy „przestrzeń jądra” i „przestrzeń użytkownika”. Ale to nie jest twarda i szybka zasada. Na przykład, ponieważ x86 pośrednio wymaga, aby jego programy obsługi przerwań / pułapek były mapowane przez cały czas, część (lub wszystkie niektóre systemy operacyjne) jądra muszą być odwzorowane w przestrzeni użytkownika. Ponownie, nie oznacza to, że taki kod ma uprawnienia użytkownika.
Dlaczego konieczne jest dzielenie jądra / użytkownika? Niektórzy projektanci nie zgadzają się, że jest to w rzeczywistości konieczne. Architektura mikrojądra opiera się na założeniu, że najbardziej uprzywilejowane sekcje kodu powinny być tak małe, jak to tylko możliwe, a wszystkie istotne operacje wykonywane są w kodzie uprzywilejowanym użytkownika. Trzeba by przestudiować, dlaczego jest to dobry pomysł, nie jest to prosta koncepcja (i słynie zarówno z zalet, jak i wad).
Pamięć podzielona jest na dwa odrębne obszary:
Procesy działające w przestrzeni użytkownika mają dostęp tylko do ograniczonej części pamięci, podczas gdy jądro ma dostęp do całej pamięci. Procesy działające w przestrzeni użytkownika również nie mają dostępu do przestrzeni jądra. Procesy przestrzeni użytkownika mogą uzyskać dostęp tylko do niewielkiej części jądra za pośrednictwem interfejsu udostępnionego przez jądro - wywołania systemowe.Jeśli proces wykonuje wywołanie systemowe, do jądra wysyłane jest przerwanie programowe, które następnie wysyła odpowiednią obsługę przerwań i kontynuuje jego praca po zakończeniu obsługi.
W Linuksie są dwie spacje, pierwsza to przestrzeń użytkownika, a druga to przestrzeń jądra. przestrzeń użytkownika składa się tylko z aplikacji użytkownika, które chcesz uruchomić. jako usługa jądra istnieje zarządzanie procesami, zarządzanie plikami, obsługa sygnałów, zarządzanie pamięcią, zarządzanie wątkami i jest tam obecnych wiele usług. Jeśli uruchamiasz aplikację z przestrzeni użytkownika, ta aplikacja współdziała tylko z usługą jądra. i ta usługa współdziała ze sterownikiem urządzenia, który jest obecny między sprzętem a jądrem. Główną zaletą oddzielenia przestrzeni jądra i przestrzeni użytkownika jest to, że możemy zapewnić ochronę przez wirus.bcaz wszystkich aplikacji użytkownika obecnych w przestrzeni użytkownika, a usługa jest obecna w przestrzeni jądra. dlatego Linux nie wpływa na wirusa.