Featured Post

Trie implementation in C

IPC Semaphores implementation in C

Here is a simple example to show how the IPC semaphores work.
In this example two processes (parent and child) are communicating between each other using semaphores.

Each process access the same track thrice based on which process gets the access.
Once the process gets the access of the track it sleeps for 5 seconds (in this section user can do some useful work instead of sleeping !) and after that it releases the track using sem_op function.

Instead of communicating between the parent and child process we can have two different processes running on the same machine also.

#include <stdio.h>
//ipcsemaphore.c
//To compile : gcc -o sem ipcsemaphore.c
//To run : ./sem
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

void die(char *msg)
{
  perror(msg);
  exit(1);
}

int main()
{
    int i,j;
    int pid;
    int semid; /* semid of semaphore set */
    key_t key ; /* key to pass to semget() */
    int semflg = IPC_CREAT | 0666; /* semflg to pass to semget() */
    int nsems = 1; /* nsems to pass to semget() */
    int nsops; /* number of operations to do */
    struct sembuf *sops = (struct sembuf *) malloc(2*sizeof(struct sembuf));
    /* ptr to operations to perform */

    /* generate key */
    if ((key = ftok("ipcsemaphore.c", 'Q')) == -1) 
       die("ftok");
    
    /* set up semaphore */

    printf("\nsemget: Setting up semaphore: semget(%#lx, %\
                    %#o)\n",key, nsems, semflg);
    if ((semid = semget(key, nsems, semflg)) == -1)
        die("semget: semget failed");


    if ((pid = fork()) < 0)
        die("fork");

    if (pid == 0)
    {
        /* child */
        i = 0;


        while (i  < 3)  /* allow for 3 semaphore sets */
        {

            nsops = 2;

            /* wait for semaphore to reach zero */

            sops[0].sem_num = 0; /* We only use one track */
            sops[0].sem_op = 0; /* wait for semaphore flag to become zero */
            sops[0].sem_flg = SEM_UNDO; /* take off semaphore asynchronous  */


            sops[1].sem_num = 0;
            sops[1].sem_op = 1; /* increment semaphore -- take control of track */
            sops[1].sem_flg = SEM_UNDO | IPC_NOWAIT; /* take off semaphore */

            /* Recap the call to be made. */

            printf("\nsemop:Child  Calling semop(%d, &sops, %d) with:", semid, nsops);
            for (j = 0; j < nsops; j++)
            {
                 printf("\n\tsops[%d].sem_num = %d, ", j, sops[j].sem_num);
                 printf("sem_op = %d, ", sops[j].sem_op);
                 printf("sem_flg = %#o\n", sops[j].sem_flg);
            }

            /* Make the semop() call and report the results. */
            if ((j = semop(semid, sops, nsops)) == -1)
            {
                perror("semop: semop failed");
            }
            else
            {
                printf("\n\nChild Process Taking Control of Track: %d/3 times\n", i+1);
                sleep(5); /* DO Nothing for 5 seconds */

                nsops = 1;

                /* wait for semaphore to reach zero */
                sops[0].sem_num = 0;
                sops[0].sem_op = -1; /* Give UP COntrol of track */
                sops[0].sem_flg = SEM_UNDO | IPC_NOWAIT; /* take off semaphore, asynchronous  */


                if ((j = semop(semid, sops, nsops)) == -1)
                {
                    perror("semop: semop failed");
                }
                else
                     printf("Child Process Giving up Control of Track: %d/3 times\n", i+1);
                sleep(5); /* halt process to allow parent to catch semaphore change first */
            }
            ++i;
        }

    }
    else /* parent */
    {
        i = 0;

        while (i  < 3)   /* allow for 3 semaphore sets */
        {

            nsops = 2;

            /* wait for semaphore to reach zero */
            sops[0].sem_num = 0;
            sops[0].sem_op = 0; /* wait for semaphore flag to become zero */
            sops[0].sem_flg = SEM_UNDO; /* take off semaphore asynchronous  */


            sops[1].sem_num = 0;
            sops[1].sem_op = 1; /* increment semaphore -- take control of track */
            sops[1].sem_flg = SEM_UNDO | IPC_NOWAIT; /* take off semaphore */

            /* Recap the call to be made. */

             printf("\nsemop:Parent Calling semop(%d, &sops, %d) with:", semid, nsops);
            for (j = 0; j < nsops; j++)
            {
                printf("\n\tsops[%d].sem_num = %d, ", j, sops[j].sem_num);
                printf("sem_op = %d, ", sops[j].sem_op);
                printf("sem_flg = %#o\n", sops[j].sem_flg);
            }

            /* Make the semop() call and report the results. */
            if ((j = semop(semid, sops, nsops)) == -1)
            {
                perror("semop: semop failed");
            }
            else
            {
                printf("Parent Process Taking Control of Track: %d/3 times\n", i+1);
                sleep(5); /* Sleep for 5 seconds */

                nsops = 1;

                /* wait for semaphore to reach zero */
                sops[0].sem_num = 0;
                sops[0].sem_op = -1; /* Give UP Control of track */
                sops[0].sem_flg = SEM_UNDO | IPC_NOWAIT; /* take off semaphore, asynchronous  */

                if ((j = semop(semid, sops, nsops)) == -1)
                {
                    perror("semop: semop failed");
                }
                else
                    printf("Parent Process Giving up Control of Track: %d/3 times\n", i+1);
                sleep(5); /* halt process to allow child to catch semaphore change first */
            }
            ++i;

        }

    }
}


References : http://www.cs.cf.ac.uk

Comments

  1. thanks for program. but i can't understand why u had written semun union without using in the program

    ReplyDelete
    Replies
    1. It's not needed. Thanks for pointing out. However, if semctl function is used, this is used to be passed as 4th argument.

      int semctl(int semid, int semnum, int cmd, union semun arg);

      In that case, we have to define it explicitly.

      Delete
    2. I have removed the part as well.

      Delete
  2. Can you write code without including the library include
    #include
    #include
    Rather define in this progrM only

    ReplyDelete

Post a Comment

Please post your valuable suggestions