Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лабораторные Тимофеев / 3316_Кирейкова_Лабораторная1

.2.pdf
Скачиваний:
0
Добавлен:
01.06.2026
Размер:
456.21 Кб
Скачать

МИНОБРНАУКИ РОССИИ

САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)

ОТЧЕТ

по Лабораторной работе №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