2012-08-10 16 views
6

Uczę się jądra Linux, ale nie wiem, jak przejść z trybu użytkownika do trybu jądra w systemie Linux. jak to działa? czy możesz dać mi jakąś radę lub podać mi link do niej, lub jakąś książkę na ten temat? dziękuję bardzo!Jak przejść z trybu użytkownika do trybu jądra?

+0

Jaki jest kontekst swoje pytanie? Pytasz o konkretne mechanizmy procesora na konkretnym procesorze lub ogólnie? Czy jest jakiś problem, który próbujesz rozwiązać? –

Odpowiedz

11

Jedynym sposobem aplikacja przestrzeń użytkownik może wyraźnie zainicjować przełącznik trybu jądra podczas normalnej pracy jest poprzez wywołanie systemowe, takie jak open, read, write itp

Ilekroć aplikacja użytkownik wywołuje te interfejsy wywołań systemowych z odpowiednimi parametrami uruchamiane jest przerwanie/wyjątek programowy (SWI).

W wyniku tego SWI kontrola wykonania kodu przechodzi z aplikacji użytkownika do predefiniowanej lokalizacji w tabeli wektora przerwań [IVT] dostarczonej przez system operacyjny.

Ten dokument IVT zawiera adres dla procedury obsługi wyjątku SWI, która wykonuje wszystkie niezbędne kroki wymagane do przełączenia aplikacji użytkownika do trybu jądra i rozpoczęcia wykonywania instrukcji jądra w imieniu procesu użytkownika.

+2

Niezupełnie. Na x86 każdy wyjątek pochodzący z trybu użytkownika przenosi kontrolę do odpowiedniej procedury obsługi wyjątków w systemie operacyjnym, w trybie jądra. –

+0

Prawda. Jak tylko opublikowałem swoją odpowiedź, chciałem ją edytować, co odzwierciedla fakt, że aplikacja użytkownika chce jawnie przejść do trybu jądra. Jednak starałem się to zrobić z powodu problemów z siecią. Zmieniliśmy to teraz, aby to odzwierciedlić. –

+0

@AmarnathRevanna W jaki sposób system operacyjny wie o tym, że w czasie obsługi SWI został przełączony na tryb jądra? Czy istnieje konkretny rejestr/bit sprzętu, który śledzi tryb, który ma być nadzorcą (ring 0)/user (ring 3) i jest aktualizowany na SWI? Zasadniczo, co zapewnia przejście do trybu użytkownika w trybie jądra na poziomie sprzętowym. – Shyam

0

Właśnie to przeczytałem i jest to całkiem niezły zasób. Wyjaśnia tryb użytkownika i tryb jądra, dlaczego zmiany zachodzą, jak drogie są i daje kilka interesujących lektur.

http://www.codinghorror.com/blog/2008/01/understanding-user-and-kernel-mode.html

Oto krótki fragment:

Kernel Tryb

w trybie jądra, kod wykonujący ma pełny i nieograniczony dostęp do warstwy sprzętowej. Może wykonać dowolną instrukcję CPU i odwołać się do dowolnego adresu pamięci. Tryb jądra jest zazwyczaj zarezerwowany dla najniżej zaufanych funkcji systemu operacyjnego. Awarie w trybie jądra są katastrofalne; zatrzymają cały komputer.

Tryb użytkownika

w trybie użytkownika, kod wykonujący ma możliwość bezpośredniego dostępu do sprzętu lub odniesienia pamięć. Kod działający w trybie użytkownika musi delegować do systemowych interfejsów API, aby uzyskać dostęp do sprzętu lub pamięci. Ze względu na ochronę zapewnianą przez tego rodzaju izolację, awarie w trybie użytkownika są zawsze możliwe do odzyskania. Większość kodu uruchomionego na twoim komputerze będzie działać w trybie użytkownika.

1

Aby przełączyć się z trybu użytkownika do trybu jądra, należy wykonać wywołanie systemowe.

Jeśli chcesz zobaczyć, co się dzieje pod maską, przejdź do TLDP is your new friend i zobacz kod (jest dobrze udokumentowany, nie ma potrzeby dodatkowej wiedzy, aby zrozumieć kod zespołu).

Jesteś zainteresowany:

movl $len,%edx   # third argument: message length 
    movl $msg,%ecx   # second argument: pointer to message to write 
    movl $1,%ebx    # first argument: file handle (stdout) 
    movl $4,%eax    # system call number (sys_write) 
    int  $0x80    # call kernel 

Jak widać, wywołanie system jest po prostu otoki wokół kodu montażu, który wykonuje przerwanie (0x80) iw rezultacie program obsługi tego wywołania systemowego będzie wezwany.

Oszukujmy trochę i użyj tutaj preprocesora C do zbudowania pliku wykonywalnego (foo.S jest plikiem, gdzie można umieścić kod z linku poniżej):

gcc -o foo -nostdlib foo.S 

go uruchomić poprzez strace aby upewnić się, że dostaniemy to, co piszemy:

$ strace -t ./foo 
09:38:28 execve("./foo", ["./foo"], 0x7ffeb5b771d8 /* 57 vars */) = 0 
09:38:28 stat(NULL, Hello, world! 
NULL)    = 14 
09:38:28 write(0, NULL, 14)  
Powiązane problemy