Лабы, Разумовский / 4_laba / ООПЛинукс_4л
.docx
МИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра ВТ
отчет
по лабораторной работе №4
по дисциплине «Организация процессов и программирование в среде Linux»
Тема: Управление потоками
Студент гр. |
|
|
Преподаватель |
|
Разумовский Г.В. |
Санкт-Петербург
2026
Цель работы
Знакомство с организацией потоков и способами синхронизации предков и потомков.
Задание
Написать программу, которая открывает входной файл и 2 выходных файла. Затем она должна в цикле построчно читать входной файл и порождать 2 потока. Одному потоку предавать нечетную строку, а другому - четную. Оба потока должны работать параллельно. Каждый поток записывает в свой выходной файл полученную строку и завершает работу. Программа должна ожидать завершения работы каждого повторять цикл порождения потоков и чтения строк входного файла, пока не прочтет последнюю строку, после чего закрыть все файлы.
Распечатка тестовой программы
own_prog.cpp
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <string>
#include <unistd.h>
using namespace std;
// Структура для передачи данных потоку
struct ThreadData {
string line;
ofstream* outFile;
int threadNum;
};
// Функция потока
void* threadFunction(void* arg) {
ThreadData* data = (ThreadData*)arg;
// Записываем строку в файл
if (data->outFile->is_open()) {
*data->outFile << data->line << endl;
cout << "Поток " << data->threadNum
<< " записал строку: " << data->line << endl;
}
delete data;
return NULL;
}
int main(int argc, char* argv[]) {
if (argc != 4) {
cerr << "Использование: " << argv[0]
<< " <входной_файл> <выходной_файл_1> <выходной_файл_2>" << endl;
return 1;
}
string inputFile = argv[1];
string outputFile1 = argv[2];
string outputFile2 = argv[3];
ifstream inFile(inputFile);
if (!inFile.is_open()) {
cerr << "Ошибка открытия входного файла: " << inputFile << endl;
return 1;
}
ofstream out1(outputFile1);
ofstream out2(outputFile2);
if (!out1.is_open()) {
cerr << "Ошибка открытия файла: " << outputFile1 << endl;
inFile.close();
return 1;
}
if (!out2.is_open()) {
cerr << "Ошибка открытия файла: " << outputFile2 << endl;
inFile.close();
out1.close();
return 1;
}
cout << "Файлы открыты. Начинаем обработку..." << endl;
string line1, line2;
int lineNumber = 0;
// Читаем файл попарно (нечетная + четная строки)
while (true) {
// Читаем нечетную строку
if (getline(inFile, line1)) {
lineNumber++;
cout << "\n--- Обработка пары строк ---" << endl;
cout << "Нечетная строка (" << lineNumber << "): " << line1 << endl;
// Создаем данные для первого потока
ThreadData* data1 = new ThreadData;
data1->line = line1;
data1->outFile = &out1;
data1->threadNum = 1;
pthread_t thread1;
pthread_create(&thread1, NULL, threadFunction, data1);
// Читаем четную строку (если есть)
if (getline(inFile, line2)) {
lineNumber++;
cout << "Четная строка (" << lineNumber << "): " << line2 << endl;
// Создаем данные для второго потока
ThreadData* data2 = new ThreadData;
data2->line = line2;
data2->outFile = &out2;
data2->threadNum = 2;
pthread_t thread2;
pthread_create(&thread2, NULL, threadFunction, data2);
// Ждем завершения обоих потоков
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
} else {
// Если нечетная строка была последней
pthread_join(thread1, NULL);
break;
}
} else {
// Файл закончился
break;
}
}
inFile.close();
out1.close();
out2.close();
cout << "\n=== Обработка завершена ===" << endl;
cout << "Всего обработано строк: " << lineNumber << endl;
cout << "Результаты записаны в файлы:" << endl;
cout << " - Нечетные строки: " << outputFile1 << endl;
cout << " - Четные строки: " << outputFile2 << endl;
return 0;
}
Вывод
В ходе выполнения лабораторной работы были изучены механизмы управления потоками в операционной системе Linux и получены практические навыки работы с многопоточными приложениями.
В работе были использованы функции pthread_create для срздания новых потоков выполнения, pthread_join для синхронизации и ожидания завершения потоков, pthread_exit для корректного завершения потока.Функция потока имеет фиксированный прототип, принимающий только один параметр типа void*. Для передачи нескольких значений в поток данные упаковываются в структуру, которая передаётся через указатель, а память для структуры должна выделяться в куче, чтобы данные оставались доступными после создания потока.
Потоки выполняются параллельно и независимо друг от друга, а порядок их завершения не детерминирован. Даже если потом создан первым, он может завершиться позже второго, что связано с работой планировщика операционной системы, распределяющего процессорное время между потоками.
Синхронизация осуществляется с помощью функции pthread_join, которая блокирует родительский процесс до завершения указанного потока. Это гарантирует, что все потоки завершат работу до перехода к следующей итерации цикла.
В результате выполнения заданий были разработаны и отлажены программы, которые открывают входной файл и два выходных файла, в цикле построчно читают входной файл, порождаются два потока, которым передают нечетную и четную строки соответственно. Оба потока работают параллельно и записывают данные в свои файлы, родительский процесс ожидает завершения потоков через pthread_join, а после обработки всех строк закрывает все файлы.
