Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once. Thus, one step towards the ...
Answer
#5: Post edited
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will delay the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
And, finally, as your code seems to calculate the area of a triangle: The area of a triangle should be calculated using the formula `base * height / 2` rather than just `base * height`.
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will delay the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
- And, finally, as your code seems to calculate the area of a triangle: The area of a triangle should be calculated using the formula `base * height / 2` (but probably better using floating point) rather than just `base * height`.
#4: Post edited
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will delay the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
```
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will delay the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
- And, finally, as your code seems to calculate the area of a triangle: The area of a triangle should be calculated using the formula `base * height / 2` rather than just `base * height`.
#3: Post edited
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
The added `usleep` will give the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will delay the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
#2: Post edited
Your code has several issues. One issue is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will give the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
- One problem of your code is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once.
- Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop.
- However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available.
- You will see this when modifying the code as follows:
- ```
- default:
- break;
- }
- usleep(1000000);
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- ```
- The added `usleep` will give the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user.
- You can reach your (assumed) goal, for example, by changing the code in the following way:
- ```
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <string.h>
- #define SEM_KEY (key_t)8765
- #define SHM_KEY (key_t)9876
- /** Questa union la trovate digitando "man semctl" */
- union semun
- {
- int val; /* Value for SETVAL */
- struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
- unsigned short *array; /* Array for GETALL, SETALL */
- struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */
- };
- /** Tipo di dato condiviso */
- struct sh_data
- {
- int altezza;
- int base;
- };
- /** Funzioni di appoggio per operare con i semafori */
- int sem_set(int semid, int val);
- int sem_wait_for_zero(int semid);
- int sem_down(int semid);
- int sem_add_two(int semid);
- void controlla_area(int, struct sh_data *);
- int main()
- {
- pid_t pid;
- int semid, shmid, i;
- struct sh_data *data;
- // SEMAFORO
- // Creazione del semaforo
- semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
- // Inizializzazione semaforo
- sem_set(semid, 0); // no data available yet
- // SHARED MEMORY
- // Creazione shared memory
- shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT);
- // Attach della shm allo spazio di indirizzi del processo
- data = (struct sh_data *)shmat(shmid, NULL, 0);
- // Processo figlio
- pid = fork();
- switch (pid)
- {
- case -1:
- perror("Errore fork");
- exit(EXIT_FAILURE);
- case 0:
- controlla_area(semid, data);
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- // Processo padre
- for (i = 0; i < 4; i++)
- {
- sem_wait_for_zero(semid); // no data yet or ready with processing
- printf("Inserisci la base: ");
- scanf("%d", &(data->base));
- printf("Inserisci l'altezza: ");
- scanf("%d", &(data->altezza));
- sem_add_two(semid); // signal that data is available
- }
- wait(NULL);
- // Detach della shared memory
- shmdt(data);
- // Eliminazione della shared memory
- shmctl(shmid, IPC_RMID, NULL);
- // Eliminazione semaforo
- semctl(semid, 0, IPC_RMID);
- exit(EXIT_SUCCESS);
- }
- void controlla_area(int semid, struct sh_data *data)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- int area;
- sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1
- area = data->base * data->altezza;
- printf("L'area del triangolo è %d\n", area);
- sem_down(semid); // signal that data processing is done (decrement from 1 to 0)
- }
- }
- int sem_set(int semid, int val)
- {
- union semun s;
- s.val = val;
- /* Inizializza il valore del semaforo */
- return semctl(semid, 0, SETVAL, s);
- }
- int sem_wait_for_zero(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 0;
- buff.sem_flg = SEM_UNDO;
- // Wait for the semaphore value to become zero
- return semop(semid, &buff, 1);
- }
- int sem_down(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = -1;
- buff.sem_flg = SEM_UNDO;
- /* Decrementa il valore del semaforo */
- return semop(semid, &buff, 1);
- }
- int sem_add_two(int semid)
- {
- struct sembuf buff;
- buff.sem_num = 0;
- buff.sem_op = 2;
- buff.sem_flg = SEM_UNDO;
- // add two to the value of the semaphore
- return semop(semid, &buff, 1);
- }
- ```
#1: Initial revision
Your code has several issues. One issue is the one that @celtschk already has reported: You start one child process, and that one child process does the area calculation exactly once. Thus, one step towards the proper solution is to either spawn one child process per calculation, or have the child process also perform the calculation in a loop. However, there is another issue with your solution: The synchronization does not work properly. Your semaphore acts as a mutex for the shared memory, but not as an indication of data readiness. That is, depending on the actual timing, the calculation might start even if no data is available. You will see this when modifying the code as follows: ``` default: break; } usleep(1000000); // Processo padre for (i = 0; i < 4; i++) { ``` The added `usleep` will give the parent process long enough for the child process to start executing. And, as a result the computation starts even before the first value has been queried from the user. You can reach your (assumed) goal, for example, by changing the code in the following way: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <string.h> #define SEM_KEY (key_t)8765 #define SHM_KEY (key_t)9876 /** Questa union la trovate digitando "man semctl" */ union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */ }; /** Tipo di dato condiviso */ struct sh_data { int altezza; int base; }; /** Funzioni di appoggio per operare con i semafori */ int sem_set(int semid, int val); int sem_wait_for_zero(int semid); int sem_down(int semid); int sem_add_two(int semid); void controlla_area(int, struct sh_data *); int main() { pid_t pid; int semid, shmid, i; struct sh_data *data; // SEMAFORO // Creazione del semaforo semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT); // Inizializzazione semaforo sem_set(semid, 0); // no data available yet // SHARED MEMORY // Creazione shared memory shmid = shmget(SHM_KEY, sizeof(struct sh_data), 0666 | IPC_CREAT); // Attach della shm allo spazio di indirizzi del processo data = (struct sh_data *)shmat(shmid, NULL, 0); // Processo figlio pid = fork(); switch (pid) { case -1: perror("Errore fork"); exit(EXIT_FAILURE); case 0: controlla_area(semid, data); exit(EXIT_SUCCESS); default: break; } // Processo padre for (i = 0; i < 4; i++) { sem_wait_for_zero(semid); // no data yet or ready with processing printf("Inserisci la base: "); scanf("%d", &(data->base)); printf("Inserisci l'altezza: "); scanf("%d", &(data->altezza)); sem_add_two(semid); // signal that data is available } wait(NULL); // Detach della shared memory shmdt(data); // Eliminazione della shared memory shmctl(shmid, IPC_RMID, NULL); // Eliminazione semaforo semctl(semid, 0, IPC_RMID); exit(EXIT_SUCCESS); } void controlla_area(int semid, struct sh_data *data) { int i; for (i = 0; i < 4; i++) { int area; sem_down(semid); // wait until data is available (semaphore has value 2) and decrement from 2 to 1 area = data->base * data->altezza; printf("L'area del triangolo è %d\n", area); sem_down(semid); // signal that data processing is done (decrement from 1 to 0) } } int sem_set(int semid, int val) { union semun s; s.val = val; /* Inizializza il valore del semaforo */ return semctl(semid, 0, SETVAL, s); } int sem_wait_for_zero(int semid) { struct sembuf buff; buff.sem_num = 0; buff.sem_op = 0; buff.sem_flg = SEM_UNDO; // Wait for the semaphore value to become zero return semop(semid, &buff, 1); } int sem_down(int semid) { struct sembuf buff; buff.sem_num = 0; buff.sem_op = -1; buff.sem_flg = SEM_UNDO; /* Decrementa il valore del semaforo */ return semop(semid, &buff, 1); } int sem_add_two(int semid) { struct sembuf buff; buff.sem_num = 0; buff.sem_op = 2; buff.sem_flg = SEM_UNDO; // add two to the value of the semaphore return semop(semid, &buff, 1); } ```