W systemach uniksopodobnych uruchomienie innego programu przeprowadza się w dwóch krokach:
- utworzenie kopii bieżącego procesu przy użyciu wywołania systemowego “fork”
- uruchomienie programu i zastąpienie tej kopii przy użyciu wywołania systemowego “exec”
Jednak są określone zależności, które powstają w wyniku utworzenia takiej kopii procesu oraz kolejne w wyniku uruchomienia programu. Te zależności wymagają wykonania określonych działań zabezpieczających. Powtarzają się one dla każdej sekwencji “fork”‐“exec”, dlatego zostały utworzone procedury obiektu “E_flow_Q_fork”, które wykonują większość tych działań. Uruchomienie programu ma następującą postać:
pid_t pid = E_flow_I_fork_I_begin(); if( !pid ) { E_flow_I_fork_I_start(); E_flow_I_fork_I_exec( cwd, args, args_n ); exit( EXIT_FAILURE ); } E_flow_I_fork_I_end(pid); if( !~E_flow_I_fork_I_wait(pid) ) return ~0;
“E_flow_I_fork_I_wait” jest procedurą służącą do oczekiwania na zakończenie uruchomionego procesu i nie jest wymagana.
Pierwszy parametr procedury “E_flow_I_fork_I_exec” (jeśli niezerowy) wskazuje na katalog bieżący, w którym zostanie uruchomiony program. Drugi parametr to tablica list argumentów zadeklarowana następująco:
struct E_flow_Z_args { N argc; Pc *argv; };
Trzeci parametr to liczba elementów tej tablicy.
Tablica list argumentów jest sklejana w jedną listę i uruchamiany jako program jest pierwszy element tej listy, natomiast pozostałe elementy listy są podanymi mu parametrami wiersza polecenia, na przykład:
pid_t pid = E_flow_I_fork_I_begin(); if( !pid ) { E_flow_I_fork_I_start(); struct E_flow_Z_args args[1]; args[0].argc = 1; args[0].argv = ( Pc [] ){ "program", 0 }; E_flow_I_fork_I_exec( cwd, args, 1 ); exit( EXIT_FAILURE ); } E_flow_I_fork_I_end(pid);
Do właściwego uruchomienia innego programu potrzeba jeszcze w kopii procesu (po “E_flow_I_fork_I_start”) zamknąć wszystkie nie używane deskryptory plików. A używane deskryptory plików (na przykład deskryptory standardowego wejścia i wyjścia nowo uruchamianego programu) można ewentualnie przekierować (przy użyciu wywołania systemowego “dup2”) do “pipe” utworzonego przed wywołaniem “E_flow_I_fork_I_begin”.