Advertisement
Guest User

Untitled

a guest
Apr 2nd, 2020
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.65 KB | None | 0 0
  1. /*
  2. Iată o soluție incompletă, în sensul că s-a omis codul efectiv de punere și de scoatere a lacătului pentru acces exclusiv la fișierul de date partajat,
  3. precum și tratarea anumitor excepții (i.e., atunci când se încearcă extragerea unei cantități mai mari decât cea disponibilă în rezervorul stației PECO).
  4. */
  5. // TODO: respectivele omisiuni vă rămân ca temă să le completați dvs. !!!
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #include <unistd.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <fcntl.h>
  15.  
  16. void initializare_fisier_date();
  17. /*
  18. * Pentru început, avem nevoie de o rutină ajutătoare, care să creeze conținutul inițial al fișierului de date partajat.
  19. * Se va crea fișierul și va conține un număr real, stocat în format binar, reprezentând cantitatea inițială de combustibil din rezervor.
  20. * Vom apela programul cu opțiunea -i pentru a invoca această rutină de inițializare.
  21. */
  22.  
  23. void afisare_fisier_date();
  24. /*
  25. * Similar, la finalul tuturor actualizărilor, vom avea nevoie de o altă rutină ajutătoare, care să ne afișeze conținutul final din rezervor.
  26. * Vom apela programul cu opțiunea -o pentru a invoca această rutină de afișare finală.
  27. */
  28.  
  29. void secventa_de_actualizari(int n, char* nr[]);
  30. /*
  31. * Rutina principală a programului, care va executa secvența de actualizări primită în linia de comandă, în manieră concurentă,
  32. * conform celor specificate în enunțul problemei.
  33. * Observație: rutina principală nu este implementată în întregime mai jos, ci vă rămâne dvs. sarcina să completați "bucățile" de cod
  34. * care lipsesc (indicate prin comentarii TODO).
  35. */
  36.  
  37. int main(int argc, char* argv[])
  38. {
  39. if(argc == 1)
  40. {
  41. fprintf(stderr, "Eroare: programul trebuie apelat cu optiunile: -i, -o, sau cu o secventa de numere reale...\n"); return 1;
  42. }
  43.  
  44. /* Cazul de inițializare a fișierului de date. */
  45. if( strcmp(argv[1],"-i") == 0 )
  46. {
  47. initializare_fisier_date(); return 0;
  48. }
  49.  
  50. /* Cazul de afișare a fișierului de date. */
  51. if( strcmp(argv[1],"-o") == 0 )
  52. {
  53. afisare_fisier_date(); return 0;
  54. }
  55.  
  56. /* Cazul general: actualizarea fișierului de date. */
  57. secventa_de_actualizari(argc, argv);
  58. return 0;
  59. }
  60.  
  61.  
  62. void initializare_fisier_date()
  63. {/* Funcționalitate: inițializarea fișierului de date. */
  64.  
  65. int fd;
  66. float val;
  67.  
  68. printf("Dati cantitatea initiala de combustibil (i.e., un numar real pozitiv): ");
  69. while( (1 != scanf("%f", &val)) && (val < 0) ) { fprintf(stderr,"Eroare: nu ati introdus un numar real pozitiv! Incercati din nou..."); }
  70.  
  71. if(-1 == (fd = creat("peco.bin", 0600) ) )
  72. {
  73. perror("Eroare la crearea fisierului de date..."); exit(2);
  74. }
  75.  
  76. if(-1 == write(fd, &val, sizeof(float) ) )
  77. {
  78. perror("Eroare la scrierea valorii initiale in fisierul de date..."); exit(3);
  79. }
  80.  
  81. close(fd);
  82. }
  83.  
  84.  
  85. void afisare_fisier_date()
  86. {/* Funcționalitate: afișarea fișierului de date. */
  87.  
  88. int fd;
  89. float val;
  90.  
  91. if ( -1 == (fd = open("peco.bin", O_RDONLY) ) )
  92. {
  93. perror("Eroare la deschiderea pentru afisare a fisierului de date..."); exit(4);
  94. }
  95.  
  96. if (-1 == read(fd, &val, sizeof(float) ) )
  97. {
  98. perror("Eroare la citirea valorii finale din fisierul de date..."); exit(5);
  99. }
  100.  
  101. close(fd);
  102. printf("Stocul final de combustibil este: %f litri de combustibil.\n", val);
  103. }
  104.  
  105.  
  106. void secventa_de_actualizari(int n, char* nr[])
  107. { /* Funcționalitate: realizarea secvenței de operații de actualizare a fișierului de date. */
  108.  
  109. float valoare, stoc;
  110. int fd,i;
  111.  
  112. if ( -1 == (fd = open("peco.bin", O_RDWR) ) )
  113. {
  114. perror("Eroare la deschiderea pentru actualizare a fisierului de date..."); exit(6);
  115. }
  116.  
  117. srandom( getpid() ); // Inițializarea generatorului de numere aleatoare.
  118.  
  119. for(i = 1; i < n; i++) // Iterăm prin secvența de numere reale specificată în linia de comandă.
  120. {
  121. if(1 != sscanf(nr[i], "%f", &valoare)) // Facem conversie de la string la float.
  122. {
  123. fprintf(stderr, "[PID: %d] Eroare: ati specificat o valoare invalida drept argument de tip numar real : %s !\n", getpid(), nr[i] );
  124. exit(7);
  125. }
  126.  
  127. /* Începutul secțiunii critice! */
  128.  
  129.  
  130. fd = open("file.txt", O_WRONLY | O_CREAT | O_TRUNC, 0600);
  131. lck.l_type = F_WRLCK;
  132. lck.l_whence = SEEK_SET;
  133. lck.l_start = 0;
  134. lck.l_len = sizeof(float);
  135.  
  136. if ( -1 == (fcntl(fd, F_SETLKW, &lck) ) ) {
  137. exit(1);
  138. }
  139. write(fd, argv[1], 1);
  140.  
  141. if(-1 == lseek(fd, 0, SEEK_SET) ) // (Re)poziționăm cursorul la începutul fișierului.
  142. {
  143. perror("Eroare la repozitionarea in fisierul de date, pentru citire..."); exit(8);
  144. }
  145. if (-1 == read(fd, &stoc, sizeof(float) ) )
  146. {
  147. perror("Eroare la citirea valorii din fisierul de date..."); exit(9);
  148. }
  149.  
  150. printf("[PID: %d] Se adauga/extrage in/din rezervor cantitatea de %f litri de combustibil.\n", getpid(), valoare );
  151.  
  152. stoc = stoc + valoare;
  153. /*
  154. if(stoc<0) exit(1)
  155. ... // TODO: implementați singuri tratarea excepției: stoc negativ
  156. ... // Varianta 1: refuzarea operației de extragere, cu un mesaj informativ în acest sens.
  157. ... // Varianta 2: realizarea unei extrageri parțiale, i.e. se extrage doar cât e în stoc, nu cât s-a cerut, cu un mesaj informativ în acest sens.
  158. ... // Varianta 3: interogarea utilizatorului, ce variantă de rezolvare dorește? , i.e. varianta 1 sau varianta 2 de mai sus?
  159. */
  160.  
  161. if(-1 == lseek(fd, 0, SEEK_SET) ) // Repoziționăm cursorul la începutul fișierului.
  162. {
  163. perror("Eroare la repozitionarea in fisierul de date, pentru scriere..."); exit(10);
  164. }
  165. if (-1 == write(fd, &stoc, sizeof(float) ) )
  166. {
  167. perror("Eroare la scrierea valorii actualizate in fisierul de date..."); exit(11);
  168. }
  169.  
  170. /* Sfârșitul secțiunii critice! */
  171. /*
  172. ... // TODO: implementați singuri scoaterea lacătului de pe fișier.
  173. */
  174.  
  175. lck.l_type = F_UNLCK;
  176. if ( -1 == (fcntl(fd, F_SETLKW, &lck) ) ) {
  177. exit(1);
  178. }
  179. sleep( random() % 5 ); // Facem o pauză aleatoare, de maxim 4 secunde, înainte de a continua cu următoarea iterație.
  180. }
  181.  
  182. close(fd);
  183. printf("[PID: %d] Am terminat de procesat secventa de actualizari.", getpid());
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement