Advertisement
Guest User

Untitled

a guest
Apr 9th, 2020
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.15 KB | None | 0 0
  1. #include <unistd.h>
  2. #include <sys/mman.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define handle_error(msg) \
  10.     { perror(msg); exit(EXIT_FAILURE); }
  11.  
  12. int main(int argc, char *argv[])
  13. {
  14.     char *map_addr;
  15.     int fd;
  16.     struct stat sb;
  17.     off_t offset, pa_offset;
  18.     size_t length, adjusted_length;
  19.     ssize_t codw;
  20.     char to_be_replaced[10] = { '0','1','2','3','4','5','6','7','8','9' };   ///CARACTERELE CARE SE VOR INLOCUI DIN FISIER
  21.     char replace_with[10] = { 'q','w','e','r','t','y','u','i','o','p' };    ///CARACTERELE CU CARE SE VA INLOCUI IN FISIER
  22.  
  23.     /* Determinăm dimensiunea paginilor corespunzătoare arhitecturii hardware a calculatorului dvs. */
  24.     long PageSize = sysconf(_SC_PAGE_SIZE);
  25.     if (PageSize == -1)
  26.         handle_error("Error at sysconf");
  27.     fprintf(stderr, "Notification: the page size on your hardware system is: %ld bytes.\n", PageSize);
  28.  
  29.  
  30.     /* Validăm argumentele din linia de comandă. */
  31.     if (argc < 3 || argc > 4) {
  32.         fprintf(stderr, "Commandline:  %s file offset [length]\n", argv[0]);
  33.         exit(EXIT_FAILURE);
  34.     }
  35.  
  36.     fd = open(argv[1], O_RDWR);
  37.     if (fd == -1)
  38.         handle_error("Error at open");
  39.  
  40.     if (fstat(fd, &sb) == -1)   /* To obtain file size */
  41.         handle_error("Error at fstat");
  42.  
  43.     offset = atoi(argv[2]);
  44.     fprintf(stderr, "Notification: the specified offset was: %ld\n", offset);
  45.  
  46.     if (offset >= sb.st_size) {
  47.         fprintf(stderr, "Error: offset is past end of file\n");
  48.         exit(EXIT_FAILURE);
  49.     }
  50.  
  51.     pa_offset = offset & ~(PageSize - 1);   /* offset for mmap() must be page aligned */
  52.     fprintf(stderr, "Notification: the page-aligned ajusted offset is: %ld\n", pa_offset);
  53.     /* Aici, practic am calculat câtul întreg al împărțirii offset-ului la dimensiunea paginii, folosind operatori pe biți. */
  54.  
  55.     if (argc == 4) {
  56.         length = atoi(argv[3]);
  57.         fprintf(stderr, "Notification: the specified length was: %ld\n", length);
  58.  
  59.         if (offset + length > sb.st_size)
  60.             length = sb.st_size - offset;  /* Can't display bytes past end of file */
  61.     }
  62.     else {    /* No length arg ==> display to end of file */
  63.         length = sb.st_size - offset;
  64.     }
  65.     fprintf(stderr, "Notification: the corrected length (taking EOF into account) is: %ld\n", length);
  66.  
  67.     adjusted_length = length + offset - pa_offset;
  68.     fprintf(stderr, "Notification: the adjusted length (to the page-aligned offset) is: %ld\n", adjusted_length);
  69.    
  70.  
  71.     /* Apelul de mapare a porțiunii de fișier specificate, în memorie. */
  72.     map_addr = mmap( NULL,                   // Se va crea o mapare începând de la o adresă page-aligned aleasă de kernel (și returnată în map_addr)
  73.                      adjusted_length,        // Lungimea aliniată (i.e. ajustată page-aligned) a mapării (calculată mai sus)
  74.                      PROT_READ | PROT_WRITE, // Tipul de protecție a mapării: paginile mapării vor permite accese în citire și în scriere
  75.                      MAP_SHARED,             // Maparea este partajată (altfel, ca mapare privată, nu se salvează nimic în fișierul de pe disc, la final)
  76.                      fd,                     // Descriptorul de fișier, din care se citesc octeții corespunzători porțiunii mapate în memorie
  77.                      pa_offset               // Offset-ul (deplasamentul) aliniat (i.e. ajustat page-aligned), de la care începe porțiunea de fișier mapată
  78.                );                            //   în memorie, i.e. porțiunea din fișier din care se citesc cei actual_length octeți, în maparea din memorie
  79.     if (map_addr == MAP_FAILED)
  80.         handle_error("Error at mmap");
  81.     fprintf(stderr, "Notification: A file mapping in memory was created, for the file: %s\n", argv[1]);
  82.     fprintf(stderr, "Notification: \tthe mapping corresponds to the file's content starting at aligned offset: %ld, and with the length: %ld\n",
  83.                      pa_offset, adjusted_length);
  84.  
  85.     long mmap_size_in_pages = ( adjusted_length % PageSize ? 1 : 0 ) + ( adjusted_length / PageSize ); // Notă: și aici am fi putut folosi operatori pe biți!
  86.     /* Aici, practic am calculat partea întreagă superioară a raportului dintre valorile adjusted_length și PageSize. */
  87.     fprintf(stderr, "Notification: \tthe length/size of the mapping in memory is: %ld page(s).\n", mmap_size_in_pages);
  88.  
  89.     /* După crearea mapării, descriptorul de fișier poate fi închis imediat, fără a se invalida maparea ! */
  90.     if (-1 == close(fd) )
  91.         handle_error("Error at close");
  92.  
  93.     /* Scriem pe ecran (stdout) conținutul mapării. Mai precis, afișăm doar zona mapată din fișier (fără începutul ei), nu întreaga mapare ! */
  94.     printf("\nThe initial content of the mapping (read from the file), started from the original, non-aligned, offset, is the following:\n");
  95.     codw = write(STDOUT_FILENO, map_addr + offset - pa_offset, length);
  96.     if (codw == -1)
  97.         handle_error("Error at 1st write on screen");
  98.     if (codw != length) {
  99.         fprintf(stderr, "Error at 1st write on screen: partial write completed.\n");
  100.         exit(EXIT_FAILURE);
  101.     }
  102.  
  103.     int i;
  104.     for (i = 0; i < adjusted_length; i++) {  
  105.         for (int j = 0; j < 10; ++j) {
  106.             if (*map_addr + 1) == to_be_replaced[j]{
  107.                 *(map_addr + i) = replace_with[j];
  108.             break;    ///AVOID MULTIPLE REPLACEMENTS
  109.             }
  110.         }
  111.        }
  112.    
  113.  
  114.     /* Scriem pe ecran (stdout) conținutul mapării. Mai precis, afișăm doar zona mapată din fișier (fără începutul ei), nu întreaga mapare ! */
  115.     printf("\nThe modified content of the mapping, started from the original, non-aligned, offset, is the following:\n");
  116.     codw = write(STDOUT_FILENO, map_addr + offset - pa_offset, length);
  117.     if (codw == -1)
  118.         handle_error("Error at 2nd write on screen");
  119.     if (codw != length) {
  120.         fprintf(stderr, "Error at 2nd write on screen: partial write completed.\n");
  121.         exit(EXIT_FAILURE);
  122.     }
  123.  
  124.     /* Ne asigurăm că modificările, operate în memorie asupra mapării, sunt salvate pe disc înainte de "ștergerea" mapării. */
  125.     if (-1 == msync(map_addr, adjusted_length, MS_SYNC) )
  126.         handle_error("Error at msync");
  127.     /* De data aceasta, maparea fiind de tip shared, vei observa că fișierul este actualizat la final pe disc!
  128.        Făcând un număr mare de execuții ale programului fără msync(), cu aceleași date de intrare, veți observa că pentru un anumit procent, p%, dintre execuții,
  129.        "race"-ul va fi câștigat de administratorul de memorie (i.e., veți vedea că fișierul este actualizat la final), iar pentru restul de (100-p)% dintre ele,
  130.        veți observa că "race"-ul va fi câștigat de apelul munmap() de mai jos (i.e., veți vedea că fișierul NU este actualizat la final).  */
  131.  
  132.  
  133.     // "Ștergem/distrugem" maparea creată anterior.
  134.     if (-1 == munmap(map_addr, adjusted_length) )
  135.         handle_error("Error at munmap");
  136.  
  137.     printf("\nTODO: verificati continutul fisierului la final (i.e. dupa 'distrugerea' maparii), cu ajutorul comenzii urmatoare:\ncat %s \n\n", argv[1] );
  138.     exit(EXIT_SUCCESS);
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement