diff --git a/lab_4/Lab4_Pipes_IPC_Report.pdf b/lab_4/Lab4_Pipes_IPC_Report.pdf deleted file mode 100644 index 2004191..0000000 Binary files a/lab_4/Lab4_Pipes_IPC_Report.pdf and /dev/null differ diff --git a/lab_4/Makefile b/lab_4/Makefile index d38394d..6806c68 100644 --- a/lab_4/Makefile +++ b/lab_4/Makefile @@ -16,7 +16,7 @@ fifo_client: fifo_client.c $(CC) $(CFLAGS) -o $@ $< # ===== Test files ===== -test_files: +files: @echo "Создание тестовых файлов..." echo "abbaabbaabbaabbaabbaabbaabbaabba" > input1.txt echo "xyzxyzxyzxyzxyzxyzxyzxyz" >> input1.txt @@ -27,17 +27,18 @@ test_files: echo "ppppython" >> input3.txt # ===== FIFO tests ===== -test_fifo_server: fifo test_files +test_server: fifo files @echo "=== Запуск FIFO сервера ===" @echo "В другом терминале выполните: make test_fifo_client" + @echo "\n\n" ./fifo_server 10 -test_fifo_client: fifo test_files - @echo "=== Запуск FIFO клиента ===" & \ +test_client: fifo files + @echo "=== Запуск FIFO клиента ===\n\n" & \ ./fifo_client input1.txt output1_fifo.txt; \ ./fifo_client input2.txt output2_fifo.txt; \ ./fifo_client input3.txt output3_fifo.txt; - @echo "\n=== Результаты FIFO ===" + @echo "\n=== Результаты FIFO ===\n" @echo "--- output1_fifo.txt ---" @cat output1_fifo.txt || true @echo "\n--- output2_fifo.txt ---" @@ -45,35 +46,6 @@ test_fifo_client: fifo test_files @echo "\n--- output3_fifo.txt ---" @cat output3_fifo.txt || true -# Automatic FIFO test (server in background) -test_all: fifo test_files - @echo "=== Автоматический тест FIFO ===" - @./fifo_server 10 & \ - SERVER_PID=$$!; \ - sleep 1; \ - ./fifo_client input1.txt output1_fifo.txt; \ - ./fifo_client input2.txt output2_fifo.txt; \ - ./fifo_client input3.txt output3_fifo.txt; \ - kill $$SERVER_PID 2>/dev/null || true; \ - wait $$SERVER_PID 2>/dev/null || true - @echo "\n=== Результаты FIFO ===" - @echo "--- output1_fifo.txt ---" - @cat output1_fifo.txt || true - @echo "\n--- output2_fifo.txt ---" - @cat output2_fifo.txt || true - @echo "\n--- output3_fifo.txt ---" - @cat output3_fifo.txt || true - -# Error handling test for FIFO -test_error: fifo - @echo "\n=== Тест обработки ошибки (несуществующий файл) - FIFO ===" - @./fifo_server 5 & \ - SERVER_PID=$$!; \ - sleep 1; \ - ./fifo_client nonexistent.txt output_error.txt || true; \ - kill $$SERVER_PID 2>/dev/null || true; \ - wait $$SERVER_PID 2>/dev/null || true - # Cleanup clean: @echo "Очистка..." @@ -85,15 +57,11 @@ clean: # Help help: @echo "Available targets:" - @echo " all - Build FIFO programs" - @echo " fifo - Compile fifo_server and fifo_client" - @echo " test_files - Create test input files" - @echo " test_fifo_server - Run FIFO server (use client in another terminal)" - @echo " test_fifo_client - Run FIFO client and show results" - @echo " test_all - Automatic FIFO test (server in background)" - @echo " test_error - Error handling test (nonexistent file)" - @echo " clean - Remove built files and test files" - @echo " help - Show this help" + @echo " fifo - Compile fifo_server and fifo_client" + @echo " files - Create test input files" + @echo " test_server - Run FIFO server (use client in another terminal)" + @echo " test_client - Run FIFO client and show results + @echo " clean - Remove built files and test files" + @echo " help - Show this help" -.PHONY: all fifo test_files test_fifo_server test_fifo_client test_all \ - test_error clean help +.PHONY: all fifo files test_server test_client clean help diff --git a/lab_4/README_lab4.md b/lab_4/README_lab4.md deleted file mode 100644 index 15e377d..0000000 --- a/lab_4/README_lab4.md +++ /dev/null @@ -1,238 +0,0 @@ -# Лабораторная работа №4: Каналы передачи данных - -## Цель работы -Получить навыки организации обмена информацией между процессами средствами неименованных или именованных каналов в программах на языке C в операционных системах семейства Linux. - -## Описание задания - -Лабораторная работа является модификацией лабораторной работы №3, в которой обмен данными между родительской и дочерними программами производится через программные каналы. - -### Вариант 12 -Программа читает текстовый файл построчно. Для каждой строки первый символ становится ключом, и все вхождения этого символа в строке заменяются пробелами, пока не будет достигнуто максимальное количество замен. - -## Реализованные решения - -### 1. Решение с неименованными каналами (pipes) - -**Файлы:** -- `parent_pipe.c` - родительская программа -- `child_pipe.c` - дочерняя программа - -**Принцип работы:** -1. Родительский процесс создает три канала для каждого дочернего процесса: - - `pipe_to_child` - для передачи данных дочернему процессу - - `pipe_from_child` - для получения обработанных данных - - `pipe_error` - для получения количества замен - -2. Родительский процесс: - - Читает данные из входного файла - - Передает данные дочернему процессу через `pipe_to_child` - - Получает обработанные данные через `pipe_from_child` - - Записывает результат в выходной файл - -3. Дочерний процесс: - - Перенаправляет stdin на чтение из канала (dup2) - - Перенаправляет stdout на запись в канал (dup2) - - Обрабатывает данные согласно варианту 12 - - Возвращает количество замен через stderr - -**Преимущества:** -- Простая реализация для родственных процессов -- Автоматическая синхронизация через блокирующие операции чтения/записи -- Нет необходимости в файловых дескрипторах на диске - -**Недостатки:** -- Работает только между родственными процессами -- Ограниченный размер буфера канала - -### 2. Решение с именованными каналами (FIFO) - -**Файлы:** -- `fifo_server.c` - серверная программа -- `fifo_client.c` - клиентская программа - -**Принцип работы:** -1. Сервер создает два именованных канала: - - `/tmp/fifo_request` - для получения запросов - - `/tmp/fifo_response` - для отправки ответов - -2. Клиент: - - Читает данные из входного файла - - Отправляет данные серверу через `fifo_request` - - Получает обработанные данные через `fifo_response` - - Записывает результат в выходной файл - -3. Сервер: - - Ожидает запросы от клиентов - - Обрабатывает данные согласно варианту 12 - - Отправляет результат обратно клиенту - -**Преимущества:** -- Работает между неродственными процессами -- Клиент-серверная архитектура -- Возможность обработки запросов от нескольких клиентов - -**Недостатки:** -- Более сложная реализация -- Требуется управление файлами в файловой системе -- Необходима синхронизация между клиентом и сервером - -## Компиляция и запуск - -### Компиляция всех программ -```bash -make -f Makefile_lab4 all -``` - -### Тестирование с неименованными каналами -```bash -make -f Makefile_lab4 test_pipes -``` - -### Тестирование с именованными каналами - -**Вариант 1: Автоматический тест** -```bash -make -f Makefile_lab4 test_fifo_auto -``` - -**Вариант 2: Ручной запуск в двух терминалах** - -Терминал 1 (сервер): -```bash -make -f Makefile_lab4 test_fifo_server -``` - -Терминал 2 (клиент): -```bash -make -f Makefile_lab4 test_fifo_client -``` - -### Сравнение с оригинальной версией -```bash -make -f Makefile_lab4 test_compare -``` - -### Запуск всех тестов -```bash -make -f Makefile_lab4 test_all -``` - -## Примеры использования - -### Неименованные каналы -```bash -./parent_pipe ./child_pipe 10 input1.txt output1.txt input2.txt output2.txt -``` - -### Именованные каналы - -Запустить сервер: -```bash -./fifo_server 10 -``` - -В другом терминале запустить клиент: -```bash -./fifo_client input1.txt output1.txt -./fifo_client input2.txt output2.txt -``` - -## Обработка исключительных ситуаций - -Программы предусматривают обработку следующих ошибок: -- Отсутствие или неверное количество входных параметров -- Ошибки открытия входного и/или выходного файла -- Ошибки создания каналов -- Ошибки создания дочерних процессов -- Ошибки чтения и записи через каналы - -## Технические детали - -### Используемые системные вызовы - -**Неименованные каналы:** -- `pipe()` - создание канала -- `fork()` - создание дочернего процесса -- `dup2()` - дублирование файлового дескриптора -- `read()` / `write()` - чтение/запись данных -- `close()` - закрытие файлового дескриптора -- `waitpid()` - ожидание завершения дочернего процесса -- `execl()` - запуск новой программы - -**Именованные каналы:** -- `mkfifo()` - создание именованного канала -- `open()` - открытие FIFO -- `read()` / `write()` - чтение/запись данных -- `close()` - закрытие FIFO -- `unlink()` - удаление FIFO - -### Схема работы каналов - -**Неименованные каналы (pipes):** -``` -Родительский процесс Дочерний процесс - [файл] → read stdin ← pipe - ↓ ↓ - pipe → write read → process - ↓ - read ← pipe write → stdout - ↓ - write → [файл] -``` - -**Именованные каналы (FIFO):** -``` -Клиент Сервер -[файл] → read /tmp/fifo_request ← open - ↓ ↓ - write → /tmp/fifo_request read → process - ↓ - read ← /tmp/fifo_response write → /tmp/fifo_response - ↓ - write → [файл] -``` - -## Структура проекта - -``` -lab4/ -├── parent_pipe.c # Родительская программа (pipes) -├── child_pipe.c # Дочерняя программа (pipes) -├── fifo_server.c # Серверная программа (FIFO) -├── fifo_client.c # Клиентская программа (FIFO) -├── parent.c # Оригинальная версия (Lab 3) -├── lab1_var12.c # Оригинальная версия (Lab 1) -├── Makefile_lab4 # Makefile для компиляции и тестирования -└── README_lab4.md # Документация -``` - -## Контрольные вопросы (стр. 82) - -1. **Что такое канал (pipe)?** - - Канал - это механизм межпроцессного взаимодействия (IPC), представляющий собой однонаправленный канал связи между процессами. - -2. **В чем разница между именованными и неименованными каналами?** - - Неименованные каналы существуют только в памяти и доступны только родственным процессам - - Именованные каналы (FIFO) создаются в файловой системе и доступны любым процессам - -3. **Как создать канал?** - - Неименованный: `int pipe(int fd[2])` - - Именованный: `int mkfifo(const char *pathname, mode_t mode)` - -4. **Что происходит при чтении из пустого канала?** - - Процесс блокируется до тех пор, пока в канал не будут записаны данные - -5. **Что происходит при записи в заполненный канал?** - - Процесс блокируется до тех пор, пока в канале не освободится место - -6. **Как передать данные через канал?** - - Используя системные вызовы `write()` для записи и `read()` для чтения - -7. **Зачем нужно закрывать неиспользуемые концы канала?** - - Для корректного определения EOF при чтении - - Для освобождения ресурсов - - Для предотвращения deadlock - -## Автор -Лабораторная работа выполнена в рамках курса "Системное программирование в среде Linux" diff --git a/lab_4/fifo_client.c b/lab_4/fifo_client.c index 9abe125..28f854b 100644 --- a/lab_4/fifo_client.c +++ b/lab_4/fifo_client.c @@ -1,5 +1,3 @@ -// fifo_client.c - Клиентская программа с использованием именованных каналов (FIFO) - #include #include #include diff --git a/lab_4/fifo_server.c b/lab_4/fifo_server.c index d0c0ace..92bad9a 100644 --- a/lab_4/fifo_server.c +++ b/lab_4/fifo_server.c @@ -1,6 +1,3 @@ -// fifo_server.c - Серверная программа с использованием именованных каналов (FIFO) -// Вариант повышенной сложности для Lab 4 - #include #include #include diff --git a/lab_4/Инструкция_по_запуску.md b/lab_4/Инструкция_по_запуску.md deleted file mode 100644 index 76c8a6f..0000000 --- a/lab_4/Инструкция_по_запуску.md +++ /dev/null @@ -1,399 +0,0 @@ -# Инструкция по запуску Лабораторной работы №4 - -## Быстрый старт - -### 1. Подготовка файлов - -Создайте рабочую директорию и поместите в неё следующие файлы: -- `parent_pipe.c` - родительская программа (pipes) -- `child_pipe.c` - дочерняя программа (pipes) -- `fifo_server.c` - серверная программа (FIFO) -- `fifo_client.c` - клиентская программа (FIFO) -- `Makefile_lab4` - Makefile для компиляции -- Оригинальные файлы: `parent.c`, `lab1_var12.c`, `Makefile` (для сравнения) - -### 2. Компиляция - -```bash -# Компилировать все программы -make -f Makefile_lab4 all - -# Или компилировать отдельно: -make -f Makefile_lab4 pipes # Только pipes -make -f Makefile_lab4 fifo # Только FIFO -make -f Makefile_lab4 original # Оригинальная версия -``` - -### 3. Автоматическое тестирование - -```bash -# Тест с неименованными каналами (pipes) -make -f Makefile_lab4 test_pipes - -# Автоматический тест с именованными каналами (FIFO) -make -f Makefile_lab4 test_fifo_auto - -# Сравнение с оригинальной версией -make -f Makefile_lab4 test_compare - -# Запустить все тесты -make -f Makefile_lab4 test_all -``` - -## Подробные инструкции - -### Вариант 1: Неименованные каналы (Pipes) - -#### Компиляция -```bash -gcc -Wall -Wextra -std=c99 -g -o parent_pipe parent_pipe.c -gcc -Wall -Wextra -std=c99 -g -o child_pipe child_pipe.c -``` - -#### Создание тестовых файлов -```bash -echo "abbaabbaabbaabbaabbaabbaabbaabba" > input1.txt -echo "xyzxyzxyzxyzxyzxyzxyzxyz" >> input1.txt -echo "hello world hello" >> input1.txt - -echo "testtest" > input2.txt -echo "aaaaaaa" >> input2.txt - -echo "programming" > input3.txt -echo "ppppython" >> input3.txt -``` - -#### Запуск -```bash -# Формат: ./parent_pipe [ ...] - -# Обработка одного файла -./parent_pipe ./child_pipe 10 input1.txt output1.txt - -# Обработка нескольких файлов параллельно -./parent_pipe ./child_pipe 10 input1.txt output1.txt input2.txt output2.txt input3.txt output3.txt - -# Разные лимиты замен -./parent_pipe ./child_pipe 5 input1.txt output1_5.txt -./parent_pipe ./child_pipe 20 input1.txt output1_20.txt -``` - -#### Просмотр результатов -```bash -cat output1.txt -cat output2.txt -cat output3.txt -``` - -### Вариант 2: Именованные каналы (FIFO) - -#### Компиляция -```bash -gcc -Wall -Wextra -std=c99 -g -o fifo_server fifo_server.c -gcc -Wall -Wextra -std=c99 -g -o fifo_client fifo_client.c -``` - -#### Вариант 2.1: Запуск в двух терминалах - -**Терминал 1 (Сервер):** -```bash -./fifo_server 10 -``` -Сервер запустится и будет ожидать подключения клиентов. - -**Терминал 2 (Клиент):** -```bash -# Формат: ./fifo_client - -./fifo_client input1.txt output1_fifo.txt -./fifo_client input2.txt output2_fifo.txt -./fifo_client input3.txt output3_fifo.txt -``` - -После обработки всех файлов остановите сервер: Ctrl+C в терминале 1. - -#### Вариант 2.2: Автоматический запуск (одна команда) - -```bash -# Сервер запустится в фоне, обработает запросы и автоматически остановится -make -f Makefile_lab4 test_fifo_auto -``` - -#### Вариант 2.3: Ручной запуск в фоне - -```bash -# Запустить сервер в фоне -./fifo_server 10 & -SERVER_PID=$! - -# Подождать запуска сервера -sleep 1 - -# Отправить запросы -./fifo_client input1.txt output1_fifo.txt -./fifo_client input2.txt output2_fifo.txt -./fifo_client input3.txt output3_fifo.txt - -# Остановить сервер -kill $SERVER_PID -``` - -## Тестирование обработки ошибок - -### Несуществующий входной файл - -```bash -# Pipes -./parent_pipe ./child_pipe 5 nonexistent.txt output.txt - -# FIFO -./fifo_server 5 & -sleep 1 -./fifo_client nonexistent.txt output.txt -killall fifo_server -``` - -### Неверное количество аргументов - -```bash -# Недостаточно аргументов -./parent_pipe ./child_pipe 5 - -# Нечетное количество файлов -./parent_pipe ./child_pipe 5 input1.txt -``` - -### Клиент без сервера (FIFO) - -```bash -# Попытка подключиться при выключенном сервере -./fifo_client input1.txt output1.txt -# Ожидается: "ERROR: Не удалось открыть FIFO запроса" -``` - -## Сравнение результатов - -### Сравнение pipes vs original - -```bash -# Запустить обе версии -./parent_pipe ./child_pipe 10 input1.txt output1_pipe.txt -./parent ./lab1_var12 10 input1.txt output1_orig.txt - -# Сравнить результаты -diff output1_pipe.txt output1_orig.txt - -# Если различий нет - программа работает корректно -``` - -### Сравнение FIFO vs pipes - -```bash -# Pipes -./parent_pipe ./child_pipe 10 input1.txt output1_pipe.txt - -# FIFO -./fifo_server 10 & -sleep 1 -./fifo_client input1.txt output1_fifo.txt -killall fifo_server - -# Сравнение -diff output1_pipe.txt output1_fifo.txt -``` - -## Анализ работы программ - -### Просмотр процессов - -```bash -# Во время работы parent_pipe в другом терминале: -ps aux | grep child_pipe -ps aux | grep parent_pipe - -# Просмотр открытых файловых дескрипторов -lsof -c parent_pipe -lsof -c child_pipe -``` - -### Просмотр FIFO файлов - -```bash -# Во время работы сервера: -ls -la /tmp/fifo_* - -# Информация о типе файла -file /tmp/fifo_request -file /tmp/fifo_response -``` - -### Трассировка системных вызовов - -```bash -# Трассировка работы с каналами -strace -e trace=pipe,read,write,fork,execl ./parent_pipe ./child_pipe 10 input1.txt output1.txt - -# Трассировка FIFO операций -strace -e trace=open,read,write,mkfifo ./fifo_server 10 -``` - -## Очистка - -```bash -# Удалить скомпилированные программы и тестовые файлы -make -f Makefile_lab4 clean - -# Или вручную: -rm -f parent_pipe child_pipe fifo_server fifo_client -rm -f parent lab1_var12 -rm -f input*.txt output*.txt -rm -f /tmp/fifo_request /tmp/fifo_response -``` - -## Типичные проблемы и решения - -### Проблема 1: "Permission denied" при запуске - -**Решение:** -```bash -chmod +x parent_pipe child_pipe fifo_server fifo_client -``` - -### Проблема 2: FIFO клиент зависает - -**Причина:** Сервер не запущен. - -**Решение:** Убедитесь, что сервер запущен: -```bash -ps aux | grep fifo_server -``` - -### Проблема 3: "Address already in use" для FIFO - -**Причина:** FIFO файлы остались после некорректного завершения. - -**Решение:** -```bash -rm -f /tmp/fifo_request /tmp/fifo_response -``` - -### Проблема 4: Зомби-процессы - -**Причина:** Родительский процесс не вызвал wait() для дочерних. - -**Решение:** В коде уже реализован waitpid(), но если проблема возникла: -```bash -# Просмотр зомби -ps aux | grep defunct - -# Завершить родительский процесс -killall parent_pipe -``` - -### Проблема 5: Broken pipe - -**Причина:** Попытка записи в канал, у которого закрыт конец для чтения. - -**Решение:** Убедитесь, что оба конца канала правильно настроены и дочерний процесс не завершился преждевременно. - -## Дополнительные команды - -### Справка по использованию - -```bash -# Показать все доступные команды Makefile -make -f Makefile_lab4 help -``` - -### Компиляция с отладочной информацией - -```bash -# Уже включено флагом -g, запуск с gdb: -gdb ./parent_pipe -(gdb) run ./child_pipe 10 input1.txt output1.txt -``` - -### Проверка утечек памяти - -```bash -# Для pipes -valgrind --leak-check=full ./parent_pipe ./child_pipe 10 input1.txt output1.txt - -# Для FIFO сервера -valgrind --leak-check=full ./fifo_server 10 -``` - -## Примеры вывода - -### Успешное выполнение pipes - -``` -=== Запуск родительского процесса с каналами === -Родительский PID: 12345 -Программа для запуска: ./child_pipe -Максимум замен: 10 -Количество файловых пар: 2 - -Создание процесса 1 для файлов: input1.txt -> output1.txt -Создание процесса 2 для файлов: input2.txt -> output2.txt - -=== Обработка файлов через каналы === - -Обработка процесса PID=12346 (input1.txt -> output1.txt) - Отправлено байт: 87 - Получено байт: 87 - Количество замен: 10 - Статус: SUCCESS - -Обработка процесса PID=12347 (input2.txt -> output2.txt) - Отправлено байт: 17 - Получено байт: 17 - Количество замен: 6 - Статус: SUCCESS - -=== Итоговая статистика === -Всего запущено процессов: 2 -Успешно завершено: 2 -Завершено с ошибкой: 0 - -ОБЩИЙ СТАТУС: Все процессы завершены успешно -``` - -### Успешное выполнение FIFO - -``` -=== FIFO Server запущен === -Server PID: 12350 -Максимум замен: 10 -FIFO каналы созданы: - Request: /tmp/fifo_request - Response: /tmp/fifo_response -Ожидание запросов от клиентов... - -Получен запрос: 87 байт -Выполнено замен: 10 -Отправлен ответ: 87 байт -``` - -``` -=== FIFO Client === -Client PID: 12351 -Входной файл: input1.txt -Выходной файл: output1.txt -Прочитано байт из файла: 87 -Отправка запроса серверу... -Отправлено байт: 87 -Ожидание ответа от сервера... -Получено байт от сервера: 100 -Записано байт в выходной файл: 87 -Количество выполненных замен: 10 - -Обработка завершена успешно! -``` - -## Контакты и поддержка - -При возникновении вопросов обратитесь к: -- Отчету лабораторной работы (PDF) -- Комментариям в исходном коде -- Документации Linux man pages: `man pipe`, `man mkfifo`, `man fork`, `man dup2`