Advertisement
Guest User

numbers-mod

a guest
Jan 29th, 2020
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.69 KB | None | 0 0
  1. /* Sistemi Operativi - prova di laboratorio
  2.  * Il programma dovrà leggere dal file di input specificato una serie di numeri (uno per riga)
  3.  * e dovrà dare in output gli stessi una volta applicata la funzione f(x) = x mod n, dove n è
  4.  * il modulo specificato sulla riga di comando.
  5.  * Suggerimenti: il padre P dovrebbe bloccarsi se il buffer dovesse risultare pieno;
  6.  * anche il figlio Mod dovrebbe bloccarsi se, nel tentativo di inserire il suo record, il
  7.  * buffer dovesse risultare pieno; trovare un opportuno meccanismo di segnalazione per la fine
  8.  * dei dati affinché i consumatori non si blocchino all'infinito.
  9.  *          [SH_MEM]<---[PADRE]<---{file}
  10.  *             |
  11.  *   [MOD]<--->|<--->[OUT]
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <sys/ipc.h>
  17. #include <sys/sem.h>
  18. #include <sys/shm.h>
  19. #include <sys/stat.h>
  20. #include <sys/wait.h>
  21. #include <unistd.h>
  22.  
  23. #define DIM_LIST 10 //numero di record da inserire
  24. #define DIM_BUFFER 1024
  25.  
  26. /* 4 semafori */
  27. enum SEM_TYPE { S_MUTEX, S_EMPTY, S_FULL_NUM, S_FULL_RES };
  28.  
  29. /* i tipi di dati che si possono trovare nella lista */
  30. enum DATA_TYPE { T_NUMBER = 0, T_RESIDUE = 1, T_EOF, T_EMPTY };
  31.  
  32. /* l'elemento di base della lista nella memoria condivisa */
  33. typedef struct {
  34.     long number;
  35.     char type;
  36. } shm_msg;
  37.  
  38. int WAIT(int sem_des, short unsigned int sem_num) {
  39.     struct sembuf ops[1] = {{sem_num, -1, 0}};
  40.  
  41.     return semop(sem_des, ops, 1);
  42. }
  43. int SIGNAL(int sem_des, short unsigned int sem_num) {
  44.     struct sembuf ops[1] = {{sem_num, +1, 0}};
  45.  
  46.     return semop(sem_des, ops, 1);
  47. }
  48.  
  49. /* il processo figlio Mod dovrà estrarre dal buffer condiviso, non appena disponibili,
  50.  * record del tipo [x, 0] e reinserirne altrettanti del tipo [f(x), 1]*/
  51. void child_mod(int sem_des, shm_msg *shared_list, long modulus) {
  52.     char eof = 0;
  53.     int i;
  54.     long count = 0;
  55.  
  56.     while (1) {
  57.         WAIT(sem_des, S_FULL_NUM);
  58.         WAIT(sem_des, S_MUTEX);
  59.  
  60.         /* cerca un elemento di tipo T_NUMBER e lo converte */
  61.         for (i = 0; i < DIM_LIST; i++)
  62.             if (shared_list[i].type == T_NUMBER) {
  63.                 shared_list[i].number %= modulus;
  64.                 shared_list[i].type = T_RESIDUE;
  65.                 count++;
  66.                 break; // converte un elemento alla volta (non indispensabile)
  67.             } else if (shared_list[i].type ==
  68.                        T_EOF) { // se incontra T_EOF ne tiene nota
  69.                 eof = 1;
  70.             }
  71.  
  72.         SIGNAL(sem_des, S_MUTEX);
  73.         SIGNAL(sem_des, S_FULL_RES);
  74.  
  75.         /* se ho incontrato T_EOF e ho esaminato l'intera lista all'ultima
  76.            iterazione, allora ho finito */
  77.         if (eof && (i == DIM_LIST))
  78.             break;
  79.     }
  80.  
  81.     fprintf(stderr, "M: %lu modded elements\n", count);
  82.  
  83.     exit(0);
  84. }
  85.  
  86. /* il processo figlio Out dovrà estrarre dal buffer condiviso, non appena disponibili,
  87.  * record del tipo [y, 1] e dare in output il numero y. */
  88. void child_out(int sem_des, shm_msg *shared_list) {
  89.     char eof = 0;
  90.     int i;
  91.     long count = 0;
  92.  
  93.     while (1) {
  94.         WAIT(sem_des, S_FULL_RES);
  95.         WAIT(sem_des, S_MUTEX);
  96.  
  97.         /* cerca un elemento di tipo T_RESIDUE e lo stampa
  98.            sullo standard output */
  99.         for (i = 0; i < DIM_LIST; i++)
  100.             if (shared_list[i].type == T_RESIDUE) {
  101.                 shared_list[i].type = T_EMPTY;
  102.                 printf("%lu\n", shared_list[i].number);
  103.                 count++;
  104.                 break; // stampa un elemento alla volta (non indispensabile)
  105.             } else if (shared_list[i].type ==
  106.                        T_EOF) { // se incontra T_EOF ne tiene nota
  107.                 eof = 1;
  108.             }
  109.  
  110.         SIGNAL(sem_des, S_MUTEX);
  111.         SIGNAL(sem_des, S_EMPTY);
  112.  
  113.         /* se ho incontrato T_EOF e ho esaminato l'intera lista all'ultima
  114.             iterazione, allora ho finito */
  115.         if (eof && (i == DIM_LIST))
  116.             break;
  117.     }
  118.  
  119.     fprintf(stderr, "O: %lu outputed elements\n", count);
  120.     exit(0);
  121. }
  122.  
  123. int main(int argc, char *argv[]) {
  124.     /* dichiarazione delle variabili */
  125.     shm_msg *shared_list;
  126.     int shm_des, sem_des;
  127.     long modulus;
  128.     struct stat statbuf;
  129.     FILE *file_input;
  130.     long count = 0;
  131.     /* controllo sui parametri */
  132.     if (argc != 3) {
  133.         printf("usage: %s <input file> <modulus numbe>\n", argv[0]);
  134.         exit(1);
  135.     }
  136.     /* controllo sul file di testo inserito*/
  137.     if ((stat(argv[1], &statbuf) == -1) || !S_ISREG(statbuf.st_mode)) {
  138.         perror(argv[1]);
  139.         exit(1);
  140.     }
  141.     /* controllo sul modulo inserito, non negativo*/
  142.     if ((modulus = atol(argv[2])) <= 0) {
  143.         fprintf(stderr, "wrong modulus\n");
  144.         exit(1);
  145.     }
  146.     /* creazione della memoria condivisa*/
  147.     if ((shm_des = shmget(IPC_PRIVATE, sizeof(shm_msg) * DIM_LIST,
  148.                           IPC_CREAT | 0600)) == -1) {
  149.         perror("shmget");
  150.         exit(1);
  151.     }
  152.     /*mappatura dell'area*/
  153.     if ((shared_list = (shm_msg *)shmat(shm_des, NULL, 0)) == (shm_msg *)-1) {
  154.         perror("shmat");
  155.         exit(1);
  156.     }
  157.     /* creazione dei semafori*/
  158.     if ((sem_des = semget(IPC_PRIVATE, 4, IPC_CREAT | 0600)) == -1) {
  159.         perror("semget");
  160.         exit(1);
  161.     }
  162.     /*settaggio dei valori per tutti i semafori*/
  163.     if (semctl(sem_des, S_MUTEX, SETVAL, 1) == -1) {
  164.         perror("semctl SETVAL S_MUTEX");
  165.         exit(1);
  166.     }
  167.     if (semctl(sem_des, S_EMPTY, SETVAL, DIM_LIST) == -1) {
  168.         perror("semctl SETVAL S_EMPTY");
  169.         exit(1);
  170.     }
  171.     if (semctl(sem_des, S_FULL_NUM, SETVAL, 0) == -1) {
  172.         perror("semctl SETVAL S_FULL_NUM");
  173.         exit(1);
  174.     }
  175.     if (semctl(sem_des, S_FULL_RES, SETVAL, 0) == -1) {
  176.         perror("semctl SETVAL S_FULL_RES");
  177.         exit(1);
  178.     }
  179.  
  180.     if (fork() == 0) {
  181.         child_out(sem_des, shared_list);
  182.     } else if (fork() == 0) {
  183.         child_mod(sem_des, shared_list, modulus);
  184.     } else {
  185.         /* il processo padre P dovrà leggere il file specificato inserendo, per ogni numero x
  186.          *  letto, il record [x, 0] nel buffer condiviso;  */
  187.         char buffer[DIM_BUFFER];
  188.         long number;
  189.         /* rende vuoti gli elementi iniziali della lista condivisa */
  190.         for (int i = 0; i < DIM_LIST; i++)
  191.             shared_list[i].type = T_EMPTY;
  192.  
  193.         if ((file_input = fopen(argv[1], "r")) == NULL) {
  194.             perror(argv[1]);
  195.             exit(1);
  196.         }
  197.  
  198.         while (fgets(buffer, DIM_BUFFER, file_input)) {
  199.             number = atol(buffer);
  200.  
  201.             WAIT(sem_des, S_EMPTY);
  202.             WAIT(sem_des, S_MUTEX);
  203.  
  204.             /* cerca uno slot vuoto... sicuro di trovarlo */
  205.             for (int i = 0; i < DIM_LIST; i++) {
  206.                 if (shared_list[i].type == T_EMPTY) {
  207.                     shared_list[i].type = T_NUMBER;
  208.                     shared_list[i].number = number;
  209.                     break;
  210.                 }
  211.             }
  212.  
  213.             SIGNAL(sem_des, S_MUTEX);
  214.             SIGNAL(sem_des, S_FULL_NUM);
  215.  
  216.             count++;
  217.         }
  218.  
  219.         fprintf(stderr, "P: %lu inserted elements\n", count);
  220.  
  221.         /* inserisce un elemento di tipo T_EOF che segnalerà l'assenza di
  222.          * ulteriori nuovi numeri */
  223.         WAIT(sem_des, S_EMPTY);
  224.         WAIT(sem_des, S_MUTEX);
  225.  
  226.         for (int i = 0; i < DIM_LIST; i++) {
  227.             if (shared_list[i].type == T_EMPTY) {
  228.                 shared_list[i].type = T_EOF;
  229.                 break;
  230.             }
  231.         }
  232.  
  233.         SIGNAL(sem_des, S_MUTEX);
  234.  
  235.         SIGNAL(sem_des, S_FULL_NUM);
  236.         SIGNAL(sem_des, S_FULL_RES);
  237.  
  238.         wait(NULL);
  239.         wait(NULL);
  240.  
  241.         shmctl(shm_des, IPC_RMID, NULL);
  242.         semctl(sem_des, 0, IPC_RMID, 0);
  243.     }
  244.  
  245.     exit(0);
  246. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement