#define _GNU_SOURCE #include #include #include #include #include #include const int STACK_SIZE = 4096; /* volé depuis le template */ volatile char counter = 0; int child() { printf("Coucou depuis l'enfant\n"); printf("parent id: %d\n", getppid()); printf("process id: %d\n", getpid()); printf("thread id: %d\n", gettid()); printf("user id: %d\n", getuid()); while (counter < 4) { printf("[Child] Counter: %d\n", counter); counter += 1; sleep(1); } return 0; } void help(char *name) { printf("%s - Émule différent types de fork()\n", name); printf("Usage: %s \n\n", name); printf(" fork Fork basique.\n"); printf(" chimera Créer un processus enfant partageant le même espace mémoire.\n"); printf(" thread Créé un thread.\n"); } int main(int argc, char *argv[]) { int flags, c_pid; char *mode, *stack; if (argc < 2) { help(argv[0]); return 0; } /* * Je mets SIGCHLD quand on fait un fork basique, histoire d'avoir au moins * un flag. En théorie, il n'y en a pas besoin vu qu'on ne souhaite pas * gérer la mort de l'enfant. * * Pas besoin de notifier le père pour la chimère, on met directement le * flag pour partager la zone mémoire. */ mode = argv[1]; if (!strcmp(mode, "fork")) flags = SIGCHLD; else if (!strcmp(mode, "chimera")) flags = CLONE_VM; else if (!strcmp(mode, "thread")) flags = CLONE_VM | CLONE_THREAD | CLONE_SIGHAND; else { help(argv[0]); return 0; } stack = (char *) malloc(STACK_SIZE); printf("Coucou depuis le parent\n"); printf("parent id: %d\n", getppid()); printf("process id: %d\n", getpid()); printf("thread id: %d\n", gettid()); printf("user id: %d\n\n", getuid()); /* * On passe la dernière adresse de la stack, cf. le manuel. */ c_pid = clone(child, (stack + STACK_SIZE - 1), flags, NULL); printf("[Parent] PID enfant: %d\n", c_pid); while (counter < 4) { printf("[Parent] Counter: %d\n", counter); counter += 1; sleep(1); } free(stack); return 0; }