‟overcq”

Z bloga o OUX/C+

Tworzenie procesu potomnego

W systemach uniksopodobnych uruchomienie innego programu przeprowadza się w dwóch krokach:

  1. utworzenie kopii bieżącego procesu przy użyciu wywołania systemowego “fork”
  2. 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”.