posix_spawn
je dnes pravděpodobně preferovaným řešením.
Před tím fork()
a poté execXX()
byl způsob, jak to udělat (kde execXX
je jedním z exec
rodina funkcí, včetně execl
, execlp
, execle
, execv
, execvp
a execvpe
). V současné době v knihovně GNU C, alespoň pro Linux, posix_spawn
je stejně implementován přes fork/exec; Linux nemá posix_spawn
systémové volání.
Použili byste fork()
(nebo vfork()
) ke spuštění samostatného procesu, který bude klonem rodiče. V podřízeném i nadřazeném procesu provádění pokračuje, ale fork
v obou případech vrátí jinou hodnotu, což vám umožní rozlišovat. Poté můžete použít jeden z execXX()
funkce z podřízeného procesu.
Všimněte si však tohoto problému – text vypůjčený z jednoho z mých blogových příspěvků (http://davmac.wordpress.com/2008/11/25/forkexec-is-forked-up/):
Zdá se, že neexistuje žádný jednoduchý způsob, který by vyhovoval standardům (nebo dokonce obecně přenosný způsob), jak paralelně spustit jiný proces a mít jistotu, že volání exec() bylo úspěšné. Problém je v tom, že jakmile fork()d a poté úspěšně exec()d, nemůžete komunikovat s nadřazeným procesem, abyste informovali, že exec() bylo úspěšné. Pokud exec() selže, můžete komunikovat s rodičem (například prostřednictvím signálu), ale nemůžete informovat o úspěchu – jediný způsob, jak si rodič může být jistý úspěchem exec(), je počkat () na potomka. proces dokončit (a zkontrolovat, že neexistuje žádná indikace selhání) a že se samozřejmě nejedná o paralelní provádění.
tj. pokud execXX()
uspěje, již nemáte kontrolu, takže nemůžete signalizovat úspěch původnímu (nadřazenému) procesu.
Potenciální řešení tohoto problému v případě, že se jedná o problém ve vašem případě:
[...] použijte pipe() k vytvoření roury, nastavte výstupní konec na close-on-exec, pak fork() (nebo vfork()), exec() a zapište něco (možná errno) do roura, pokud exec() selže (před voláním _exit()). Rodičovský proces může číst z roury a dostane okamžitý konec vstupu, pokud exec() uspěje, nebo nějaká data, pokud exec() selže.
(Všimněte si, že toto řešení může způsobit inverzi priority, pokud podřízený proces běží s nižší prioritou než nadřazený proces a rodič čeká na výstup z něj).
Existuje také posix_spawn
jak je uvedeno výše a v jiných odpovědích, ale neřeší to problém detekce selhání při spuštění podřízeného spustitelného souboru, protože je často implementován z hlediska fork/exec a může vrátit úspěch před exec()
fáze selže.
fork
/exec
kombinace již byla zmíněna, ale existuje také posix_spawn
rodina funkcí, které lze použít jako náhradu za fork
+ exec
a je přímějším ekvivalentem CreateProcess
. Zde je příklad pro obě možnosti:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/wait.h>
extern char **environ;
void test_fork_exec(void);
void test_posix_spawn(void);
int main(void) {
test_fork_exec();
test_posix_spawn();
return EXIT_SUCCESS;
}
void test_fork_exec(void) {
pid_t pid;
int status;
puts("Testing fork/exec");
fflush(NULL);
pid = fork();
switch (pid) {
case -1:
perror("fork");
break;
case 0:
execl("/bin/ls", "ls", (char *) 0);
perror("exec");
break;
default:
printf("Child id: %i\n", pid);
fflush(NULL);
if (waitpid(pid, &status, 0) != -1) {
printf("Child exited with status %i\n", status);
} else {
perror("waitpid");
}
break;
}
}
void test_posix_spawn(void) {
pid_t pid;
char *argv[] = {"ls", (char *) 0};
int status;
puts("Testing posix_spawn");
fflush(NULL);
status = posix_spawn(&pid, "/bin/ls", NULL, NULL, argv, environ);
if (status == 0) {
printf("Child id: %i\n", pid);
fflush(NULL);
if (waitpid(pid, &status, 0) != -1) {
printf("Child exited with status %i\n", status);
} else {
perror("waitpid");
}
} else {
printf("posix_spawn: %s\n", strerror(status));
}
}
Napsal jsi:
Chci ve své knihovně vytvořit nový proces bez nahrazení aktuálního spouštění image.system() blokuje aktuální proces, není to dobré. Chci pokračovat v aktuálním procesu.
Stačí za příkaz call přidat ampersand. Příklad:system("/bin/my_prog_name &");
Váš proces nebude zablokován!