Wyobraź sobie, że chcesz uruchomić inny program z poziomu swojego procesu — na przykład uruchomić skrypt, program lub powłokę. W systemie Linux, aby to zrobić na najniższym poziomie, korzystamy z wywołania systemowego execve.
W tym artykule dowiesz się, czym jest syscall execve, jak działa i zobaczysz praktyczne przykłady jego użycia — zarówno z poziomu języka C, jak i asemblera.
Co to jest execve?
execve (ang. execute program) to wywołanie systemowe w Linuxie służące do uruchomienia nowego programu, zastępując obecny obraz procesu nowym programem.
- Nie tworzy nowego procesu — zamienia kod, dane i stos bieżącego procesu.
- Przyjmuje ścieżkę do programu, argumenty oraz zmienne środowiskowe.
- Po wywołaniu
execveobecny program przestaje istnieć — zastępuje go nowy.
Jak działa execve?
Wywołanie execve ma następującą sygnaturę:
int execve(const char *pathname, char *const argv[], char *const envp[]);
pathname— ścieżka do wykonywalnego pliku.argv— tablica wskaźników do argumentów przekazywanych do programu.envp— tablica wskaźników do zmiennych środowiskowych.
Jeśli wywołanie powiedzie się, nie wraca do programu wywołującego — proces jest zastąpiony nowym programem. Jeśli zwróci błąd, execve zwróci -1.
execve w asemblerze x86-64
Wywołania systemowe w Linux x86-64 wykonuje się instrukcją syscall. Numer execve to 59 (decimal).
Argumenty przekazujemy do rejestrów:
| Rejestr | Argument |
|---|---|
rax | numer syscall (59) |
rdi | pathname |
rsi | argv |
rdx | envp |
Przykład minimalnego kodu w NASM, który uruchamia /bin/ls:
section .data
path db '/bin/ls', 0
argv dq path, 0
envp dq 0
section .text
global _start
_start:
mov rax, 59 ; execve syscall number
mov rdi, path ; ścieżka programu
mov rsi, argv ; argumenty
mov rdx, envp ; środowisko
syscall
; jeśli execve zawiedzie - zakończ program
mov rax, 60 ; exit syscall
xor rdi, rdi
syscall
Kompilacja powyższego kodu na Linux
$ nasm -f elf64 -o run_ls_asm.o run_ls_asm.asm
$ ld -o run_ls_asm run_ls_asm.o
$ ./run_ls_asm
run_ls_asm run_ls_asm.asm run_ls_asm.o
Praktyczne zastosowania execve
1. Implementacja własnego exec w shellu
execve to fundament działania wielu powłok (shelli). Po wpisaniu polecenia:
ls -l /home
shell wykorzystuje fork() do utworzenia procesu potomnego, a w nim execve do uruchomienia /bin/ls z argumentami.
2. Uruchamianie skryptów lub programów z własnej aplikacji
Czasem aplikacja musi uruchomić zewnętrzny program, np. narzędzie do konwersji plików. execve pozwala na zastąpienie procesu tym programem, albo (częściej) wykorzystuje się fork() + execve(), by nie zamknąć aplikacji macierzystej.
3. Zastąpienie bieżącego procesu nowym programem
Jeśli w procesie chcesz całkowicie zmienić jego kod i dane (np. po zalogowaniu się użytkownika), wywołujesz execve, co zastępuje proces nowym obrazem.
execve vs system()
Funkcja system() w C uruchamia powłokę /bin/sh i wykonuje komendę. Jest wygodna, ale mniej elastyczna i bezpieczna niż bezpośrednie użycie execve.
Uwaga na błędy
- Jeśli ścieżka jest błędna lub program nie ma uprawnień —
execvezwróci błąd. - Pamiętaj o przekazaniu poprawnych tablic argumentów i środowiska.
execvenigdy nie wraca jeśli jest sukcesem!
Podsumowanie
execveto najniższy poziom uruchamiania programów w Linuxie.- Zastępuje obecny proces nowym obrazem programu.
- Jest fundamentem działania powłok i procesów potomnych.
- Można go używać bezpośrednio z asemblera, lub przez standardowe funkcje w C.