From da93cb8369bef0161bae89d05fad0122b243bdcf Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Mon, 26 Aug 2024 15:35:43 +0200 Subject: [PATCH] Added Process exercise's chapter --- .gitignore | 61 ++++++++++++++++++++++++++++++++++++ bitmap.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ bitmap.h | 22 +++++++++++++ collatz.c | 54 ++++++++++++++++++++++++++++++++ collatz_shm.c | 64 +++++++++++++++++++++++++++++++++++++ collatz_shm2.c | 60 +++++++++++++++++++++++++++++++++++ cons.c | 21 +++++++++++++ ex1.c | 46 +++++++++++++++++++++++++++ ex12.c | 39 +++++++++++++++++++++++ ex13.c | 23 ++++++++++++++ ex14.c | 27 ++++++++++++++++ ex17.c | 29 +++++++++++++++++ ex19.c | 18 +++++++++++ pid_manager.c | 63 +++++++++++++++++++++++++++++++++++++ pid_manager.h | 15 +++++++++ prod.c | 31 ++++++++++++++++++ test.c | 7 +++++ 17 files changed, 665 insertions(+) create mode 100644 .gitignore create mode 100644 bitmap.c create mode 100644 bitmap.h create mode 100644 collatz.c create mode 100644 collatz_shm.c create mode 100644 collatz_shm2.c create mode 100644 cons.c create mode 100644 ex1.c create mode 100644 ex12.c create mode 100644 ex13.c create mode 100644 ex14.c create mode 100644 ex17.c create mode 100644 ex19.c create mode 100644 pid_manager.c create mode 100644 pid_manager.h create mode 100644 prod.c create mode 100644 test.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce94c57 --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Created by https://www.toptal.com/developers/gitignore/api/c +# Edit at https://www.toptal.com/developers/gitignore?templates=c + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# User specific +/kernel-sign + +# End of https://www.toptal.com/developers/gitignore/api/c diff --git a/bitmap.c b/bitmap.c new file mode 100644 index 0000000..c738724 --- /dev/null +++ b/bitmap.c @@ -0,0 +1,85 @@ +#include "bitmap.h" +#include +#include + +#ifdef bitmap_64 +#define bitmap_type unsigned long long int +#define bitmap_shift 6 +#define bitmap_mask 63 +#define bitmap_wordlength 64 +#define bitmap_fmt "%016llx" +#else // assumed to be 32 bits +#define bitmap_type unsigned int +#define bitmap_shift 5 +#define bitmap_mask 31 +#define bitmap_wordlength 32 +#define bitmap_fmt "%08x" +#endif + +// get the types right +#define bitmap_one (bitmap_type)1 + +// we expect 0 <= n and n < b->bits, but it is not verified + +// arch a 8 bit +// bitmap shift 3 +// wordlength 8 + +// n = 10 -> 00001010 +// 00000001 -> word = 1 +// +// n = 12 -> 00001100 +// mask = 7 -> 00000111 +// 00000100 = 4 +// 00000001 -> word = 1 +// +// n = 32 -> 00100000 +// mask = 7 -> 00000111 +// 00000000 +// 00000100 -> word = 4 +// +// n = 127 -> 01111111 +// mask = 7 -> 00000111 +// position = 7 -> 00000111 +// + +void bitmap_set(bitmap *b, int n) { + int word = n >> bitmap_shift; // n / bitmap_wordlength + int position = n & bitmap_mask; // n % bitmap_wordlength + b->array[word] |= bitmap_one << position; +} + +void bitmap_clear(bitmap *b, int n) { + int word = n >> bitmap_shift; // n / bitmap_wordlength + int position = n & bitmap_mask; // n % bitmap_wordlength + b->array[word] &= ~(bitmap_one << position); +} + +int bitmap_read(bitmap *b, int n) { + int word = n >> bitmap_shift; // n / bitmap_wordlength + int position = n & bitmap_mask; // n % bitmap_wordlength + return (b->array[word] >> position) & 1; +} + +bitmap *bitmap_allocate(int bits) { + // error-checking should be better :-) + bitmap *b = malloc(sizeof(bitmap)); + b->bits = bits; + b->words = (bits + bitmap_wordlength - 1) / bitmap_wordlength; + // divide, but round up for the ceiling + b->array = calloc(b->words, sizeof(bitmap_type)); + return b; +} + +void bitmap_deallocate(bitmap *b) { + // error-checking should be better :-) + free(b->array); + free(b); +} + +void bitmap_print(bitmap *b) { + for (int i = 0; i < b->words; i++) { + printf(" " bitmap_fmt, b->array[i]); + } + printf("\n"); +} diff --git a/bitmap.h b/bitmap.h new file mode 100644 index 0000000..7b4d45d --- /dev/null +++ b/bitmap.h @@ -0,0 +1,22 @@ +// use dynamic allocation with these functions +// compile with -Dbitmap_64 to force 64-bit words +// compile with -O [dash capital o] for more efficient machine code + +#ifdef bitmap_64 +#define bitmap_type unsigned long long int +#else // assumed to be 32 bits +#define bitmap_type unsigned int +#endif + +typedef struct { + int bits; // number of bits in the array + int words; // number of words in the array + bitmap_type *array; +} bitmap; + +void bitmap_set(bitmap *b, int n); // n is a bit index +void bitmap_clear(bitmap *b, int n); +int bitmap_read(bitmap *b, int n); +bitmap *bitmap_allocate(int bits); +void bitmap_deallocate(bitmap *b); +void bitmap_print(bitmap *b); diff --git a/collatz.c b/collatz.c new file mode 100644 index 0000000..d04276b --- /dev/null +++ b/collatz.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +int collatz(int, int[], int); +void print_buffer(int buff[]); + +int main(int argc, char *argv[]) { + if (argc < 2) { + perror("Usage: collatz NUMBER\n"); + return EXIT_FAILURE; + } + + int n = atoi(argv[1]); + if (n <= 1) { + perror("The number MUST be greater than 1\n"); + return EXIT_FAILURE; + } + + printf("Collatz of %d\n", n); + + pid_t pid = fork(); + if (pid == 0) { + int buff[1024] = {0}; + collatz(n, buff, 0); + print_buffer(buff); + } else if (pid > 0) { + wait(NULL); + } + + return EXIT_SUCCESS; +} + +int collatz(int n, int buff[], int steps) { + buff[steps] = n; + if (n == 1) { + return n; + } else if (n % 2 == 0) { + return collatz(n / 2, buff, steps + 1); + } else { + return collatz(3 * n + 1, buff, steps + 1); + } +} + +void print_buffer(int buff[]) { + int i = 0; + while (buff[i] != 0) { + printf("%d ", buff[i]); + i++; + } + printf("\n"); +} diff --git a/collatz_shm.c b/collatz_shm.c new file mode 100644 index 0000000..0528c72 --- /dev/null +++ b/collatz_shm.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SIZE 4096 +#define SHM_NAME "collatz" + +int collatz(int, void *); + +int main(int argc, char *argv[]) { + if (argc < 2) { + perror("Usage: collatz NUMBER\n"); + return EXIT_FAILURE; + } + + int n = atoi(argv[1]); + if (n <= 1) { + perror("The number MUST be greater than 1\n"); + return EXIT_FAILURE; + } + + printf("Collatz of %d\n", n); + + // Create memory shared object + int fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0600); + ftruncate(fd, SIZE); + void *ptr = (int *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + pid_t pid = fork(); + if (pid == 0) { + collatz(n, ptr); + } else if (pid > 0) { + wait(NULL); + + printf("%s\n", (char *)ptr); + shm_unlink(SHM_NAME); + } + + return EXIT_SUCCESS; +} + +int collatz(int n, void *shm) { + char buff[50]; + sprintf(buff, "%d", n); + sprintf(shm, "%s", buff); + shm += strlen(buff); + + sprintf(shm, "%s", " "); + shm += 1; + + if (n == 1) { + return n; + } else if (n % 2 == 0) { + return collatz(n / 2, shm); + } else { + return collatz(3 * n + 1, shm); + } +} diff --git a/collatz_shm2.c b/collatz_shm2.c new file mode 100644 index 0000000..dfef3ef --- /dev/null +++ b/collatz_shm2.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int collatz(int, int *, int); +void print_buffer(int buff[]); + +int main(int argc, char *argv[]) { + if (argc < 2) { + perror("Usage: collatz NUMBER\n"); + return EXIT_FAILURE; + } + + int n = atoi(argv[1]); + if (n <= 1) { + perror("The number MUST be greater than 1\n"); + return EXIT_FAILURE; + } + + printf("Collatz of %d\n", n); + + int *buff = mmap(NULL, sizeof(int *) * 1024, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + pid_t pid = fork(); + if (pid == 0) { + collatz(n, buff, 0); + } else if (pid > 0) { + wait(NULL); + print_buffer(buff); + } + + return EXIT_SUCCESS; +} + +int collatz(int n, int *shm, int steps) { + *(shm + steps) = n; + if (n == 1) { + return n; + } else if (n % 2 == 0) { + return collatz(n / 2, shm, steps + 1); + } else { + return collatz(3 * n + 1, shm, steps + 1); + } +} + +void print_buffer(int buff[]) { + int i = 0; + while (buff[i] != 0) { + printf("%d ", buff[i]); + i++; + } + printf("\n"); +} diff --git a/cons.c b/cons.c new file mode 100644 index 0000000..409b1b8 --- /dev/null +++ b/cons.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + const int SIZE = 4096; + const char *name = "OS"; + + int shm_fd; + void *ptr; + + shm_fd = shm_open(name, O_RDONLY, 0666); + ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0); + printf("%s", (char *)ptr); + shm_unlink(name); +} diff --git a/ex1.c b/ex1.c new file mode 100644 index 0000000..9015b9c --- /dev/null +++ b/ex1.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +struct MyStruct { + int value; +}; + +int value = 5; + +int main(void) +{ + struct MyStruct *str; + str->value = 5; + + int *p = malloc(sizeof(int)); + *p = 100; + + printf("PARENT: %p\n", &value); + printf("PARENT: %p\n", str); + printf("PARENT: %p\n", p); + + pid_t pid; + pid = fork(); + + if (pid == 0) { + value += 15; + str->value += 15; + *p += 10; + printf("CHILD: %p, %d\n", &value, value); + printf("CHILD: %p, %d\n", &str->value, str->value); + printf("CHILD: %p, %d\n", p, *p); + return 0; + } else if (pid > 0) { + wait(NULL); + printf("PARENT: value = %d\n", value); + printf("PARENT: value = %d\n", str->value); + printf("PARENT: value = %d\n", *p); + + free(p); + + return 0; + } +} diff --git a/ex12.c b/ex12.c new file mode 100644 index 0000000..96a6ea3 --- /dev/null +++ b/ex12.c @@ -0,0 +1,39 @@ +#include +#include +#include + +void add_children(pid_t children[], pid_t pid); + +int main(void) +{ + pid_t parent_pid = getpid(); + pid_t children[1024] = {-1}; + for (int i = 0; i < 4; i++) { + pid_t pid = fork(); + add_children(children, pid); + } + + if (parent_pid = getpid()) { + wait(NULL); + printf("pids: "); + for (int i = 0; i < 1024; i++) { + if (children[i] == -1) { + printf("\n"); + break; + } + printf("%d ", children[i]); + } + } + + return 0; +} + +void add_children(pid_t children[], pid_t pid) +{ + for (int i = 0; i < 1024; i++) { + if (children[i] < 0) { + children[i] = pid; + break; + } + } +} diff --git a/ex13.c b/ex13.c new file mode 100644 index 0000000..25d804a --- /dev/null +++ b/ex13.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +int main(void) +{ + pid_t pid; + pid = fork(); + + if (pid < 0) { + fprintf(stderr, "Fork failed\n"); + return 1; + } else if (pid == 0) { + execlp("/bin/ls", "ls", NULL); + printf("LINEA J\n"); + } else { + wait(NULL); + printf("Child complete\n"); + } + + return 0; +} diff --git a/ex14.c b/ex14.c new file mode 100644 index 0000000..2e10389 --- /dev/null +++ b/ex14.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include + +int main(void) { + pid_t pid, pid1; + + pid = fork(); + + if (pid < 0) { + fprintf(stderr, "Fork failed"); + return EXIT_FAILURE; + } else if (pid == 0) { + pid1 = getpid(); + printf("child: pid = %d\n", pid); // A + printf("child: pid1 = %d\n", pid1); // B + } else { + pid1 = getpid(); + printf("parent: pid = %d\n", pid); // C + printf("parent: pid1 = %d\n", pid1); // D + wait(NULL); + } + + return EXIT_SUCCESS; +} diff --git a/ex17.c b/ex17.c new file mode 100644 index 0000000..4e0d87d --- /dev/null +++ b/ex17.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#define SIZE 5 + +int nums[SIZE] = {0, 1, 2, 3, 4}; + +int main(void) { + int i; + pid_t pid; + + pid = fork(); + + if (pid == 0) { + for (i = 0; i < SIZE; i++) { + nums[i] *= -i; + printf("CHILD : %d\n", nums[i]); // Linea X + } + } else if (pid > 0) { + wait(NULL); + for (i = 0; i < SIZE; i++) { + printf("PARENT: %d\n", nums[i]); // Linea Y + } + } + + return EXIT_SUCCESS; +} diff --git a/ex19.c b/ex19.c new file mode 100644 index 0000000..6def429 --- /dev/null +++ b/ex19.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include + +int main(void) { + pid_t parent_pid = getpid(); + pid_t pid = fork(); + + if (pid > 0) { + printf("PARENT PID = %d, CHILD PID = %d\n", parent_pid, pid); + sleep(10); + wait(NULL); + } + + return EXIT_SUCCESS; +} diff --git a/pid_manager.c b/pid_manager.c new file mode 100644 index 0000000..bd21294 --- /dev/null +++ b/pid_manager.c @@ -0,0 +1,63 @@ +#include "pid_manager.h" +#include +#include +#include + +#define MIN_PID 300 +#define MAX_PID 5000 +#define SIZE (MAX_PID - MIN_PID + 1) + +bool pids[SIZE]; + +int allocate_map(void) { + for (int i = 0; i < SIZE; i++) { + pids[i] = false; + } + return 1; +} + +int allocate_pid(void) { + for (int i = 0; i < SIZE; i++) { + if (!pids[i]) { + pids[i] = true; + return i + MIN_PID; + } + } + return -1; +} + +void release_pid(int pid) { + if (pid >= MIN_PID && pid <= MAX_PID) { + pids[pid - MIN_PID] = false; + } +} + +int main(void) { + if (allocate_map() != 1) { + perror("Failed to initialiaze PID Manager\n"); + exit(1); + } + + for (int i = 0; i < SIZE; i++) { + printf("Allocate PID = %d\n", allocate_pid()); + } + + int last = allocate_pid(); + printf("Attempt to allocate another PID, result %d\n", last); + + if (last == -1) { + printf("Release a PID 4000\n"); + release_pid(4000); + } + + printf("Allocate another PID: %d\n", allocate_pid()); + + printf("Release PIDs 300 and 5000\n"); + release_pid(300); + release_pid(5000); + + printf("Allocate another PID: %d\n", allocate_pid()); + printf("Allocate another PID: %d\n", allocate_pid()); + + return 0; +} diff --git a/pid_manager.h b/pid_manager.h new file mode 100644 index 0000000..a8011f8 --- /dev/null +++ b/pid_manager.h @@ -0,0 +1,15 @@ +#if !defined(__PID_MANGER_H__) +#define __PID_MANGER_H__ + +// Crea e inizializza una struttura per rappresentare i pid; +// restituisce -1 in caso di insuccesso e 1 in caso di successo. +int allocate_map(void); + +// Alloca e restituisce un pid, restituisce -1 se non รจ possibile +// assegnare un PID (tutti i pid sono in uso). +int allocate_pid(void); + +// Rilascia un pid +void release_pid(int pid); + +#endif diff --git a/prod.c b/prod.c new file mode 100644 index 0000000..181a349 --- /dev/null +++ b/prod.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + const int SIZE = 4096; + const char *name = "OS"; + const char *message_0 = "Hello"; + const char *message_1 = "World!"; + + int shm_fd; + void *ptr; + + shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); + ftruncate(shm_fd, SIZE); + ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0); + sprintf(ptr, "%s", message_0); + ptr += strlen(message_0); + sprintf(ptr, "%s", " "); + ptr += 1; + sprintf(ptr, "%s", message_1); + ptr += strlen(message_1); + + return 0; +} diff --git a/test.c b/test.c new file mode 100644 index 0000000..8ec4683 --- /dev/null +++ b/test.c @@ -0,0 +1,7 @@ +#include + +int main(void) { + int n; + printf("%d\n", n); + return 0; +}