#include #include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include /* * https://github.com/marcotessarotto/exOpSys/tree/master/006.3signals4ipc * * processo padre e processo figlio * processo padre controlla il processo figlio attraverso dei signal * SIGUSR1 ("avvia la produzione"), * SIGUSR2 ("ferma la produzione"), * SIGTERM (fa terminare il processo figlio) * * processo padre riceve comandi da stdin: * +: avvia la produzione * -: ferma la produzione * q: termina tutto * */ pid_t child_pid; int cookie_machine_state; int pipe_fd[2]; void * worker_thread_entry_point(void * arg) { while (1) { while (cookie_machine_state) { printf("[child] COOKIE\n"); sleep(3); } // ora cookie_machine_state == 0 printf("[child] prima di pause()\n"); pause(); printf("[child] dopo pause()\n"); } return NULL; } void child_process_signal_handler(int signum) { if (signum == SIGALRM) { printf("[signal handler] ALARM\n"); exit(0); } else if (signum == SIGUSR1) { printf("[signal handler] SIGUSR1\n"); } } void child_process() { // legge dalla pipe i comandi // il while "utilizza" il main thread // while (read(....)) { ... } // creo un thread che "lavorerà" (produrrà i "cookies") int res; pthread_t t1; res = pthread_create(&t1, NULL, worker_thread_entry_point, NULL); if (res != 0) { perror("pthread_create"); exit(1); } // chiudere l'estremità di scrittura della pipe if (close(pipe_fd[1]) == -1) { perror("close"); } if (signal(SIGALRM, child_process_signal_handler) == SIG_ERR) { perror("signal"); exit(1); } if (signal(SIGUSR1, child_process_signal_handler) == SIG_ERR) { perror("signal"); exit(1); } char command; while ((res = read(pipe_fd[0], &command, sizeof(command))) > 0) { switch (command) { case '+': cookie_machine_state = 1; pthread_kill(t1, SIGUSR1); break; case '-': cookie_machine_state = 0; // pthread_kill(t1, SIGUSR1); break; case 'q': // shutdown del macchinario cookie_machine_state = 0; // diamo il tempo alla macchina di spegnersi if (close(pipe_fd[0]) == -1) { perror("close"); } printf("[child] prima di alarm(3) e pause()\n"); alarm(3); pause(); // correzione 20210511 } } } void parent_process() { // chiudere l'estremità di lettura della pipe if (close(pipe_fd[0]) == -1) { perror("close"); exit(1); } printf("[parent] prima di sleep(2)\n"); // dormire 2 secondi sleep(2); printf("[parent] avvio la produzione\n"); char command; command = '+'; if (write(pipe_fd[1], &command, sizeof(command)) == -1) { perror("write"); exit(1); } printf("[parent] prima di sleep(10)\n"); // dormire 10 secondi sleep(10); printf("[parent] fermo la produzione\n"); command = '-'; if (write(pipe_fd[1], &command, sizeof(command)) == -1) { perror("write"); exit(1); } printf("[parent] prima di sleep(2)\n"); // dormire 2 secondi sleep(2); printf("[parent] termino il processo figlio\n"); command = 'q'; if (write(pipe_fd[1], &command, sizeof(command)) == -1) { perror("write"); exit(1); } if (wait(NULL) == -1) { perror("wait"); } printf("[parent] bye\n"); exit(0); } int main() { // pipe: // creare una pipe prima di invocare fork() // utilizzare la pipe per inviare comandi al processo figlio if (pipe(pipe_fd) == -1) { perror("pipe"); exit(1); } switch (child_pid = fork()) { case -1: perror("fork"); exit(1); case 0: child_process(); default: parent_process(); } }