c - sistema - fork() ejemplo
En cuanto a los procesos en segundo plano que usan fork() y los procesos hijo en mi shell ficticio (1)
Intento crear un programa de shell simple en C. Lo que necesito hacer es proporcionar al usuario un mensaje en el que puedan ejecutar otros programas locales. Puedo hacerlo bien, usando un tenedor () en el que el proceso padre espera () en el niño y el niño en el programa ().
Sin embargo, si el carácter ''&'' se agrega al final del comando del usuario, necesito que el programa se ejecute en segundo plano, lo que significa que necesito que el padre NO espere en el proceso hijo, sino que devuelva inmediatamente el mensaje al usuario, mientras permite que el proceso en segundo plano continúe ejecutándose, pero no le permite mostrar nada en la pantalla. Solo quiero poder verificar que todavía existe a través del comando ps.
Traté de entender la idea detrás de usar fork () para crear un niño, luego tener el niño fork () nuevamente para crear un tipo de nieto, y luego salir inmediatamente () - el proceso secundario. es decir, huérfano el nieto. Supuestamente, esto permite que el padre todavía espere al niño, pero dado que el niño termina de manera efectiva casi de inmediato, es como si no esperara en absoluto. ¿Algo sobre la locura zombie? No lo 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, me pasan cosas desagradables 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 es bastante erróneo. Me pregunto si toda esta cosa de nieto es incluso la ruta que debo tomar, y si es así, ¿qué ocurre 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 claro, necesito que el proceso que estoy ejecutando en segundo plano no vuelva a hacer ningún sonido, incluso si tiene un ciclo infinito de instrucciones de impresión o algo así. Solo quiero asegurarme de que todavía se ejecuta 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 subsiguiente determine el valor booleano de ''fondo'', disculpe la confusión
No desea utilizar el método double- fork()
en un shell, esto es, para escribir daemons que específicamente desean escapar de la supervisión del shell que los ejecutó.
En su lugar, la forma de duplicar el comportamiento de &
shells existentes es llamar a fork()
, luego en la llamada de niño setpgid(0, 0);
para poner al niño en un nuevo grupo de proceso . El padre simplemente continúa (quizás después de imprimir el PID
del niño) - no llama a wait()
.
Cada terminal puede tener solo un grupo de procesos en primer plano, que es el grupo de procesos que actualmente está autorizado para enviar salidas al terminal. Este seguirá siendo el grupo de procesos del que su shell es miembro, por lo que su shell permanecerá en primer plano.
Si un grupo de proceso en segundo plano intenta leer desde el terminal, se enviará una señal para detenerlo. La salida al terminal aún está permitida, esto es normal (pruebe ls &
en su shell normal). Para implementar el comando fg
en su shell, necesitará la función tcsetpgrp()
para cambiar el grupo de procesos en primer plano.
También querrá llamar a waitpid()
con la opción WNOHANG
con regularidad, es decir, inmediatamente antes de mostrar el indicador del shell. Esto le permitirá detectar cuando el proceso de fondo se ha salido o parado (o alternativamente, puede manejar la señal SIGCHLD
).