En ce qui concerne les processus d'arrière-plan à l'aide de la fourchette () et processus enfants dans ma coquille factice

StackOverflow https://stackoverflow.com/questions/8319484

  •  25-10-2019
  •  | 
  •  

Question

Je suis en train de créer un simple programme shell en C. Ce que je besoin de faire est de fournir à l'utilisateur une invite dans lequel ils peuvent exécuter d'autres programmes locaux. Je peux le faire amende partiel, à l'aide d'une fourchette (), dans lequel les temps d'attente de processus parent () sur l'enfant, et la execvp des enfants () est le programme.

Cependant, si le caractère « & » est ajouté à la fin de la commande de l'utilisateur, j'ai besoin de leur programme en arrière-plan, ce qui signifie que je dois le parent de ne pas attendre le processus de l'enfant mais au lieu immédiatement retourner l'invite à l'utilisateur, tout en permettant au processus d'arrière-plan de continuer à fonctionner, mais pas ce qui lui permet d'afficher quoi que ce soit sur l'écran. Je veux juste être en mesure de vérifier qu'il existe toujours via la commande ps.

J'ai essayé de comprendre l'idée derrière l'utilisation de fork () pour créer un enfant, alors la fourchette de l'enfant () pour créer un petit-enfant de toutes sortes, puis quittez immédiatement () - ing processus enfant. à savoir, l'orphelin petits-enfants. Soi-disant ce qui permet au parent d'attendre encore sur l'enfant, mais étant donné que l'enfant se termine presque immédiatement efficacement, il est comme ça n'attend pas du tout? Quelque chose au sujet de la folie zombie? Je ne sais pas. Plusieurs sites que je suis tombé semblent recommander cela comme un moyen d'exécuter un processus en arrière-plan.

Cependant, lorsque je tente de le faire, je reçois des choses sauvages qui se passe avec le déroulement du programme, le processus « de fond » continue d'afficher des entrées sur l'écran, et je ne suis vraiment pas sûr où aller d'ici.

Ceci est ma mise en œuvre du code, que je suis sûr est tout à fait tort. Je me demande si cette chose de petit-enfant est même la voie que je besoin de prendre, et si oui, quel est le problème avec mon code?

36 int main(int argc, char *argv[])
37 {
38     char buffer[512];
39     char *args[16];
40     int background;
41     int *status;
42     size_t arg_ct;
43     pid_t pid;
44 
45     while(1)
46     {
47         printf("> ");
48         fgets(buffer, 512, stdin);
49         parse_args(buffer, args, 16, &arg_ct);
50 
51         if (arg_ct == 0) continue;
52 
53         if (!strcmp(args[0], "exit"))
54         {
55             exit(0);
56         }
57 
58         pid = fork();  //here I fork and create a child process
61 
62         if (pid && !background)  //i.e. if it's the parent process and don't need to run in the background (this is the part that seems to work)
63         {
64             printf("Waiting on child (%d).\n", pid);
65             pid = wait(status);
66             printf("Child (%d) finished.\n", pid);
67         }
68         else
69         {
70             if (background && pid == 0) { //if it's a child process and i need to run the command in background
71                
72                 pid = fork(); //fork child and create a grandchild
73                 if (pid) exit(0); //exit child and orphan grandchild
74                 
75                 execvp(args[0], args); //orphan execs the command then exits
76                 exit(1);
77 
78             } else exit(0);
79         }
80     }
81     return 0;
82 }

P.S. Pour être clair, je dois le processus que je suis en cours d'exécution en arrière-plan pour ne jamais faire un son nouveau, même si elle a obtenu une boucle infinie d'états d'impression ou quelque chose. Je veux juste vous assurer qu'il fonctionne toujours en arrière-plan via ps -a ou quelque chose.

Désolé pour l'explication confondant je ne sais pas comment l'expliquer mieux.

Merci à l'avance

P.P.S Je vais le mettre en œuvre afin que chaque commande subséquente déterminera la valeur booléenne de « background », désolé pour la confusion

Était-ce utile?

La solution

Vous ne voulez pas utiliser la méthode à double fork() dans une coquille -. Qui est pour l'écriture daemons qui veulent spécifiquement pour échapper à la surveillance de la coquille qui les a couru

Au lieu de cela, la façon de reproduire le comportement des & dans des coquilles existants est d'appeler fork(), puis dans l'appel de l'enfant setpgid(0, 0); de mettre l'enfant dans une nouvelle groupe de processus . Le parent continue juste à (peut-être après l'impression du PID de l'enfant) -. Il ne remet pas wait()

Chaque terminal peut avoir qu'un seul groupe de processus de premier plan, qui est le groupe de processus qui est actuellement autorisé à envoyer une sortie à la borne. Cela restera le groupe de processus dont votre shell est membre, de sorte que votre coquille restera au premier plan.

Si un groupe essaie de processus d'arrière-plan pour lire à partir du terminal, il sera envoyé un signal pour l'arrêter. Sortie à la borne est encore autorisé - ce qui est normal (ls & try dans votre shell régulière). Pour mettre en œuvre la commande fg dans votre shell, vous aurez besoin de la fonction tcsetpgrp() pour changer le groupe de processus de premier plan.

Vous voudrez aussi appeler waitpid() avec l'option WNOHANG régulièrement - par exemple, immédiatement avant d'afficher l'invite du shell. Cela vous permettra de détecter lorsque le processus d'arrière-plan a quitté ou arrêté (ou bien, vous pouvez gérer le signal de SIGCHLD).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top