/
MaestroN
/
Eltex_Homework
Обзор
Документация
Войти
/
MaestroN
/
Eltex_Homework
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Task_11/Task11.1.c
167 строк
8 KB
nikita_shub
Добавление задания 11 семафоры
11 фев 2025, 09:11
11 фев 2025, 09:11
e960854
Код
Авторство
О чём код?
/*Организация обмена данными между несколькими процессами с разделяемой памятью и семафорами Цель: Создать программу, где несколько процессов работают с разделяемой памятью, обеспечивая как синхронизированное чтение/запись данных, так и параллельную обработку информации. • Создайте разделяемую память, которая представляет собой общую структуру (например, структурированную очередь или буфер фиксированного размера), где процессы могут размещать сообщения или данные. • Организуйте три процесса (один поставщик данных и два потребителя). • Используйте семафоры для синхронизации: один семафор для контроля доступа к критической секции (для защиты чтения/записи), другие семафоры можно использовать для сигнализации о наличии новых данных (например, для реализации счетчика сообщений в буфере). • Каждый процесс, читающий разделяемую память, должен извлекать и обрабатывать данные (например, выводить их на экран), а процесс, пишущий данные, должен сигнализировать о наличии новых данных. • Обеспечьте корректное управление ресурсами: отсоединение разделяемой памяти, очистка семафоров, корректную обработку ошибок. Рекомендации: • Рассмотрите реализацию кольцевого буфера в разделяемой памяти, где один процесс записывает данные, а другой — считывает. • Используйте два семафора: один — для контроля доступа к разделяемой памяти (mutex), другой — для учета количества доступных сообщений. • Протестируйте сценарии, когда потребитель пытается извлечь данные из пустого буфера, и поставщик пытается записать данные в заполненный буфер.*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <semaphore.h> // Константы для размера буфера и максимального количества элементов #define BUFFER_SIZE 1 // Размер кольцевого буфера #define MAX_ITEMS 20 // Общее количество элементов для производства // Структура разделяемой памяти typedef struct { int buffer[BUFFER_SIZE]; // Кольцевой буфер int head; // Индекс для записи (производитель) int tail; // Индекс для чтения (потребители) } shared_buffer; // Глобальные указатели на разделяемую память и семафоры shared_buffer *shm_buf; sem_t *sem_mutex, *sem_full, *sem_empty; /************************** * Функция производителя * **************************/ void producer() { for(int i = 1; i <= MAX_ITEMS; i++) { // Ожидаем свободное место (уменьшаем счетчик свободных ячеек) sem_wait(sem_empty); // Захватываем мьютекс для работы с разделяемой памятью sem_wait(sem_mutex); // Записываем данные в буфер shm_buf->buffer[shm_buf->head] = i; printf("Производитель записал: %d\n", i); // Обновляем индекс записи с учетом кольцевой структуры shm_buf->head = (shm_buf->head + 1) % BUFFER_SIZE; // Освобождаем мьютекс sem_post(sem_mutex); // Увеличиваем счетчик заполненных ячеек sem_post(sem_full); // Имитация работы производителя usleep(100000); } } /************************ * Функция потребителя * ************************/ void consumer(int num) { while(1) { // Ожидаем данные для чтения (уменьшаем счетчик заполненных ячеек) sem_wait(sem_full); // Захватываем мьютекс sem_wait(sem_mutex); // Читаем данные из буфера int item = shm_buf->buffer[shm_buf->tail]; printf("Потребитель %d считал: %d\n", num, item); // Обновляем индекс чтения с учетом кольцевой структуры shm_buf->tail = (shm_buf->tail + 1) % BUFFER_SIZE; // Освобождаем мьютекс sem_post(sem_mutex); // Увеличиваем счетчик свободных ячеек sem_post(sem_empty); // Условие завершения работы потребителя if(item == MAX_ITEMS) break; // Имитация обработки данных usleep(200000); } } /************** * Основная функция * **************/ int main() { // Создаем объект разделяемой памяти int shm_fd = shm_open("/shared_buffer", O_CREAT | O_RDWR, 0666); // Устанавливаем размер разделяемой памяти ftruncate(shm_fd, sizeof(shared_buffer)); // Отображаем разделяемую память в адресное пространство процесса shm_buf = mmap(NULL, sizeof(shared_buffer), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); // Инициализируем буфер shm_buf->head = 0; shm_buf->tail = 0; // Создаем и инициализируем семафоры sem_mutex = sem_open("/mutex", O_CREAT, 0666, 1); // Бинарный семафор (мьютекс) sem_full = sem_open("/full", O_CREAT, 0666, 0); // Счетчик заполненных ячеек sem_empty = sem_open("/empty", O_CREAT, 0666, BUFFER_SIZE); // Счетчик свободных ячеек // Создаем процессы pid_t pid = fork(); if(pid == 0) { // Дочерний процесс pid_t pid2 = fork(); if(pid2 == 0) { // Внучатый процесс - производитель producer(); exit(0); } else { // Дочерний процесс - потребитель 1 consumer(1); exit(0); } } else { // Родительский процесс - потребитель 2 //consumer(2); } /************************** * Очистка ресурсов * **************************/ // Закрываем семафоры sem_close(sem_mutex); sem_close(sem_full); sem_close(sem_empty); // Удаляем именованные семафоры sem_unlink("/mutex"); sem_unlink("/full"); sem_unlink("/empty"); // Отсоединяем разделяемую память munmap(shm_buf, sizeof(shared_buffer)); // Удаляем объект разделяемой памяти shm_unlink("/shared_buffer"); return 0; }