#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include #include #include /* ***D12*** copia di un file regolare, tra threads: è dato un file origine, da copiare il thread t1 legge tutto il file in memoria il thread t2 va a scrivere i contenuti nel file destinazione nota: vedere esercizio C03 */ char * source_filename; char * target_filename; int fd; char * source_map; char * target_map; __off_t source_file_size; int is_fd_a_regular_file(int fd) { struct stat sb; int res; res = fstat(fd, &sb); if (res == -1) { perror("fstat()"); return -1; } return (sb.st_mode & S_IFMT) == S_IFREG; } // restituisce la dimensione del file, -1 in caso di errore __off_t get_fd_size(int fd) { struct stat sb; int res; res = fstat(fd, &sb); if (res == -1) { perror("fstat()"); return -1; } return sb.st_size; } void * leggi_file(void * arg) { // il thread t1 legge tutto il file in memoria // apriamo il file in sola lettura fd = open(source_filename, O_RDONLY); if (fd == -1) { perror("open"); exit(1); } // se non è un file regolare, terminiamo if (!is_fd_a_regular_file(fd)) { printf("il file da copiare non è un file regolare.\n"); exit(1); } // dimensione del file da copiare source_file_size = get_fd_size(fd); // mappiamo in memoria tutto il file da copiare source_map = mmap(NULL, source_file_size, PROT_READ, MAP_PRIVATE, fd, 0); if (source_map == MAP_FAILED) { perror("mmap"); exit(1); } close(fd); printf("[t1] ho 'letto' il file\n"); return NULL; } void * scrivi_file(void * arg) { // il thread t2 va a scrivere i contenuti nel file destinazione // creiamo il file destinazione fd = open(target_filename, O_CREAT | O_TRUNC | O_RDWR, S_IWUSR | S_IRUSR); if (fd == -1) { perror("open"); exit(1); } // impostiamo la dimensione del file destinazione // il suo contenuto è 'zero' if (ftruncate(fd, source_file_size) == -1) { perror("ftruncate"); exit(1); } // mappiamo in memoria il file destinazione target_map = mmap(NULL, source_file_size, PROT_WRITE, MAP_SHARED, fd, 0); if (target_map == MAP_FAILED) { perror("mmap"); exit(1); } close(fd); // copiamo tutto il contenuto della memory map del file sorgente // nella memory map del file destinazione memcpy(target_map, source_map, source_file_size); printf("[t2] ho copiato %ld bytes\n", source_file_size); return NULL; } int main() { pthread_t t1, t2; source_filename = "text01.txt"; target_filename = "copia.txt"; // t1 legge il file sorgente if (pthread_create(&t1, NULL, leggi_file, NULL) != 0) { perror("pthread_create"); exit(1); } if (pthread_join(t1, NULL) != 0) { perror("pthread_join"); exit(1); } // t2 scrive il file destinazione; // prima di scrivere, dobbiamo aspettare che tutto il file sorgente // sia disponibile, ovvero aspettiamo che t1 sia terminato if (pthread_create(&t2, NULL, scrivi_file, NULL) != 0) { perror("pthread_create"); exit(1); } if (pthread_join(t2, NULL) != 0) { perror("pthread_join"); exit(1); } printf("[main] bye\n"); return 0; }