Warning: Undefined array key "view" in /var/www/html/wp-content/uploads/classes/so/lab-exams/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/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/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/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/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/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/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/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/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/lab-exams/index.php:2) in /var/www/html/wp-content/uploads/classes/so/lab-exams/index.php on line 51
/* Sistemi Operativi - prova di laboratorio
* compito del 12/06/2016 - soluzione */
#include
#include
#include
#include
#include
#include
#include
#include
#define DIM_LIST 10
#define DIM_BUFFER 1024
/* 4 semafori */
enum SEM_TYPE { S_MUTEX, S_EMPTY, S_FULL_NUM, S_FULL_RES };
/* i tipi di dati che si possono trovare nella lista */
enum DATA_TYPE { T_NUMBER = 0, T_RESIDUE = 1, T_EOF, T_EMPTY };
/* l'elemento di base della lista nella memoria condivisa */
typedef struct {
long number;
char type;
} shm_msg;
int WAIT(int sem_des, short unsigned int sem_num) {
struct sembuf ops[1] = {{sem_num, -1, 0}};
return semop(sem_des, ops, 1);
}
int SIGNAL(int sem_des, short unsigned int sem_num) {
struct sembuf ops[1] = {{sem_num, +1, 0}};
return semop(sem_des, ops, 1);
}
/* il codice del figlio MOD che converte numberi in residui modulo dato */
void child_mod(int sem_des, shm_msg *shared_list, long modulus) {
char eof = 0;
int i;
long count = 0;
while (1) {
WAIT(sem_des, S_FULL_NUM);
WAIT(sem_des, S_MUTEX);
/* cerca un elemento di tipo T_NUMBER e lo converte */
for (i = 0; i < DIM_LIST; i++)
if (shared_list[i].type == T_NUMBER) {
shared_list[i].number %= modulus;
shared_list[i].type = T_RESIDUE;
count++;
break; // converte un elemento alla volta (non indispensabile)
} else if (shared_list[i].type ==
T_EOF) { // se incontra T_EOF ne tiene nota
eof = 1;
}
SIGNAL(sem_des, S_MUTEX);
SIGNAL(sem_des, S_FULL_RES);
/* se ho incontrato T_EOF e ho esaminato l'intera lista all'ultima
iterazione, allora ho finito */
if (eof && (i == DIM_LIST))
break;
}
fprintf(stderr, "M: %lu modded elements\n", count);
exit(0);
}
/* il codice del figlio OUT che visualizza sullo standard output i residui */
void child_out(int sem_des, shm_msg *shared_list) {
char eof = 0;
int i;
long count = 0;
while (1) {
WAIT(sem_des, S_FULL_RES);
WAIT(sem_des, S_MUTEX);
/* cerca un elemento di tipo T_RESIDUE e lo stampa
sullo standard output */
for (i = 0; i < DIM_LIST; i++)
if (shared_list[i].type == T_RESIDUE) {
shared_list[i].type = T_EMPTY;
printf("%lu\n", shared_list[i].number);
count++;
break; // stampa un elemento alla volta (non indispensabile)
} else if (shared_list[i].type ==
T_EOF) { // se incontra T_EOF ne tiene nota
eof = 1;
}
SIGNAL(sem_des, S_MUTEX);
SIGNAL(sem_des, S_EMPTY);
/* se ho incontrato T_EOF e ho esaminato l'intera lista all'ultima
iterazione, allora ho finito */
if (eof && (i == DIM_LIST))
break;
}
fprintf(stderr, "O: %lu outputed elements\n", count);
exit(0);
}
int main(int argc, char *argv[]) {
shm_msg *shared_list;
int shm_des, sem_des;
long modulus;
struct stat statbuf;
FILE *file_input;
long count = 0;
if (argc != 3) {
printf("usage: %s \n", argv[0]);
exit(1);
}
if ((stat(argv[1], &statbuf) == -1) || !S_ISREG(statbuf.st_mode)) {
perror(argv[1]);
exit(1);
}
if ((modulus = atol(argv[2])) <= 0) {
fprintf(stderr, "wrong modulus\n");
exit(1);
}
if ((shm_des = shmget(IPC_PRIVATE, sizeof(shm_msg) * DIM_LIST,
IPC_CREAT | 0600)) == -1) {
perror("shmget");
exit(1);
}
if ((shared_list = (shm_msg *)shmat(shm_des, NULL, 0)) == (shm_msg *)-1) {
perror("shmat");
exit(1);
}
if ((sem_des = semget(IPC_PRIVATE, 4, IPC_CREAT | 0600)) == -1) {
perror("semget");
exit(1);
}
if (semctl(sem_des, S_MUTEX, SETVAL, 1) == -1) {
perror("semctl SETVAL S_MUTEX");
exit(1);
}
if (semctl(sem_des, S_EMPTY, SETVAL, DIM_LIST) == -1) {
perror("semctl SETVAL S_EMPTY");
exit(1);
}
if (semctl(sem_des, S_FULL_NUM, SETVAL, 0) == -1) {
perror("semctl SETVAL S_FULL_NUM");
exit(1);
}
if (semctl(sem_des, S_FULL_RES, SETVAL, 0) == -1) {
perror("semctl SETVAL S_FULL_RES");
exit(1);
}
if (fork() == 0) {
child_out(sem_des, shared_list);
} else if (fork() == 0) {
child_mod(sem_des, shared_list, modulus);
} else {
char buffer[DIM_BUFFER];
long number;
/* rende vuoti gli elementi iniziali della lista condivisa */
for (int i = 0; i < DIM_LIST; i++)
shared_list[i].type = T_EMPTY;
if ((file_input = fopen(argv[1], "r")) == NULL) {
perror(argv[1]);
exit(1);
}
while (fgets(buffer, DIM_BUFFER, file_input)) {
number = atol(buffer);
WAIT(sem_des, S_EMPTY);
WAIT(sem_des, S_MUTEX);
/* cerca uno slot vuoto... sicuro di trovarlo */
for (int i = 0; i < DIM_LIST; i++) {
if (shared_list[i].type == T_EMPTY) {
shared_list[i].type = T_NUMBER;
shared_list[i].number = number;
break;
}
}
SIGNAL(sem_des, S_MUTEX);
SIGNAL(sem_des, S_FULL_NUM);
count++;
}
fprintf(stderr, "P: %lu inserted elements\n", count);
/* inserisce un elemento di tipo T_EOF che segnalerà l'assenza di
* ulteriori nuovi numeri */
WAIT(sem_des, S_EMPTY);
WAIT(sem_des, S_MUTEX);
for (int i = 0; i < DIM_LIST; i++) {
if (shared_list[i].type == T_EMPTY) {
shared_list[i].type = T_EOF;
break;
}
}
SIGNAL(sem_des, S_MUTEX);
SIGNAL(sem_des, S_FULL_NUM);
SIGNAL(sem_des, S_FULL_RES);
wait(NULL);
wait(NULL);
shmctl(shm_des, IPC_RMID, NULL);
semctl(sem_des, 0, IPC_RMID, 0);
}
exit(0);
}