diff options
author | Santo Cariotti <santo@dcariotti.me> | 2021-09-24 20:09:56 +0200 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2021-09-24 20:09:56 +0200 |
commit | 08860d002a81ca71406c49c33e300441bc110d50 (patch) | |
tree | f9f30d37a2245b4550270a3d99f79ea6ca39a41e /Year_2 | |
parent | efaec4509af562d79582dad8017334d778489aaa (diff) |
os: add homework 8
Diffstat (limited to 'Year_2')
-rw-r--r-- | Year_2/OS/hw/hw8.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Year_2/OS/hw/hw8.c b/Year_2/OS/hw/hw8.c new file mode 100644 index 0000000..0e2ecc4 --- /dev/null +++ b/Year_2/OS/hw/hw8.c @@ -0,0 +1,163 @@ +/* + Homework n.8 + + Modificare l'homework precedente (n.7) sostituendo il canale di comuniciazione + offerto dalla coda di messaggi tra padre e figlio con un segmento di memoria + condiviso e una coppia di semafori (esattamente due) opportunamente utilizzati + per il coordinamento. + +*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define DIM_MSG 1024 + +int +WAIT(int des, int n) +{ + struct sembuf op[1] = { { n, -1, 0 } }; + return semop(des, op, 1); +} + +int +SIGNAL(int des, int n) +{ + struct sembuf op[1] = { { n, 1, 0 } }; + return semop(des, op, 1); +} + +void +execute(int id_shm, int id_sem) +{ + pid_t pid; + char* msg; + char command[DIM_MSG]; + int n; + char* p; + int pipefd[2]; + + if ((msg = (char*)shmat(id_shm, NULL, 0)) == (char*)-1) { + perror("shmat"); + exit(1); + } + + while (1) { + WAIT(id_sem, 0); + + /* The variable `command` will be the substring of the passed string + * until the first space, ignoring all parameters */ + n = 0; + p = msg; + while (*p != '\0') { + if (*p == ' ') + break; + n++; + p++; + } + + strncpy(command, msg, n); + command[n] = '\0'; + + if (strcmp(command, "exit") == 0) + break; + + if (pipe(pipefd) == -1) { + perror("pipe"); + exit(1); + } + + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(1); + } + + if (pid == 0) { + dup2(pipefd[1], 1); + dup2(pipefd[1], 2); + close(pipefd[0]); + execlp(command, "", NULL); + fprintf(stderr, "Error executing '%s'\n", command); + exit(1); + } else { + wait(NULL); + + close(pipefd[1]); + n = read(pipefd[0], msg, 1024); + msg[n] = '\0'; + SIGNAL(id_sem, 1); + close(pipefd[0]); + } + } +} + +int +main() +{ + int id_shm, id_sem; + int pid; + int n; + char* msg; + + if ((id_shm = shmget(IPC_PRIVATE, DIM_MSG, IPC_CREAT | 0644)) == -1) { + perror("shmget"); + exit(1); + } + + if ((id_sem = semget(IPC_PRIVATE, 2, IPC_CREAT | 0644)) == -1) { + perror("semget"); + exit(1); + } + + /* Set values to 0 */ + semctl(id_sem, 0, SETVAL, 0); + semctl(id_sem, 1, SETVAL, 0); + + pid = fork(); + if (pid == -1) { + perror("fork"); + exit(1); + } + + if ((msg = (char*)shmat(id_shm, NULL, 0)) == (char*)-1) { + perror("shmat"); + exit(1); + } + + if (pid != 0) { + while (1) { + printf("Insert a command: "); + fgets(msg, DIM_MSG, stdin); + n = strlen(msg); + msg[n - 1] = '\0'; + + /* Ignore empty string */ + if (strcmp(msg, "") == 0) + continue; + + SIGNAL(id_sem, 0); + + if (strcmp(msg, "exit") == 0) { + break; + } + + WAIT(id_sem, 1); + printf("%s\n", msg); + sleep(1); + } + } else { + execute(id_shm, id_sem); + } + + shmctl(id_shm, IPC_RMID, NULL); + semctl(id_sem, 0, IPC_RMID, 0); + + return 0; +} |