C Synchronization: Semaphores for Process Control

Classified in Computers

Written on in English with a size of 5.09 KB

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <sys/time.h>

define DELAY_MICROSECONDS 1000 // Renamed ESPERA for clarity

int initialize_semaphore(int value); int operate_semaphore(int semaphore, int operation); int remove_semaphore(int semaphore); int semaphore_wait(int semaphore); // Corresponds to P operation int semaphore_signal(int semaphore); // Corresponds to V operation void execute_command(int semaphore, char* command); void custom_delay();

int main() { int sem = initialize_semaphore(1); if (sem == -1) { fprintf(stderr, "Failed to initialize semaphore.\n"); return 1; }

execute_command(sem, "clear");
execute_command(sem, "date");
execute_command(sem, "ls");
execute_command(sem, "ps");

printf("FIN\n");

if (remove_semaphore(sem) == -1) {
    fprintf(stderr, "Failed to remove semaphore.\n");
    return 1;
}

return 0;

} // End of main

/**

  • @brief Initializes a semaphore.

  • @param value The initial value of the semaphore.

  • @return The semaphore ID on success, or -1 on failure. / int initialize_semaphore(int value) { int sem_id; union semun { int val; struct semid_ds buf; unsigned short *array; } arg;

    arg.val = value;

    // Create a new semaphore set with one semaphore if ((sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666)) == -1) { perror("Error in semget: Failed to create semaphore"); return -1; }

    // Set the initial value of the semaphore if (semctl(sem_id, 0, SETVAL, arg) == -1) { perror("Error in semctl: Failed to initialize semaphore value"); // Clean up the created semaphore if initialization fails semrm(sem_id); return -1; }

    return sem_id; } // End of initialize_semaphore

/**

  • @brief Performs a semaphore operation.

  • @param semaphore The semaphore ID.

  • @param operation The operation to perform (e.g., +1 for signal, -1 for wait).

  • @return 0 on success, -1 on failure. */ int operate_semaphore(int semaphore, int operation) { struct sembuf sb; sb.sem_num = 0; // Operate on the first semaphore in the set sb.sem_op = operation; sb.sem_flg = IPC_NOWAIT; // Use non-blocking operation

    if (semop(semaphore, &sb, 1) == -1) { perror("Error in semop: Semaphore operation failed"); return -1; } return 0; } // End of operate_semaphore

/**

  • @brief Removes a semaphore.
  • @param semaphore The semaphore ID.
  • @return 1 on success, -1 on failure. */ int remove_semaphore(int semaphore) { if (semctl(semaphore, 0, IPC_RMID) == -1) { perror("Error in semctl: Failed to remove semaphore"); return -1; } return 1; } // End of remove_semaphore

/**

  • @brief Decrements the semaphore value (P operation).
  • @param semaphore The semaphore ID.
  • @return 0 on success, -1 on failure. */ int semaphore_wait(int semaphore) { return operate_semaphore(semaphore, -1); } // End of semaphore_wait

/**

  • @brief Increments the semaphore value (V operation).
  • @param semaphore The semaphore ID.
  • @return 0 on success, -1 on failure. */ int semaphore_signal(int semaphore) { return operate_semaphore(semaphore, 1); } // End of semaphore_signal

/**

  • @brief Executes a system command using fork and system(), synchronizing with a semaphore.

  • @param semaphore The semaphore ID.

  • @param command The command string to execute. / void execute_command(int semaphore, char command) { pid_t child_pid;

    child_pid = fork();

    if (child_pid == -1) { perror("Error in fork: Failed to create child process"); return; }

    if (child_pid == 0) { // Child process if (semaphore_wait(semaphore) == -1) { fprintf(stderr, "Child process failed to wait on semaphore.\n"); exit(EXIT_FAILURE); } system(command); if (semaphore_signal(semaphore) == -1) { fprintf(stderr, "Child process failed to signal semaphore.\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } else { // Parent process if (semaphore_wait(semaphore) == -1) { fprintf(stderr, "Parent process failed to wait on semaphore.\n"); // Continue to wait for child, but log the error } custom_delay(); // Introduce a delay in the parent if (semaphore_signal(semaphore) == -1) { fprintf(stderr, "Parent process failed to signal semaphore.\n"); // Continue to wait for child, but log the error } wait(NULL); // Wait for the child process to terminate } } // End of execute_command

/**

  • @brief Introduces a small delay using gettimeofday. */ void custom_delay() { struct timeval current_time; struct timezone tz; unsigned long start_time, elapsed_time;

    gettimeofday(&current_time, &tz); start_time = current_time.tv_sec * 1000000 + current_time.tv_usec; elapsed_time = start_time;

    while (elapsed_time < start_time + DELAY_MICROSECONDS) { gettimeofday(&current_time, &tz); elapsed_time = current_time.tv_sec * 1000000 + current_time.tv_usec; } } // End of custom_delay

Related entries: