3, ఏప్రిల్ 2012, మంగళవారం

DEMONSTRATES THE USAGE OF A SEMAPHORE AS A MUTEX THAT SYNCHRONIZES ACCESSES OF MULTIPLE PROCESSES TO A FILE-ADVANCED UNIX PROGRAMMING


/*sem-mutex.c */
#include <stdio.h>     /* standard I/O routines.              */
#include <stdlib.h>      /* rand() and srand() functions        */
#include <unistd.h>    /* fork(), etc.                        */
#include <time.h>      /* nanosleep(), etc.                   */
#include <sys/types.h>   /* various type definitions.           */
#include <sys/ipc.h>     /* general SysV IPC structures         */
#include <sys/sem.h>   /* semaphore functions and structs.    */
#include <sys/wait.h>  /* wait(), etc.                        */

#define NUM_PROCS  5   /* number of processes to launch.      */
#define SEM_ID    250  /* ID for the semaphore.               */
#define FILE_NAME "sem_mutex"  /* name of file to manipulate    */
#define DELAY     400000 /* delay between file updates by one process. */

/*this function updates the contents of the file with the given path name. */
void update_file(int sem_set_id, char* file_path, int number)
{
    /* structure for semaphore operations.   */
    struct sembuf sem_op;
    FILE* file;

    /* wait on the semaphore, unless it's value is non-negative. */
    sem_op.sem_num = 0;
    sem_op.sem_op = -1;   /* <-- Comment 1 */
    sem_op.sem_flg = 0;
    semop(sem_set_id, &sem_op, 1);

    /* Comment 2 we "locked" the semaphore, and are assured exclusive access to file. manipulate the file in some way. for example, write a number into it. */
    file = fopen(file_path, "w");
    if (file) {
        fprintf(file, "%d\n", number);
        printf("%d\n", number);
        fclose(file);
    }

    /* finally, signal the semaphore - increase its value by one. */
    sem_op.sem_num = 0;
    sem_op.sem_op = 1;   /* <-- Comment 3 */
    sem_op.sem_flg = 0;
    semop(sem_set_id, &sem_op, 1);
}
/* this function calls "file_update" several times in a row,  and waiting a little time between each two calls, in order  to allow other processes time to operate. */
void do_child_loop(int sem_set_id, char* file_name)
{
    pid_t pid = getpid();
    int i, j;

    for (i=0; i<3; i++) {
        update_file(sem_set_id, file_name, pid);
        for (j=0; j<400000; j++)
            ;
    }
}

/* finally, the main() function. */
void main()
{
    int sem_set_id;          /* ID of the semaphore set.       */
    union semun sem_val;      /* semaphore value, for semctl(). */
    int child_pid;           /* PID of our child process.      */
    int i;                   /* counter for loop operation.    */
    int rc;                  /* return value of system calls.  */

    /* create a semaphore set with ID 250, with one semaphore in it, with access only to the owner.   */
    sem_set_id = semget(SEM_ID, 1, IPC_CREAT | 0600);
    if (sem_set_id == -1) {
        perror("main: semget");
        exit(1);
    }

    /* intialize the first (and single) semaphore in our set to '1'. */
    sem_val.val = 1;
    rc = semctl(sem_set_id, 0, SETVAL, sem_val);
    if (rc == -1) {
        perror("main: semctl");
        exit(1);
    }

    /* create a set of child processes that will compete on the semaphore */
    for (i=0; i<NUM_PROCS; i++) {
        child_pid = fork();
        switch(child_pid) {
            case -1:
               perror("fork");
               exit(1);
            case 0:  /* we're at child process. */
               do_child_loop(sem_set_id, FILE_NAME);
               exit(0);
            default: /* we're at parent process. */
               break;
        }
    }

    /* wait for all children to finish running */
    for (i=0; i<NUM_PROCS; i++) {
        int child_status;

        wait(&child_status);
    }

    printf("main: we're done\n");
    fflush(stdout);
}

కామెంట్‌లు లేవు:

కామెంట్‌ను పోస్ట్ చేయండి