Linux Exec System Call

Linux Exec System Call
Wywołanie systemowe EXEC służy do wykonywania pliku, który przebywa w aktywnym procesie. Po nazwie EXEC jest wymieniany poprzedni plik wykonywalny, a nowy plik jest wykonywany.

Mówiąc dokładniej, możemy powiedzieć, że użycie połączenia systemowego Exec zastąpi stary plik lub program z procesu nowym plik lub programem. Cała zawartość procesu zastępuje się nowym programem.

Segment danych użytkownika, który wykonuje wywołanie systemowe exec (), jest zastępowana plikami danych, którego nazwa jest podana w argumencie podczas wywoływania exec ().

Nowy program jest ładowany do tej samej przestrzeni procesowej. Obecny proces jest po prostu przekształcony w nowy proces, a zatem proces procesu nie jest zmieniany, dzieje się tak, ponieważ nie tworzymy nowego procesu.

Jeśli aktualnie uruchomiony proces zawiera więcej niż jeden wątek, wszystkie wątki zostaną zakończone, a nowy obraz procesu zostanie załadowany, a następnie wykonany. Nie ma funkcji destruktora, które kończą wątki bieżącego procesu.

PID procesu nie jest zmieniane, ale dane, kod, stos, sterta itp. procesu są zmieniane i zastępowane na nowo załadowanego procesu. Nowy proces jest wykonywany z punktu wejścia.

Wywołanie systemowe EXEC to zbiór funkcji i w języku programowania C, standardowe nazwy tych funkcji są następujące:

  1. execl
  2. Execle
  3. execlp
  4. execv
  5. Execve
  6. execvp


Należy tutaj zauważyć, że funkcje te mają tę samą bazę Exec a następnie jedna lub więcej liter. Są one wyjaśnione poniżej:

mi: Jest to szereg wskazówek wskazujących na zmienne środowiskowe i jest wyraźnie przekazywany do nowo załadowanego procesu.

L: L dotyczy argumentów wiersza poleceń przekazanych listy do funkcji

P: P jest zmienną środowiskową ścieżki, która pomaga znaleźć plik przekazany jako argument, który ma zostać załadowany do procesu.

V: v dotyczy argumentów wiersza poleceń. Są one przekazywane jako szereg wskaźników do funkcji.

Dlaczego Exec jest używany?

Exec jest używany, gdy użytkownik chce uruchomić nowy plik lub program w tym samym procesie.

Wewnętrzne działanie Exec

Rozważ następujące punkty, aby zrozumieć działanie Exec:

  1. Obecny obraz procesu jest zastąpiony nowym obrazem procesu.
  2. Nowy obraz procesu to ten, który przekazałeś jako argument Exec
  3. Obecnie uruchomiony proces jest zakończony
  4. Nowy obraz procesu ma ten sam identyfikator procesu, to samo środowisko i ten sam deskryptor pliku (ponieważ proces nie został zastąpiony obraz procesu) zastąpiony)
  5. Wpływ na statystyki procesora i pamięć wirtualna. Wirtualne mapowanie pamięci bieżącego obrazu procesu zastępuje się wirtualną pamięcią nowego obrazu procesu.

Składniki funkcji rodzinnych EXEC:

Poniżej przedstawiono składnię dla każdej funkcji EXEC:

int execl (const char* ścieżka, const char* arg,…)
int execlp (const char* plik, const char* arg,…)
int execle (const char* ścieżka, const char* arg,…, char* const envP [])
int execv (const char* ścieżka, const char* argv [])
int execvp (const char* plik, const char* argv [])
int execvpe (const char* plik, const char* argv [], char* const envP [])

Opis:

Typ powrotu tych funkcji jest int. Gdy obraz procesu zostanie pomyślnie zastąpiony, nic nie zwraca się do funkcji wywoływania, ponieważ proces, który go nazywał. Ale jeśli wystąpi jakiś błąd -1. Jeśli wystąpi jakikolwiek błąd errno jest ustawiony.

W składni:

  1. ścieżka służy do określenia pełnej nazwy ścieżki pliku, który ma być wykonany.
  1. arg jest przekazany argument. W rzeczywistości jest to nazwa pliku, który zostanie wykonany w trakcie procesu. Większość razy wartość arg i ścieżki jest sama.
  1. const char* arg W funkcjach execl (), execlp () i execle () są uważane za arg0, arg1, arg2,…, argn. Zasadniczo jest to lista wskazówek do zerowych zwolnionych ze strin. Tutaj pierwszy argument wskazuje na nazwę pliku, która zostanie wykonana zgodnie z opisem w punkcie 2.
  1. Envp to tablica zawierająca wskazówki wskazujące na zmienne środowiskowe.
  1. plik służy do określenia nazwy ścieżki, która zidentyfikuje ścieżkę nowego pliku obrazu procesu.
  1. Funkcje wywoływania exec, które kończą się mi są używane do zmiany środowiska dla nowego obrazu procesu. Te funkcje przechodzą listę środowiska za pomocą argumentu Envp. Ten argument jest szeregiem znaków, które wskazują na Null zakończony ciąg i definiuje zmienną środowiskową.

Aby korzystać z funkcji Exec Family, musisz dołączyć następujący plik nagłówka w programie C:

#włączać

Przykład 1: Korzystanie z Call System Call w programie C

