Warning: Undefined array key "view" in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 2

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 47

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 48

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 49

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 50

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1617/lab-homeworks/index.php on line 51
/* Homework n.8 Modificare l'homework precedente (n.7) sostituendo il canale di comuniciazione offerto dalla coda di messaggi tra padre e figlio con un segmento di memoria condiviso e una coppia di semafori (esattamente due) opportunamente utilizzati per il coordinamento. */ #include #include #include #include #include #include #include #include #define DIM_MSG 4096 #define S_COMMAND 0 #define S_OUTPUT 1 #define STD_IN 0 #define STD_OUT 1 #define STD_ERR 2 int WAIT(int sem_des, int num_semaforo) { struct sembuf operazioni[1] = {{num_semaforo, -1, 0}}; return semop(sem_des, operazioni, 1); } int SIGNAL(int sem_des, int num_semaforo) { struct sembuf operazioni[1] = {{num_semaforo, +1, 0}}; return semop(sem_des, operazioni, 1); } /* si occupa di leggere i comandi dal prompt, di inviarli sul buffer condiviso e di riceverne l'output sullo stesso */ void gestore_terminale(int id_shm, int id_sems) { int len; char *messaggio; if ((messaggio = (char *) shmat(id_shm, NULL, 0)) == (char *) -1) { perror("shmat"); exit(1); } while (1) { /* legge il comando da tastiera e lo inserisce direttamente nel buffer condiviso */ printf("> "); fgets(messaggio, DIM_MSG, stdin); len = strlen(messaggio); if ( messaggio[len-1] == '\n' ) messaggio[len-1] = '\0'; /* segnala la disponibilita' del comando sul buffer, controllando anche se e' il comando di uscita */ if ( strcmp(messaggio, "exit") != 0 ) { SIGNAL(id_sems, S_COMMAND); } else { SIGNAL(id_sems, S_COMMAND); break; } /* NB: non posso fare il SIGNAL prima del confronto: rischierei che il comando sia sovrascritto dall'output */ /* aspetta che sia disponibile l'output sul buffer */ WAIT(id_sems, S_OUTPUT); printf("%s", messaggio); } exit(0); } /* si occupa di ricevere i comandi dalla coda, di eseguirli tramite dei processi figli, di catturarne l'output/error tramite redirezione su pipe e inviarne il risultato indietro con un messaggio */ void esecutore(int id_shm, int id_sems) { char *messaggio; int pipefd[2]; int len; if ((messaggio = (char *) shmat(id_shm, NULL, 0)) == (char *) -1) { perror("shmat"); exit(1); } while (1) { /* aspetta che il comando dia disponibile sul buffer condiviso */ WAIT(id_sems, S_COMMAND); if ( strcmp(messaggio, "exit") == 0 ) break; /* crea una nuova pipe per il nuovo figlio */ if (pipe(pipefd) == -1 ) { perror("pipe"); exit(1); } if ( fork() == 0 ) { /* redireziona lo standard output sulla pipe */ close(STD_OUT); dup(pipefd[1]); /* redireziona lo standard error sulla pipe */ close(STD_ERR); dup(pipefd[1]); /* chiude il canale di lettura sulla pipe */ close(pipefd[0]); execlp(messaggio, messaggio, NULL); fprintf(stderr, "Errore nell'esecuzione di '%s'\n", messaggio); exit(2); } else { /* chiude il canale di scrittura sulla pipe */ close(pipefd[1]); /* legge l'output del comando dalla pipe e lo scrive direttamente sul buffer */ len = read(pipefd[0], messaggio, DIM_MSG-1); messaggio[len] = '\0'; /* segnala la disponibilita' dell'output sul buffer condiviso */ SIGNAL(id_sems, S_OUTPUT); /* chiude il restante canale sulla pipe */ close(pipefd[0]); } } shmctl(id_shm, IPC_RMID, NULL); semctl(id_sems, 0, IPC_RMID, 0); exit(0); } int main() { int id_shm, id_sems; key_t chiave = IPC_PRIVATE; /* crea un segmento di memoria condiviso per scambiarsi messaggi */ if ((id_shm = shmget(chiave, DIM_MSG, IPC_CREAT|IPC_EXCL|0600)) == -1) { perror("shmget"); exit(1); } /* crea 2 semafori (S_COMMAND, S_OUTPUT) */ if ((id_sems = semget(chiave, 2, IPC_CREAT|IPC_EXCL|0600)) == -1) { perror("semget"); exit(1); } // imposta i valori iniziali dei semafori semctl(id_sems, S_COMMAND, SETVAL, 0); semctl(id_sems, S_OUTPUT, SETVAL, 0); if ( fork() != 0 ) gestore_terminale(id_shm, id_sems); else esecutore(id_shm, id_sems); }