148 lines
5.2 KiB
C
148 lines
5.2 KiB
C
/// @file t_semget.c
|
|
/// @brief This program creates a son and then performs a blocking operation on
|
|
/// a semaphore. The son sleeps for five seconds and then it wakes up his
|
|
/// father and then it deletes the semaphore.
|
|
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
|
|
/// See LICENSE.md for details.
|
|
|
|
#include "sys/unistd.h"
|
|
#include "sys/errno.h"
|
|
#include "sys/sem.h"
|
|
#include "sys/ipc.h"
|
|
#include "stdlib.h"
|
|
#include "fcntl.h"
|
|
#include "stdio.h"
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct sembuf op_child;
|
|
struct sembuf op_father[3];
|
|
union semun arg;
|
|
long ret, semid;
|
|
key_t key;
|
|
|
|
// ========================================================================
|
|
// Generating a key using ftok
|
|
key = ftok("/home/user/test7.txt", 5);
|
|
if (key < 0) {
|
|
perror("Failed to generate key using ftok.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("Generated key using ftok (key = %d)\n", key);
|
|
|
|
// ========================================================================
|
|
// Create the first semaphore.
|
|
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
if (semid < 0) {
|
|
perror("Failed to create semaphore set.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[father] Created semaphore set (id : %d)\n", semid);
|
|
|
|
// ========================================================================
|
|
// Set the value of the semaphore in the structure.
|
|
arg.val = 1;
|
|
// Setting the semaphore value.
|
|
ret = semctl(semid, 0, SETVAL, &arg);
|
|
if (ret < 0) {
|
|
perror("Failed to set value of semaphore.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[father] Set semaphore value (id : %d, value : %d == 1)\n", semid, arg.val);
|
|
|
|
// ========================================================================
|
|
// Check if we successfully set the value of the semaphore.
|
|
ret = semctl(semid, 0, GETVAL, NULL);
|
|
if (ret < 0) {
|
|
perror("Failed to get the value of semaphore set.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[father] Get semaphore value (id : %d, value : %d == 1)\n", semid, ret);
|
|
|
|
// ========================================================================
|
|
// Create child process.
|
|
if (!fork()) {
|
|
// Initialize the operation structure.
|
|
op_child.sem_num = 0; // Operate on semaphore 0.
|
|
op_child.sem_op = 1; // Increment value by 1.
|
|
op_child.sem_flg = 0; // No flags.
|
|
|
|
// Semaphore has value 1.
|
|
sleep(3);
|
|
if (semop(semid, &op_child, 1) < 0) {
|
|
perror("Failed to perform first child operation.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[child] Succesfully performed opeation (id : %d)\n", semid);
|
|
|
|
// Check if we successfully set the value of the semaphore.
|
|
ret = semctl(semid, 0, GETVAL, NULL);
|
|
if (ret < 0) {
|
|
perror("Failed to get the value of semaphore set.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
|
|
|
|
// Semaphore has value 2, now the father can continue.
|
|
sleep(3);
|
|
if (semop(semid, &op_child, 1) < 0) {
|
|
perror("Failed to perform second child operation.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[child] Succesfully performed opeation (id : %d)\n", semid);
|
|
|
|
// Check if we successfully set the value of the semaphore.
|
|
ret = semctl(semid, 0, GETVAL, NULL);
|
|
if (ret < 0) {
|
|
perror("Failed to get the value of semaphore set.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[child] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
|
|
|
|
printf("[child] Exit, now.\n", semid, ret);
|
|
|
|
// Exit with the child process.
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Initialize the operation structure.
|
|
op_father[0].sem_num = 0; // Operate on semaphore 0.
|
|
op_father[0].sem_op = -1; // Decrement value by 1.
|
|
op_father[0].sem_flg = 0; // No flags.
|
|
op_father[1].sem_num = 0; // Operate on semaphore 0.
|
|
op_father[1].sem_op = -1; // Decrement value by 1.
|
|
op_father[1].sem_flg = 0; // No flags.
|
|
op_father[2].sem_num = 0; // Operate on semaphore 0.
|
|
op_father[2].sem_op = -1; // Decrement value by 1.
|
|
op_father[2].sem_flg = 0; // No flags.
|
|
|
|
// ========================================================================
|
|
// Perform the operations.
|
|
if (semop(semid, op_father, 3) < 0) {
|
|
perror("Failed to perform father operation.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
sleep(2);
|
|
|
|
printf("[father] Performed semaphore operations (id : %d)\n", semid);
|
|
|
|
// Check if we successfully set the value of the semaphore.
|
|
ret = semctl(semid, 0, GETVAL, NULL);
|
|
if (ret < 0) {
|
|
perror("Failed to get the value of semaphore set.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
printf("[father] Get semaphore value (id : %d, value : %d == 0)\n", semid, ret);
|
|
|
|
// Delete the semaphore set.
|
|
ret = semctl(semid, 0, IPC_RMID, 0);
|
|
if (ret < 0) {
|
|
perror("Failed to remove semaphore set.");
|
|
}
|
|
printf("[father] Correctly removed semaphore set.\n");
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|