Zastanów się nad następującym przykładem, w którym użyliśmy wywołania systemu EXEC w programowaniu C w Linux, Ubuntu: Mamy tutaj dwa pliki C.C i cześć.C:

przykład.C

KOD:

#włączać
#włączać
#włączać
int main (int argc, char *argv [])

printf („PID przykładu.c = %d \ n ”, getpid ());
char *args [] = „hello”, „c”, „programowanie”, null;
execv ("./Hello ”, args);
printf („Powrót do przykładu.C");
powrót 0;

Witam.C

KOD:

#włączać
#włączać
#włączać
int main (int argc, char *argv [])

printf („Jesteśmy w witamo.c \ n ”);
printf („pid of hello.c = %d \ n ”, getpid ());
powrót 0;

WYJŚCIE:

PID przykładu.C = 4733
Jesteśmy w witamo.C
PID Hello.C = 4733

W powyższym przykładzie mamy przykład.plik C i cześć.plik C. W przykładzie .Plik C Przede wszystkim wydrukowaliśmy identyfikator bieżącego procesu (przykład pliku.C działa w bieżącym procesie). Następnie w następnym wierszu stworzyliśmy szereg wskazówek postaci. Ostatni element tej tablicy powinien być zerowy jako punkt zakończenia.

Następnie użyliśmy funkcji execv (), która przyjmuje nazwę pliku i tablicę wskaźnika znaków jako argument. Należy tutaj zauważyć, że użyliśmy ./ Z nazwą pliku określa ścieżkę pliku. Ponieważ plik znajduje się w folderze, w którym przykład.C znajduje się, więc nie ma potrzeby określania pełnej ścieżki.

Po wywołaniu funkcji execV () nasz obraz procesu zostanie teraz zastąpiony przykładem pliku.C nie jest w trakcie procesu, ale plik Hello.C jest w trakcie. Można zauważyć, że identyfikator procesu jest taki sam.C jest obrazem procesu lub przykładem.C jest obrazem procesu, ponieważ proces jest taki sam, a obraz procesu jest zastępowany.

Następnie mamy tutaj kolejną rzecz, którą należy zwrócić uwagę, czyli instrukcja printf () po execV () nie jest wykonywana. Dzieje się tak, ponieważ kontrola nigdy nie jest zwracana z powrotem do starego obrazu procesu, gdy zastąpi go nowy obraz procesu. Kontrola wraca tylko do funkcji wywoływania, gdy zastępowanie obrazu procesu nie powiedzie się. (W tym przypadku wartość zwracania wynosi -1).

Różnica między wywołaniami systemowymi Fork () i exec ():

Wywołanie systemowe Fork () służy do utworzenia dokładnej kopii procesu uruchomionego, a utworzona kopia to proces potomny, a proces uruchomiony jest proces nadrzędny. Natomiast wywołanie systemowe jest używane do zastąpienia obrazu procesu nowym obrazem procesu. Stąd nie ma koncepcji procesów rodziców i dzieci w wywołaniu systemowym ().

W systemie Fork () Call Procesy dla rodziców i dzieci są wykonywane jednocześnie. Ale w przypadku wywołania systemowym exec (), jeśli wymiana obrazu procesu się powiedzie, kontrola nie powraca do miejsca, w którym nazywano funkcję exec, a raczej wykonuje nowy proces. Kontrola zostanie przeniesiona tylko wtedy, gdy wystąpi jakiś błąd.

Przykład 2: Połączenie połączeń systemowych Fork () i exec ()

Rozważ poniższy przykład, w którym użyliśmy połączeń systemowych zarówno Fork (), jak i exec () w tym samym programie:

przykład.C

KOD:

#włączać
#włączać
#włączać
int main (int argc, char *argv [])

printf („PID przykładu.c = %d \ n ”, getpid ());
PID_T P;
p = rozwidlenie ();
if (p ==-1)

printf („Występuje błąd podczas wywoływania forku ()”);

if (p == 0)

printf („Jesteśmy w procesie dziecka \ n”);
printf ("Wzywa Hello.c z procesu dziecięcego \ n ”);
char *args [] = „hello”, „c”, „programowanie”, null;
execv ("./Hello ”, args);

w przeciwnym razie

printf („jesteśmy w procesie nadrzędnym”);

powrót 0;

Witam.C:

KOD:

#włączać
#włączać
#włączać
int main (int argc, char *argv [])

printf („Jesteśmy w witamo.c \ n ”);
printf („pid of hello.c = %d \ n ”, getpid ());
powrót 0;

WYJŚCIE:

PID przykładu.C = 4790
Jesteśmy w procesie rodziców
Jesteśmy w procesie dziecka
Zadzwoń do Hello.C z procesu dziecięcego
Jesteśmy w witamo.C
PID Hello.C = 4791

W tym przykładzie użyliśmy połączenia systemowego Fork (). Po utworzeniu procesu dziecka 0 zostanie przypisane do P, a następnie przejdziemy do procesu dziecka. Teraz blok instrukcji z IF (p == 0) zostanie wykonany. Wyświetlany jest komunikat i użyliśmy wywołania systemu execv () i bieżącego obrazu procesu dziecka, co jest przykładem.c zostanie zastąpiony witamą.C. Przed ExecV () Call Call Child and Pareer Processes były takie same.

Można zauważyć, że PID przykładu.C i cześć.C jest teraz inne. To dlatego, że przykład.C to obraz procesu nadrzędnego i cześć.C to obraz procesu dziecka.