Do spisu treści tematu 3

Algorytm exec

Spis treści


Wprowadzenie

Procedury exec* zmieniają kontekst poziomu użytkownika danego procesu na podstawie programu wykonywalnego umieszczonego w pliku dyskowym. Tym samym, statyczny kod, jakim jest program na dysku, staje się dynamicznym, działającym w pamięci operacyjnej, procesem. Wywołania funkcji  execlp, execvp, execl, execv, execle, execve,  różniące się składniowo, wywołują ostatecznie funkcję do_execve z pliku exec.c.
sp

Algorytm funkcji do_execve

sp

Przenoszenie napisów

Napisy w pamięci jądra

Zanim jądro usunie z pamięci kod procesu wolającego do_execve oraz jego dane, musi zapamiętać argumenty wywołania i zmienne środowiska (a.w. i z.ś.). Do tego celu służy tablica page oraz wskaźnik p. Tablica page jest tablicą stron, do których kopiowane sa a.w. i z.ś. Strony te przydzielane są od końca dynamicznie, w trakcie kopiowania, tzn. początkowa część tablicy page nie odpowiada żadnym stronom. Zmienna p wskazuje na pierwszą przydzieloną już stronę, a w jej obrębie - ostatni wolny adres (p/PAGE_SIZE i p%PAGE_SIZE). Jądro trzyma wszystkie napisy obok siebie pooddzielane zerami. Ponadto pamiętana jest liczba a.w. i z.ś. Na tej podstawie można potem odtworzyć tablicę a.w. i tak wlaśnie dzieje się w rzeczywistości. Strony z page dołączane są do pamięci nowego procesu na końcu jego przestrzeni adresowej. Łącznie na stronach indeksowanych tablicą page mieści sie 128kB napisów, co wydaje sie być wielkoscią wystarczającą.
 

Kopiowanie napisów

Za kopiowanie napisów z tablicy napisów na strony page odpowiada funkcja copy_strings. Algorytm jej jest prosty: W ten sposób postępujemy ze wszystkimi napisami z tablicy.

Należy zwrócić tu uwagę na jeden dodatkowy szczegół. Funkcja copy_strings obsługuje zasadniczo 3 różne sytuacje:

Osiąga się to przez warunkowe przypisania fs:=ds.
 

Algorytm setup_arg_pages

Funkcja setup_arg_pages przyłącza strony z page do przestrzeni adresowej użytkownika, na samym jej końcu: W przypadku, gdy nie uda się przydzielić struktury vm_area_struct (brak pamięci), strony page są zwalniane.
mm

Kontrola - prepare_binprm

W funkcji prepare_binprm przeprowadzana jest kontrola możliwości wykonania danego pliku przez proces i ustawienie niektórych pól struktury linux_binprm
sp

Szukanie modułu ładującego - rozpoznanie formatu pliku

Funkcja odpowiedzialna za szukanie modułu ładującego: search_binary_handler
Przy szukaniu przeglądana jest lista dostępnych formatów wykonywalnych - wykonywane są dwa obroty pętli przeszukującej. Jeśli któraś funkcja rozpozna format tego pliku, to od razu ładuje go do pamięci i wykonuje.
sp

Formaty plików wykonywalnych

W pliku exec.c znajdują się też deklaracje zmiennych i definicje funkcji wykorzystywanych przez wszystkie moduły ładujące, niezależnie od formatu.

Lista formatów

Dla każdego formatu plików wykonywalnych zdefiniowana jest struktura linux_binfmt, w której trzymane są m.in. wskaźniki do funkcji ładujących program, ładujących bibliotekę dzieloną oraz robiących zrzut programu (tzw. "core-dump"). Struktury te polączone są w listę. Po starcie systemu lista ta zawiera standardowo formaty: script, java, a.out i elf. Można jednak łatwo zmienić to ustawienie (także dodać nowe formaty)
 

Algorytm open_inode

Funkcja open_inode jest wykorzystywana w modułach ładujących przy wczytywaniu pliku do pamięci. Działa następująco:  

Algorytm read_exec

Funkcja read_exec wczytuje plik wykonywalny do pamięci jądra lub użytkownika według następującego algorytmu: W przypadku, gdy wczytujemy do pamięci użytkownika, wcześniej sprawdzamy prawa do zapisu funkcją verify_area.
 
mm

Usuwanie poprzedniego kontekstu

Za usuwanie poprzedniego kontekstu odpowiada funkcja flush_old_exec, wywoływana w procedurach ładujących dla różnych formatów. Wykonuje ona następujące czynności:  

Domena wykonywania (exec domain)

Każdy proces ma ustawioną swoją osobowość, oraz na jej podstawie ustawioną domenę wykonywania. Ma stanowić wsparcie do wykonywania programów napisanych na tę samą maszynę, ale pod inną wersją systemu UNIX. W jądrze jest implementowana lista domen, z których każda ma przypisany pewien zakres osobowości. Dwie różne domeny mogą obsługiwać ten sam typ osobowości, w szczególności do domyślnej domeny Linux, występującej zawsze, przypisany jest pełen zakres osobowości.
Domena wykonywania ma zapewnić poprawną obsługę sygnałów, zakładając, że w innym systemie te same sygnały mogły występować pod innym numerami. Ponadto domena wykonywania, może mieć własną obsługę błędu segmentacji.
Nigdzie w jądrze nie napotkałem, zarejestrowania innej domeny, niż standardowa - Linux.
Ale np. przy procedurze  ładującej program wykonywalny w formacie ELF, dokonuję się sprawdzenia, czy nie był on napisany dla systemu UNIX V wersja 4, i jeśli był to ustawia mu się odpowiednią osobowość i wyszukuje domenę rozpoznającą tę osobowość.
sp

Bibliografia

  1. Pliki źródłowe jądra Linuxa (wersja 2.0.32):

Autorzy: Sławek Poreda, Marcin Mucha