Uruchamianie programów w systemie Linux

Linux udostępnia standardowe dla Unixów wywołanie systemowe execve(). Kontekst programu wołającego zostaje całkowicie zastąpiony przez kontekst nowego programu. Linux 2.4.7 obsługuje wiele formatów plików binarnych, w tym programy napisane dla innych systemów operacyjnych (SunOs, Solaris, RISCOS). Dlatego nie ma jednej procedury ładowania pliku. Zamiast tego przechowywana jest lista znanych formatów (są one zmodularyzowane) i przy poleceniu ładowania pliku próbuje się zastosować kolejno różne funkcje ładujące.

Lista formatów

Jądro utrzymuje na zmiennej formats listę struktur linux_binfmt odpowiadających zarejestrowanym formatom. Formaty można rejestrować za pomocą funkcji register_binfmt() biorącej taką strukturę jako parametr.

Przepływ sterowania

  1. Funkcja execve() rozwijana jest z makra w pliku unistd.h. Zachowuje ona w rejestrach numer odpowiadający wywołaniu execve() (__NR_EXECVE) oraz wskaźniki do swoich parametrów (ścieżka pliku, tablicę argumentów dla programu oraz tablicę zmiennych środowiska) oraz wywołuje przerwanie int 0x80.

  2. Obsługująca to przerwanie funkcja sys_call() zachowuje na stosie rejestry procesu (makro SAVE_ALL) i uruchamia funkcję znajdującą się w tablicy sys_call_table pod podanym numerem. W tym przypadku jest to funkcja sys_execve().

  3. funkcja sys_execve() kopiuje ścieżkę pliku do pamięci jądra i przekazuje ją, razem z argumentami, zmiennymi środowiska i wartościami rejestrów procesu do funkcji do_execve() . Funkcja ta wykonuje całość pracy; po jej zakończeniu zwalniana jest już tylko pamięć na ścieżkę pliku i propagowany kod powrotu funkcji do_execve().

  4. Po powrocie z wywołania systemowego do trybu użytkownika proces jest już całkowicie zmieniony; proces po powrocie zastaje nowy kod który zaczyna wykonywać zamiast wrócić do instrukcji po wywołaniu funkcji execve() (jest to drobna nieścisłość - najpierw musi zostać wykonany kod interpretera programu; patrz ładowanie programu). Stąd można powiedzieć, że w przypadku sukcesu funkcja execve() nigdy się nie kończy.