From 4eabd5640505625d7b7d4a4d29870b3f230992b7 Mon Sep 17 00:00:00 2001 From: Francesco Di Stasio Date: Wed, 7 Aug 2024 23:43:52 +0200 Subject: [PATCH] Add processes algorithms --- processes/dup2.c | 67 ++++++++++++++++ processes/dup2_pipe.c | 74 ++++++++++++++++++ processes/exec.c | 45 +++++++++++ processes/fork.c | 47 ++++++++++++ processes/macros.h | 2 + processes/pipe.c | 66 ++++++++++++++++ processes/semaphores.c | 158 ++++++++++++++++++++++++++++++++++++++ processes/shared_memory.c | 69 +++++++++++++++++ 8 files changed, 528 insertions(+) create mode 100644 processes/dup2.c create mode 100644 processes/dup2_pipe.c create mode 100644 processes/exec.c create mode 100644 processes/fork.c create mode 100644 processes/macros.h create mode 100644 processes/pipe.c create mode 100644 processes/semaphores.c create mode 100644 processes/shared_memory.c diff --git a/processes/dup2.c b/processes/dup2.c new file mode 100644 index 00000000..88dbac00 --- /dev/null +++ b/processes/dup2.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include "macros.h" + +#define BUFFER_SIZE 1024 + +// fork(), pipe(), dup2(), execlp() + +int main() { + int retvalue, pipe_fd[2]; + + // Create pipe + SYSC(retvalue, pipe(pipe_fd), "pipe error"); + + // Create Child Process + + pid_t pid; + SYSC(pid, fork(), "fork error"); + + if (pid == 0) { + + // Child Process + + // Close pipe file descriptor (read) + SYSC(retvalue, close(pipe_fd[0]), "close error"); + + // stdout redirection in pipe's write file descriptor + SYSC(retvalue, dup2(pipe_fd[1], STDOUT_FILENO), "dup2 error"); + + // Close pipe file descriptor (write) + SYSC(retvalue, close(pipe_fd[1]), "close error"); + + // Exec "ls -la" + execlp("ls", "ls -la", (char *) NULL); + + // Exec error + perror("execlp"); + exit(EXIT_FAILURE); + + } else { + + // Father Process + + char buffer[BUFFER_SIZE]; + + // Close pipe file descriptor (write) + SYSC(retvalue, close(pipe_fd[1]), "close error"); + + // Read from pipe + ssize_t n_read; + SYSC(n_read, read(pipe_fd[0], buffer, BUFFER_SIZE), "read error"); + + // Write on pipe + SYSC(retvalue, write(STDOUT_FILENO, buffer, n_read), "write error"); + + // Close pipe file descriptor (read) + SYSC(retvalue, close(pipe_fd[0]), "close error"); + + // Wait child process + SYSC(retvalue, waitpid(pid, NULL, 0), "waitpid error"); + } + + return 0; +} \ No newline at end of file diff --git a/processes/dup2_pipe.c b/processes/dup2_pipe.c new file mode 100644 index 00000000..f5d27547 --- /dev/null +++ b/processes/dup2_pipe.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include "macros.h" +#include "constants.h" +#include +#include +#include +#include +#include + +// fork(), pipe(), dup2(), execlp() + +int main(int argc, char* argv[]){ + + pid_t pid_ls, pid_wc; + int pfd[2], ret_value; + + // Create Pipe + SYSC(ret_value, pipe(pfd), "Pipe error"); + + // Create Child Process (will exec ls -l) + SYSC(pid_ls, fork(), "fork error"); + + if (pid_ls == 0) { + + // Child Process + + // stdout redirection in pipe's write file descriptor + SYSC(ret_value, dup2(pfd[1], fileno(stdout)), "dup2 error"); + + // Close pipe file descriptors (read and write) + SYSC(ret_value, close(pfd[1]), "close pipe error"); + SYSC(ret_value, close(pfd[0]), "close pipe error"); + + // Exec "ls -l" + execlp("ls", "ls", "-l", NULL); + + // Exec error + perror("exec"); + exit(EXIT_FAILURE); + } + + // Create Child Process (will exec wc -l) + SYSC(pid_wc, fork(), "fork error"); + + if (pid_wc == 0) { + + // Child Process + + // stdin redirection in pipe's read file descriptor + SYSC(ret_value, dup2(pfd[0], fileno(stdin)), "dup2 error"); + + // Close pipe file descriptors (read and write) + SYSC(ret_value, close(pfd[0]), "close pipe error"); + SYSC(ret_value, close(pfd[1]), "close pipe error"); + + // Exec "wc -l" + execlp("wc", "wc", "-l", NULL); + + // Exec error + perror("exec"); + exit(EXIT_FAILURE); + + } + + // Close pipe file descriptors (read and write) + SYSC(ret_value, close(pfd[1]), "close pipe error"); + SYSC(ret_value, close(pfd[0]), "close pipe error"); + + // Wait Child processes + SYSC(ret_value, waitpid(pid_ls, NULL, 0), "waitpid error"); + SYSC(ret_value, waitpid(pid_wc, NULL, 0), "waitpid error"); +} diff --git a/processes/exec.c b/processes/exec.c new file mode 100644 index 00000000..8e808348 --- /dev/null +++ b/processes/exec.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include "macros.h" + +// fork(), exec(), waitpid() + +int main() { + + pid_t pid; + int retvalue; + SYSC(pid, fork(), "fork error"); + + if (pid == 0) { + // Child Process + + // Exec ls -l + char *args[] = {"ls", "-l", NULL}; + execvp("ls", args); + + // Exec error + perror("exec"); + return 1; + + } else { + + // Father Process + + // Wait Child Process + int status; + pid_t child_pid; + SYSC(child_pid, waitpid(pid, &status, 0), "waitpid error"); + + if (WIFEXITED(status)) { + printf("Child process exited with code: %d\n", WEXITSTATUS(status)); + } else { + printf("Child process exit error \n"); + } + } + + return 0; +} \ No newline at end of file diff --git a/processes/fork.c b/processes/fork.c new file mode 100644 index 00000000..4ce1070e --- /dev/null +++ b/processes/fork.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include "macros.h" + +// fork(), wait() + +int main() { + pid_t pid; + + // Create Child process + SYSC(pid, fork(), "fork error"); + + if (pid == 0) { + + // Child process + + printf("I'm the Child process, PID: %d\n", getpid()); + + // Exit from child process + exit(EXIT_SUCCESS); + + } else { + + // Father Process + + printf("I'm the Father process, PID: %d\n", getpid()); + + // Wait Child Process + int status; + pid_t child_pid; + SYSC(child_pid, wait(&status), "wait error"); + + + if (WIFEXITED(status)) { + printf("Child process exited with code: %d\n", WEXITSTATUS(status)); + } else { + printf("Child process exit error \n"); + } + + // Exit from father process + exit(EXIT_SUCCESS); + + } +} diff --git a/processes/macros.h b/processes/macros.h new file mode 100644 index 00000000..4c9c9b1c --- /dev/null +++ b/processes/macros.h @@ -0,0 +1,2 @@ +#define SYSC(value,command,message) if ((value = command) == -1){perror(message); exit(errno); } +#define SYSCN(value,command,message) if ((value = command) == NULL){perror(message); exit(errno); } diff --git a/processes/pipe.c b/processes/pipe.c new file mode 100644 index 00000000..f5de6847 --- /dev/null +++ b/processes/pipe.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include "macros.h" +#include +#include +#include + +#define BUFFER_SIZE 1024 + +// fork(), pipe() + +int main() { + int pipe_fd[2], retvalue; + pid_t pid; + char buffer[BUFFER_SIZE]; + + // Create Pipe + SYSC(retvalue, pipe(pipe_fd), "pipe error"); + + // Create child process + SYSC(pid, fork(), "fork error"); + + if (pid == 0) { + + // Child Process + + // Close pipe file descriptor (write) + SYSC(retvalue, close(pipe_fd[1]), "close error"); + + // Read from pipe + ssize_t n_read, n_written; + SYSC(n_read, read(pipe_fd[0], buffer, BUFFER_SIZE), "read error"); + + // Write on pipe + SYSC(n_written, write(STDOUT_FILENO, buffer, n_read), "write error"); + + // Close pipe file descriptor (read) + SYSC(retvalue, close(pipe_fd[0]), "close error"); + + exit(EXIT_SUCCESS); + + } else { + + // Father Process + + // Close pipe file descriptor (read) + SYSC(retvalue, close(pipe_fd[0]), "close error"); + + // Write on pipe + ssize_t n_written; + const char *data_to_send = "Hello child process!"; + SYSC(n_written, write(pipe_fd[1], data_to_send, strlen(data_to_send)), "write error"); + + // Close pipe file descriptor (write) + SYSC(retvalue, close(pipe_fd[1]), "nella close"); + + pid_t pid_c; + + // Wait child process + SYSC(pid_c, waitpid(pid, NULL, 0), "nella waitpid"); + } + + return 0; +} diff --git a/processes/semaphores.c b/processes/semaphores.c new file mode 100644 index 00000000..90d2161f --- /dev/null +++ b/processes/semaphores.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "macros.h" + +#define BUFFER_SIZE 10 +#define SHARED_MEM_NAME "/shared_memory" +#define SEM_MUTEX_NAME "/sem_mutex" +#define SEM_EMPTY_NAME "/sem_empty" +#define SEM_FULL_NAME "/sem_full" + +typedef struct { + char buffer[BUFFER_SIZE]; + int read_index; + int write_index; +} SharedData; + +void writer(sem_t*, sem_t*, sem_t*, SharedData*); +void reader(sem_t*, sem_t*, sem_t*, SharedData*); + + +int main() { + int shm_fd,retvalue; + sem_t *sem_mutex, *sem_empty, *sem_full; + SharedData *shared_data; + + // Create shared memory segment + SYSC(shm_fd, shm_open(SHARED_MEM_NAME, O_CREAT | O_RDWR, 0666), "shm_open error"); + SYSC(retvalue, ftruncate(shm_fd, sizeof(SharedData)), "ftruncate error"); + + // Shared memory mapping + SYSCN(shared_data, (SharedData *)mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0), "mmap error"); + + // Create semaphores + SYSCN(sem_mutex, sem_open(SEM_MUTEX_NAME, O_CREAT | O_EXCL, 0666, 1), "sem_mutex: open"); + SYSCN(sem_empty, sem_open(SEM_EMPTY_NAME, O_CREAT | O_EXCL, 0666, 0), "sem_empty: open"); + SYSCN(sem_full, sem_open(SEM_FULL_NAME, O_CREAT | O_EXCL, 0666, BUFFER_SIZE), "sem_full: open"); + + // Circular buffer init + shared_data->read_index = 0; + shared_data->write_index = 0; + + // Create Child process + SYSC(retvalue, fork(), "fork error"); + + if (!retvalue) { + + // Child Process (reader) + reader(sem_mutex, sem_empty, sem_full, shared_data); + + } else { + + // Father Process + + // Create Child process + SYSC(retvalue, fork(), "fork error"); + + if (!retvalue) { + + // Child Process (writer) + writer(sem_mutex, sem_empty, sem_full, shared_data); + } + } + + // Wait Child processes + SYSC(retvalue, wait(NULL), "wait error"); + + // Close resources + SYSC(retvalue, munmap(shared_data, sizeof(SharedData)), "munmap error"); + SYSC(retvalue, close(shm_fd), "close error"); + + SYSC(retvalue, sem_close(sem_mutex), "sem_close error"); + SYSC(retvalue, sem_close(sem_empty), "sem_close error"); + SYSC(retvalue, sem_close(sem_full), "sem_close error"); + + SYSC(retvalue, sem_unlink(SEM_MUTEX_NAME), "sem_unlink error"); + SYSC(retvalue, sem_unlink(SEM_EMPTY_NAME), "sem_unlink error"); + SYSC(retvalue, sem_unlink(SEM_FULL_NAME), "sem_unlink error"); + + SYSC(retvalue, shm_unlink(SHARED_MEM_NAME), "shm_unlink error"); + + return 0; +} + +void reader(sem_t *sem_mutex, sem_t *sem_empty, sem_t *sem_full, SharedData *shared_data) { + + char data; + int retvalue; + + while (1) { + + // Wait data + SYSC(retvalue, sem_wait(sem_empty), "sem_wait error"); + + // Mutex lock + SYSC(retvalue, sem_wait(sem_mutex), "sem_wait error"); + + // Read from buffer + data = shared_data->buffer[shared_data->read_index]; + shared_data->read_index = (shared_data->read_index + 1) % BUFFER_SIZE; + + // Mutex unlock + SYSC(retvalue, sem_post(sem_mutex), "sem_post error"); + + // Increment data on buffer full counter + SYSC(retvalue, sem_post(sem_full), "sem_post error"); + + // Write read data on stdout + printf("Reader - Read: %c\n", data); + + if(data == 'Z') exit(EXIT_SUCCESS); + + // Simulate elaboration time + usleep(100000); + } + +} + +void writer(sem_t *sem_mutex, sem_t *sem_empty, sem_t *sem_full, SharedData *shared_data) { + + char data = 'A'; + int retvalue; + + while (1) { + + // Wait free slots + SYSC(retvalue, sem_wait(sem_full), "sem_wait error"); + + // Mutex lock + SYSC(retvalue, sem_wait(sem_mutex), "sem_wait error"); + + // Write on buffer + shared_data->buffer[shared_data->write_index] = data; + shared_data->write_index = (shared_data->write_index + 1) % BUFFER_SIZE; + + // Mutex unlock + SYSC(retvalue, sem_post(sem_mutex), "sem_post error"); + + // Increment data on buffer empty counter + SYSC(retvalue, sem_post(sem_empty), "sem_post error"); + + // Write wrote data on stdout + printf("Writer - Wrote: %c\n", data); + + // Change char + if(data == 'Z') exit(EXIT_SUCCESS); + data = data + 1; + + // Simulate elaboration time + usleep(150000); + } +} diff --git a/processes/shared_memory.c b/processes/shared_memory.c new file mode 100644 index 00000000..9cf4dc51 --- /dev/null +++ b/processes/shared_memory.c @@ -0,0 +1,69 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "macros.h" +#define MEM_SIZE 4096 + +// fork(), shm_open(), mmap() + +int main (int argc, char *ARGV[]) { + + // Param check + if(argc != 2) { + fprintf(stderr, "Usage: %s \n", ARGV[0]); + exit(EXIT_FAILURE); + } + + int retvalue, mem_fd; + + // Create shared memory segment + SYSC(mem_fd, shm_open(ARGV[1], O_CREAT | O_RDWR, 0666), "shm_open error"); + SYSC(retvalue, ftruncate(mem_fd, MEM_SIZE), "ftruncate error"); + + // Create Child Process + pid_t pid; + SYSC(pid, fork(), "fork error"); + + if (pid == 0) { + + // Child Process + + // Shared memory mapping + void *ptr; + SYSCN(ptr, mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, 0), "mmap error"); + + // Write on shared memory segment + const char *msg = "Hello, shared memory!\n"; + SYSC(retvalue, sprintf(ptr, "%s", msg), "sprintf error"); + + // Shared memory unmapping + SYSC(retvalue, munmap(ptr, MEM_SIZE), "munmap error"); + exit(EXIT_SUCCESS); + + } else { + + // Father Process + + // Shared memory mapping + void *ptr; + SYSCN(ptr, mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, 0), "mmap error"); + + // Wait Child process + SYSC(retvalue, waitpid(pid, NULL, 0), "waitpid error"); + + // Write read data on stdout + SYSC(retvalue, write(STDOUT_FILENO, ptr, strlen(ptr)), "write error"); + + // Shared memory unmapping + SYSC(retvalue, munmap(ptr, MEM_SIZE), "munmap error"); + exit(EXIT_SUCCESS); + } +}