Con respecto a los procesos de fondo utilizando los procesos de la bifurcación y el niño en mi caparazón ficticio

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

  •  25-10-2019
  •  | 
  •  

Pregunta

Estoy tratando de crear un programa de shell simple en C. Lo que necesito hacer es proporcionar al usuario un mensaje en el que pueda ejecutar otros programas locales. Puedo hacer esa parte bien, usando un bifurcado () en el que el proceso principal espera () en el niño, y el niño ejecutvp () es el programa.

Sin embargo, si el carácter '&' se agrega al final del comando del usuario, necesito que su programa se ejecute en segundo plano, lo que significa que necesito que el padre no espere en el proceso del niño, sino que devuelva inmediatamente el mensaje al usuario, mientras permite que el proceso de fondo continúe ejecutándose, pero no permite que muestre nada en la pantalla. Solo quiero poder verificar que todavía exista a través del comando PS.

Traté de entender la idea detrás de usar Fork () para crear un niño, luego volver a tener el horquilla infantil () para crear una especie de nieto, luego salir inmediatamente ()-----El proceso del niño. es decir, huérfano el nieto. Supuestamente, esto permite que el padre todavía espere al niño, pero como el niño termina efectivamente casi de inmediato, ¿es como si no espere en absoluto? ¿Algo sobre la locura zombie? No sé. Varios sitios que he encontrado parecen recomendar esto como una forma de ejecutar un proceso en segundo plano.

Sin embargo, cuando trato de hacer esto, tengo cosas salvajes que suceden con el flujo del programa, el proceso de 'fondo' continúa mostrando la entrada en la pantalla, y realmente no estoy seguro de a dónde ir desde aquí.

Esta es mi implementación del código, que estoy seguro está bastante equivocado. Me pregunto si todo este asunto del nieto es incluso la ruta que necesito tomar, y si es así, ¿qué pasa con mi código?

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 }

PD Para ser claros, necesito el proceso que estoy ejecutando en segundo plano para nunca volver a hacer un sonido, incluso si tiene un bucle infinito de declaraciones de impresión o algo así. Solo quiero asegurarme de que todavía esté funcionando en segundo plano a través de PS -a o algo así.

Perdón por la explicación confusa, simplemente no sé cómo explicarlo mejor.

Gracias por adelantado

PPS Lo implementaré para que cada comando posterior determine el valor booleano de 'antecedentes', perdón por la confusión

¿Fue útil?

Solución

No quieres usar el doblefork() Método en un shell, es decir, para escribir demonios que quieran escapar específicamente de la supervisión por el caparazón que los ejecutó.

En cambio, la forma de duplicar el comportamiento de & en las conchas existentes es llamar fork(), luego en la llamada del niño setpgid(0, 0); para poner al niño en un nuevo grupo de procesos. El padre simplemente continúa (tal vez después de imprimir el PID del niño) - no llama wait().

Cada terminal puede tener solo un grupo de proceso en primer plano, que es el grupo de proceso que actualmente se permite enviar la salida al terminal. Este seguirá siendo el grupo de proceso del que su caparazón es miembro, por lo que su caparazón permanecerá en primer plano.

Si un grupo de proceso en segundo plano intenta leer desde el terminal, se le enviará una señal para detenerla. La salida al terminal todavía está permitida: esto es normal (intente ls & en su caparazón normal). Para implementar el fg comandar en su shell, necesitará el tcsetpgrp() función para cambiar el grupo de proceso de primer plano.

También querrás llamar waitpid() con el WNOHANG Opción regularmente: digamos, inmediatamente antes de mostrar la solicitud de shell. Esto le permitirá detectar cuándo el proceso de fondo ha salido o detenido (o alternativamente, puede manejar el SIGCHLD señal).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top