exec to rodzina wywołań systemowych w systemach uniksowych, która podmienia obraz bieżącego procesu na zupełnie nowy program — przy zachowaniu tego samego PID. Mówiąc po ludzku: proces, który był dotąd np. powłoką, „znika” i w jego miejsce wskakuje inny plik wykonywalny. Nie powstaje nowy proces, nie ma rodzica i dziecka — to ten sam wpis w tablicy procesów, tylko z innym kodem, innym segmentem pamięci i innym stosem.
Jak to działa i po co
W libc exec występuje jako kilka wariantów: execl, execlp, execv, execvp, execve, execvpe. Litery w nazwie mówią o argumentach: l to lista argumentów po przecinku, v to wektor (tablica), p oznacza szukanie programu w PATH, a e przekazanie własnego środowiska. Pod spodem wszystkie sprowadzają się do jednego prawdziwego wywołania jądra — execve (na Linuksie istnieje też nowsze execveat).
Kluczowa rzecz: jeśli exec się powiedzie, kod po nim już się nie wykona — bo nie ma do czego wracać, stary program przestał istnieć. Dlatego exec zwraca cokolwiek (czyli -1) tylko wtedy, gdy zawiedzie, np. plik nie istnieje albo brak uprawnień. To zachowanie jest fundamentem modelu fork + exec: proces najpierw się klonuje przez fork, a potem dziecko robi exec, żeby stać się docelowym programem. Rodzic zostaje sobą i może czekać przez wait.
Przykład z praktyki
Tak właśnie działa każda powłoka. Gdy w bash wpiszesz ls, shell robi fork, a dziecko woła execvp("ls", ...). W skryptach przyda Ci się wbudowane polecenie exec, które robi to bez forka — w samej powłoce:
exec ./serwerw skrypcie startowym (entrypoint kontenera) — serwer dostajePID 1, dzięki czemu poprawnie odbiera sygnały typuSIGTERMprzydocker stop.exec 2>log.txtprzekierowuje błędy całego skryptu do pliku, bez uruchamiania nowego programu.
Częste pułapki
Nie myl exec z system() czy fork — exec sam w sobie nie tworzy nowego procesu, tylko zastępuje istniejący. Pamiętaj też, że deskryptory plików domyślnie przeżywają exec (chyba że ustawisz flagę O_CLOEXEC) — stąd działają potoki i przekierowania. I klasyk debugowania: jeśli „kod po exec się nie wykonuje”, to znaczy, że wszystko jest OK, a nie że masz buga.
Pojęcia powiązane: fork, wait, PID, execve, PATH, O_CLOEXEC, sygnały (SIGTERM), proces zombie.