works no files

This commit is contained in:
2025-12-10 14:23:02 +07:00
parent 2b488e06eb
commit 43b29e59e7
3 changed files with 439 additions and 0 deletions

157
lab_6/client.c Normal file
View File

@@ -0,0 +1,157 @@
// client.c
// Клиент POSIX IPC: подключается к существующей разделяемой памяти
// и именованным семафорам, передаёт строку серверу и получает результат. [web:8]
#include <stdio.h> // printf, fprintf, perror, fgets
#include <stdlib.h> // exit, EXIT_FAILURE
#include <string.h> // memset, strncpy, strlen
#include <errno.h> // errno
#include <fcntl.h> // O_RDWR
#include <sys/mman.h> // shm_open, mmap, munmap
#include <sys/stat.h> // mode_t
#include <semaphore.h> // sem_t, sem_open, sem_close, sem_wait, sem_post
#include <unistd.h> // close
// Максимальная длина строки для обмена (должна совпадать с сервером).
#define SHM_BUFFER_SIZE 1024
// Структура данных в разделяемой памяти, та же, что и у сервера.
typedef struct {
int has_data;
int result_code;
char buffer[SHM_BUFFER_SIZE];
} shared_block_t;
// Основная функция клиента.
int main(int argc, char *argv[]) {
// Ожидаем минимум три аргумента:
// argv[1] - имя объекта shared memory (должно совпадать с сервером).
// argv[2] - имя семафора клиента.
// argv[3] - имя семафора сервера.
if (argc < 4) {
fprintf(stderr,
"Usage: %s <shm_name> <sem_client_name> <sem_server_name>\n",
argv[0]);
return -1;
}
const char *shm_name = argv[1];
const char *sem_client_name = argv[2];
const char *sem_server_name = argv[3];
// Открываем уже существующий объект разделяемой памяти. [web:8]
int shm_fd = shm_open(shm_name, O_RDWR, 0);
if (shm_fd == -1) {
perror("shm_open");
return -1;
}
// Отображаем его в адресное пространство процесса. [web:8]
shared_block_t *shm_ptr = mmap(NULL,
sizeof(shared_block_t),
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd,
0);
if (shm_ptr == MAP_FAILED) {
perror("mmap");
close(shm_fd);
return -1;
}
// Дескриптор больше не нужен после mmap.
if (close(shm_fd) == -1) {
perror("close");
}
// Открываем существующие именованные семафоры. [web:16]
sem_t *sem_client = sem_open(sem_client_name, 0);
if (sem_client == SEM_FAILED) {
perror("sem_open(sem_client)");
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
sem_t *sem_server = sem_open(sem_server_name, 0);
if (sem_server == SEM_FAILED) {
perror("sem_open(sem_server)");
sem_close(sem_client);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
// Читаем строку из stdin.
char input[SHM_BUFFER_SIZE];
if (fgets(input, sizeof(input), stdin) == NULL) {
// Ошибка чтения из stdin или EOF.
fprintf(stderr, "No input line provided\n");
sem_close(sem_client);
sem_close(sem_server);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
// Удаляем перевод строки в конце, если он есть.
size_t len = strlen(input);
if (len > 0 && input[len - 1] == '\n') {
input[len - 1] = '\0';
}
// Записываем строку в разделяемую память.
// Сначала очищаем буфер.
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
// Копируем строку, гарантируя наличие '\0'.
strncpy(shm_ptr->buffer, input, SHM_BUFFER_SIZE - 1);
shm_ptr->buffer[SHM_BUFFER_SIZE - 1] = '\0';
// Устанавливаем флаг наличия данных.
shm_ptr->has_data = 1;
// Передаём управление серверу: sem_post(sem_client). [web:16]
if (sem_post(sem_client) == -1) {
perror("sem_post(sem_client)");
sem_close(sem_client);
sem_close(sem_server);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
// Ждём завершения обработки: sem_wait(sem_server). [web:16]
if (sem_wait(sem_server) == -1) {
perror("sem_wait(sem_server)");
sem_close(sem_client);
sem_close(sem_server);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
// Проверяем код результата, установленный сервером.
if (shm_ptr->result_code != 0) {
fprintf(stderr, "Server reported error, result_code = %d\n",
shm_ptr->result_code);
sem_close(sem_client);
sem_close(sem_server);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
// Выводим обработанную строку на stdout.
printf("%s\n", shm_ptr->buffer);
// Закрываем семафоры и отсоединяемся от разделяемой памяти. [web:8]
if (sem_close(sem_client) == -1) {
perror("sem_close(sem_client)");
}
if (sem_close(sem_server) == -1) {
perror("sem_close(sem_server)");
}
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
perror("munmap");
}
return 0;
}