diff --git a/lab_6/kirill/Makefile b/lab_6/kirill/Makefile new file mode 100644 index 0000000..6eefc14 --- /dev/null +++ b/lab_6/kirill/Makefile @@ -0,0 +1,51 @@ +CC = gcc +CFLAGS = -Wall -Wextra -std=c99 -g +LDFLAGS_IPC = -lrt -pthread + +SHM_NAME ?= /myshm +SEM_CLIENT_NAME ?= /sem_client +SEM_SERVER_NAME ?= /sem_server +SERVER_ITERS ?= 1000 + +all: shm + +shm: server client + +server: server.c + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS_IPC) + +client: client.c + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS_IPC) + +test_server: shm + @echo "=== Запуск сервера POSIX SHM+SEM ===" + @echo "В другом терминале выполните: make test_client" + ./server $(SHM_NAME) $(SEM_CLIENT_NAME) $(SEM_SERVER_NAME) $(SERVER_ITERS) + +test_client: shm + @echo "=== Запуск клиента, чтение input.txt, вывод на stdout ===" + ./client $(SHM_NAME) $(SEM_CLIENT_NAME) $(SEM_SERVER_NAME) + +test_all: shm + @echo "=== Автотест POSIX SHM+SEM с файлами input.txt/output.txt ===" + ./server $(SHM_NAME) $(SEM_CLIENT_NAME) $(SEM_SERVER_NAME) $(SERVER_ITERS) & \ + SRV=$$!; \ + sleep 1; \ + ./client $(SHM_NAME) $(SEM_CLIENT_NAME) $(SEM_SERVER_NAME); \ + wait $$SRV + +clean: + @echo "Очистка..." + rm -f server client + rm -f output.txt + +help: + @echo "Available targets:" + @echo " shm - Build POSIX SHM+SEM programs" + @echo " test_server - Run SHM+SEM server (client in another terminal)" + @echo " test_client - Run client reading input.txt" + @echo " test_all - Automatic end-to-end test with input.txt/output.txt" + @echo " clean - Remove built files" + @echo " help - Show this help" + +.PHONY: all shm test_server test_client test_all clean help diff --git a/lab_6/kirill/client.c b/lab_6/kirill/client.c new file mode 100644 index 0000000..7e34809 --- /dev/null +++ b/lab_6/kirill/client.c @@ -0,0 +1,141 @@ +// client.c + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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[]) { + if (argc < 4) { + fprintf(stderr, + "Usage: %s \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]; + + int shm_fd = shm_open(shm_name, O_RDWR, 0); + if (shm_fd == -1) { + perror("shm_open"); + return -1; + } + + 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; + } + + if (close(shm_fd) == -1) { + perror("close"); + } + + 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; + } + + FILE *fin = fopen("input.txt", "r"); + if (!fin) { + perror("fopen(input.txt)"); + sem_close(sem_client); + sem_close(sem_server); + munmap(shm_ptr, sizeof(shared_block_t)); + return -1; + } + + char input[SHM_BUFFER_SIZE]; + + while (fgets(input, sizeof(input), fin) != NULL) { + 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)); + strncpy(shm_ptr->buffer, input, SHM_BUFFER_SIZE - 1); + shm_ptr->buffer[SHM_BUFFER_SIZE - 1] = '\0'; + + shm_ptr->has_data = 1; + + if (sem_post(sem_client) == -1) { + perror("sem_post(sem_client)"); + fclose(fin); + sem_close(sem_client); + sem_close(sem_server); + munmap(shm_ptr, sizeof(shared_block_t)); + return -1; + } + + if (sem_wait(sem_server) == -1) { + perror("sem_wait(sem_server)"); + fclose(fin); + 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); + fclose(fin); + sem_close(sem_client); + sem_close(sem_server); + munmap(shm_ptr, sizeof(shared_block_t)); + return -1; + } + + printf("%s\n", shm_ptr->buffer); + } + + if (fclose(fin) == EOF) { + perror("fclose(input.txt)"); + } + + 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; +} diff --git a/lab_6/kirill/input.txt b/lab_6/kirill/input.txt new file mode 100644 index 0000000..c640816 --- /dev/null +++ b/lab_6/kirill/input.txt @@ -0,0 +1,6 @@ +abacaba +xxxxxx +hello +aaaaa +1abc1d1e1 +qwerty diff --git a/lab_6/kirill/server.c b/lab_6/kirill/server.c new file mode 100644 index 0000000..fe5be65 --- /dev/null +++ b/lab_6/kirill/server.c @@ -0,0 +1,185 @@ +// server.c + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHM_BUFFER_SIZE 1024 + +typedef struct { + int has_data; + int result_code; + char buffer[SHM_BUFFER_SIZE]; +} shared_block_t; + +static void process_line(char *s) { + if (!s) return; + for (size_t i = 0; s[i] != '\0'; ++i) { + if ((i + 1) % 3 == 0) { + s[i] = ' '; + } + } +} + +int main(int argc, char *argv[]) { + if (argc < 4) { + fprintf(stderr, + "Usage: %s [iterations]\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]; + + int iterations = -1; + if (argc >= 5) { + char *endptr = NULL; + unsigned long tmp = strtoul(argv[4], &endptr, 10); + if (endptr == argv[4] || *endptr != '\0') { + fprintf(stderr, "Invalid iterations value: '%s'\n", argv[4]); + return -1; + } + iterations = (int) tmp; + } + + shm_unlink(shm_name); + sem_unlink(sem_client_name); + sem_unlink(sem_server_name); + + int shm_fd = shm_open(shm_name, + O_CREAT | O_EXCL | O_RDWR, + S_IRUSR | S_IWUSR); + if (shm_fd == -1) { + perror("shm_open"); + return -1; + } + + if (ftruncate(shm_fd, sizeof(shared_block_t)) == -1) { + perror("ftruncate"); + close(shm_fd); + shm_unlink(shm_name); + return -1; + } + + 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); + shm_unlink(shm_name); + return -1; + } + + if (close(shm_fd) == -1) { + perror("close"); + } + + shm_ptr->has_data = 0; + shm_ptr->result_code = 0; + memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer)); + + sem_t *sem_client = sem_open(sem_client_name, + O_CREAT | O_EXCL, + S_IRUSR | S_IWUSR, + 0); + if (sem_client == SEM_FAILED) { + perror("sem_open(sem_client)"); + munmap(shm_ptr, sizeof(shared_block_t)); + shm_unlink(shm_name); + return -1; + } + + sem_t *sem_server = sem_open(sem_server_name, + O_CREAT | O_EXCL, + S_IRUSR | S_IWUSR, + 0); + if (sem_server == SEM_FAILED) { + perror("sem_open(sem_server)"); + sem_close(sem_client); + sem_unlink(sem_client_name); + munmap(shm_ptr, sizeof(shared_block_t)); + shm_unlink(shm_name); + return -1; + } + + FILE *fout = fopen("output.txt", "w"); + if (!fout) { + perror("fopen(output.txt)"); + } + + int processed_count = 0; + + while (iterations < 0 || processed_count < iterations) { + if (sem_wait(sem_client) == -1) { + perror("sem_wait(sem_client)"); + processed_count = -1; + break; + } + + if (!shm_ptr->has_data) { + fprintf(stderr, "Warning: sem_client posted, but has_data == 0\n"); + shm_ptr->result_code = -1; + } else { + process_line(shm_ptr->buffer); + shm_ptr->result_code = 0; + shm_ptr->has_data = 0; + processed_count++; + + if (fout) { + fprintf(fout, "%s\n", shm_ptr->buffer); + fflush(fout); + } + } + + if (sem_post(sem_server) == -1) { + perror("sem_post(sem_server)"); + processed_count = -1; + break; + } + } + + if (fout && fclose(fout) == EOF) { + perror("fclose(output.txt)"); + } + + if (processed_count >= 0) { + printf("%d\n", processed_count); + } else { + printf("-1\n"); + } + + if (sem_close(sem_client) == -1) { + perror("sem_close(sem_client)"); + } + if (sem_close(sem_server) == -1) { + perror("sem_close(sem_server)"); + } + + if (sem_unlink(sem_client_name) == -1) { + perror("sem_unlink(sem_client)"); + } + if (sem_unlink(sem_server_name) == -1) { + perror("sem_unlink(sem_server)"); + } + + if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) { + perror("munmap"); + } + if (shm_unlink(shm_name) == -1) { + perror("shm_unlink"); + } + + return 0; +}