Warning: Undefined array key "view" in /var/www/html/wp-content/uploads/classes/so/1920/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/1920/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/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/1920/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/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/1920/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/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/1920/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/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/1920/lab-homeworks/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/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);
}