лабораторные Тимофеев / 3316_Кирейкова_Лабораторная1
.2.pdfМИНОБРНАУКИ РОССИИ
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)
ОТЧЕТ
по Лабораторной работе №1
по дисциплине «Операционные системы»
«Управление файловой системы»
Выполнила: Кирейкова С.А. Группа: №3316
Преподаватель: Тимофеев А. В.
Санкт-Петербург
2025
2
Задание 1.2. Копирование файла с помощью операций перекрывающегося ввода-вывода
Графики зависимости
График зависимости при копировании файла размером 25 МБ при одной асинхронной операции:
График зависимости при копировании файла размером 25 МБ при нескольких асинхронных операциях:
3
График зависимости при копировании файла размером 1,1 ГБ при нескольких асинхронных операциях:
Код программы
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <aio.h>
4
#include <ctime> #include <sys/stat.h>
#include <bits/types/sigval_t.h> #include <iostream>
#include <string> using namespace std; char source_path[256];
char destination_path[256]; size_t block_size; int source_fd, destination_fd; off_t offset = 0; struct stat source_stat; off_t total_size; struct timespec start, finish;
int WorkingOps; int opsN; char **buffers;
struct aio_operation{
struct aiocb controlBlock; char *buffer; int isWriteOp; bool done;
int number; };
aio_operation *aiocb_list;
void aio_completion_handler(sigval_t sigval) {
auto *aio_op=(struct aio_operation *) sigval.sival_ptr; if (aio_op -> done) return;
if (aio_op -> controlBlock.aio_offset >= total_size) { aio_op -> done = true;
5
WorkingOps--;
} else if (aio_op -> isWriteOp) {
aio_op -> controlBlock.aio_fildes = destination_fd; if (aio_op -> controlBlock.aio_offset + aio_op ->
controlBlock.aio_nbytes > total_size) {
aio_op -> controlBlock.aio_nbytes = total_size - aio_op -> controlBlock.aio_offset;
}
if (aio_write(&aio_op -> controlBlock) == -1) { perror("aio_write");
exit(EXIT_FAILURE);
}
} else {
aio_op -> controlBlock.aio_offset += aio_op -> controlBlock.aio_nbytes * opsN;
aio_op -> controlBlock.aio_fildes = source_fd; if (aio_read (&aio_op -> controlBlock) == -1) {
perror("aio_read"); exit(EXIT_FAILURE);
}
}
aio_op -> isWriteOp = !aio_op -> isWriteOp;
}
void aio_read_setup(struct aio_operation *aiocbp, int fd, off_t offset, volatile void *buf, size_t size, int number) {
memset(aiocbp, 0, sizeof(struct aiocb)); aiocbp -> isWriteOp = 1;
aiocbp -> buffer = new char[block_size]{0}; aiocbp -> controlBlock = aiocb{0};
aiocbp -> controlBlock.aio_fildes = fd; aiocbp -> controlBlock.aio_buf = buf; aiocbp -> controlBlock.aio_nbytes = size; aiocbp -> controlBlock.aio_offset =offset; aiocbp -> number = number;
6
aiocbp -> controlBlock.aio_sigevent.sigev_notify = SIGEV_THREAD; aiocbp -> controlBlock.aio_sigevent.sigev_notify_function =
aio_completion_handler;
aiocbp -> controlBlock.aio_sigevent.sigev_value.sival_ptr = aiocbp; aiocbp -> done = false;
if (aio_read(&aiocbp -> controlBlock) == -1) { perror("aio_read"); exit(EXIT_FAILURE);
}
}
string get_extension(string &file_path) {
size_t dot_pos = file_path.find_last_of('.'); if (dot_pos == string::npos) { return "";
}
return file_path.substr(dot_pos);
}
int main() { double elapsed;
printf("Enter the source file path: "); scanf("%255s", source_path);
string source_path_str(source_path);
string extension = get_extension(source_path_str);
printf("Enter the destination file path (without extension): "); scanf("%255s", destination_path);
7
string destination_path_str(destination_path); destination_path_str += extension;
strncpy(destination_path, destination_path_str.c_str(), 256);
printf("Enter the block size in bytes (multiples of 1024): "); scanf("%zu", &block_size);
printf("Enter the number of asynch operations: "); scanf("%d", &opsN);
aiocb_list = new aio_operation[opsN]; buffers = new char*[opsN];
source_fd = open(source_path, O_RDONLY); if (source_fd == -1) { perror("open source"); exit(EXIT_FAILURE);
}
if (fstat(source_fd, &source_stat) == -1) { perror("fstat"); close(source_fd); exit(EXIT_FAILURE);
}
total_size = source_stat.st_size;
destination_fd = open(destination_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (destination_fd == -1) { perror("open destination"); close(source_fd); exit(EXIT_FAILURE);
}
for (int i = 0; i < opsN; i++) { buffers[i] = new char[block_size]; if (!buffers[i]) {
perror("malloc"); close(source_fd); close(destination_fd); exit(EXIT_FAILURE);
}
}
8
clock_gettime(CLOCK_MONOTONIC, &start); for (int i = 0; i < opsN; i++) { aio_read_setup(&aiocb_list[i], source_fd, offset, buffers[i], block_size, i+1); offset += block_size;
}
WorkingOps = opsN;
while (WorkingOps > 0) { sleep(0);
}
clock_gettime(CLOCK_MONOTONIC, &finish); elapsed = (finish.tv_sec - start.tv_sec);
elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
close(source_fd); close(destination_fd);
printf("Copying was completed in %f seconds\n", elapsed);
return 0;
}
Вывод:
В ходе лабораторного исследования изучалось влияние размера блока данных и количества параллельных операций на скорость асинхронного копирования файлов. Эксперименты проводились с файлами объемом 25 МБ и 1,1 ГБ.
Для крупного файла (1,1 ГБ) наилучшие результаты показали блоки размером 80–120 КБ. Именно при таких параметрах достигалось минимальное время копирования и наибольшая стабильность работы при
9
использовании 4–16 параллельных операций. Для файла меньшего размера (25 МБ) существенные различия в скорости нивелировались при размере блоков от 8192 байт, а увеличение количества операций давало лишь незначительный эффект. Исключение составил вариант с одной операцией, где производительность была заметно ниже.
Анализ результатов выявил определенную неоднозначность в оптимальных параметрах копирования. Эффективность процесса существенно зависит от выбранного размера блоков — при некоторых значениях может наблюдаться нерациональное использование памяти, особенно при неравномерном распределении блоков. Это приводит к избыточному выделению памяти и объясняет отдельные пики на графиках, наиболее заметные при промежуточном количестве операций.
Важно учитывать, что общее время выполнения включает не только непосредственно копирование данных, но и операции доступа к файлам, подготовку асинхронных операций и выделение памяти, что создает дополнительные вычислительные затраты.
Основной вывод исследования: производительность асинхронного копирования определяется тремя ключевыми факторами — размером блоков данных, количеством параллельных операций и объемом копируемого файла. Для оптимизации процесса рекомендуется использовать крупные блоки (8-12 КБ для небольших файлов и 80-120 КБ для файлов гигабайтного диапазона) в сочетании с умеренным количеством параллельных операций (4-8), что обеспечивает оптимальный баланс между скоростью передачи данных и нагрузкой на систему.
10
