Wednesday, October 2, 2013

Inter Process Communication : Part I

If there is one chapter in Design of Unix Operating System (Maurice Bach) you should read then it would be the chapter on IPC.

First time I taught this paper, I hardly understood it well ... second time around I did the coding myself and found some of the topics very interesting. Third time around you realise the clarity in the previous year was quite disconcerting :-)

Ummmm and do I expect students to understand it in first go .. well not really ... but then students are smarter than teachers !!!

I had studied the Dining Philosphers Problem and Locking Problems like "dirty read". I had used applications like OS, Databases, Compilers and Debuggers. I had worked 6 years in Unix Enviorment ....... but alas my concepts were still a bit weak. That is why teaching is such a good thing ... you learn in the process even if the students don't :-)

Some cool things Unix can do :

fork : A process can clone itself !! A ditto copy .... if recursion was difficult to teach then this in a league in itself.

Coding is easy : a=fork(); if (a==0) {// child code} else {// parent code}

but Understanding is another matter ..... what happens in this code
      for(i=0;i<5 a="=0)" ello="" else="" i="" if="" p="" printf="">
       What is the output you expect? How many Hi and Hello and in what order ?

exec: A process is overwritten by an exe in other words "memory is overlayed!!". In the following example first a fork is called (the current process is cloned) .... and then memory is overlayed in the child (using exec) !!

Lets say this app is called forkapp.exe then if we did ps command on another terminal

when code was going to run line 7: you will see two forkapp.exe due to cloning

but after line 7 : you will see 1 forkapp.exe and 1 date due to overlaying

      6    if(fork() == 0)
      7    {    execl("/bin/date","date",0);
      8         printf("Execl failed");
      9         return;
     10    }
           When will line 8 be executed? Why don't we check the return value of execl
        You have seen recursion, where a function calls a function .. what happens here .. any idea

        execl(argv[0],argv[0],0);

semaphore:
      The difficult thing in locking is that we can write a code like

      if (lock_flg==false)
      {      lock_flg=true
            // code to use some resource
       }
      but to implement locking in a multiple process system the risk is that a process p1 after calling the if line and before it calls the assignment line the kernel may give a chance to somebody else (process p2)

     This other process p2 also happens to be executing the same code and he may also check the flag and then set the flag not knowing that process p1 has already intending to lock the same resource.

    Very soon chaos will result with both process using the same resource without realizing that somebody else is also using the same resource (say a printer !!)

      
     Djikstra came up with a clean solution called semaphore (read on wiki)

      semget : create or get an existing semaphore
      semctl : to control semaphore, you can SETALL GETALL IPC_RMID etc
      semop : To increment or decrement a semaphore

We can create an array of semaphore or just a single one and that is a very cool thing because not only we solve Locking problem we also solve the dreadful "deadlock" problem. How Exactly .... you tell me ?
     
 Following Code is the menu:

     22    while (ch!=0)
     23    {
     24       printf("\n 1. Create Semaphore if does not exist");
     25       printf("\n 2. Set All to 1         ");
     26       printf("\n 3. Get All ");
     27       printf("\n 4. P Operation / Decrement / Lock");
     28       printf("\n 5. V Operation / Increment / Unlock");
     29       printf("\n 6. Clean Up");
     30       printf("\n 0. Exit ");
     31       printf("\n\t-----------------------");
     32       scanf("%d",&ch);


      We will create semaphore using semget

     34    if(ch == 1)
     35    {
     36       semid=semget(0X22,2,IPC_CREAT|0777);     37
     38       printf("\n\t Sem Id is %d",semid);
     39       printf("\n setting semaphore");
     40    }

        Here we are creating an array of 2 semaphore

     To set values in the semaphore we use semctl 
     41    if(ch == 2)
     42    {
     43       rval=semctl(semid, 2 , SETALL, r);     44
     45       printf("\n semaphore val is %d %d rval is %d",r[0],r[1],rval);
     46       printf("\n set semaphore");
     47    }
        Q: What is r ?
          To get the values of semaphore we again use semctl
     48    if(ch == 3) // check what is status
     49    {
     50       semid=semget(0X22,2,0777);
     51       printf("\n getting semaphore");
     52       rval=semctl(semid, 2 , GETALL, o);
   
53       printf("\n semaphore val is %d %d rval is %d",o[0],o[1],rval);
     54    }

        Q: What is o ?

         To lock we use semop with op set as -1 (line 61)
     55    if(ch == 4) // try to take lock
     56    {
     57       semid=semget(0X22,2,0777);
     58       printf("\n\t If part Sem Id is %d",semid);
     59       printf("\n Process Before Semaphore %d ... Trying to get lock",semid);
     60       sop.sem_num=0; // set the first semaphore
     61       sop.sem_op=-1; // lock
     62       sop.sem_flg=SEM_UNDO;
     63       a = semop(semid , &sop , 1);
     64
     65       printf("\n Process semop %d ",a);
     66       printf("\n Process in critical section");
     67       printf("\n Process Locked ");
     68     }

         To unlock we use semop again but this time we set op to 1
     69    if(ch == 5) // Unlock
     70    {
     71       semid=semget(0X22,2,0777);
     72       sop.sem_num=0; // set the first semaphore
     73       sop.sem_op=1; // unlock
     74       sop.sem_flg=SEM_UNDO;
     75       a = semop(semid , &sop , 1);
     76
     77       printf("\n Process Over is %d ",a);
     78       getchar();
     79    }

          To remove we use semctl again
     80    if(ch == 6) // clean Up
     81    {
     82       semid=semget(0X22,2,0777);
     83       printf("\n getting semaphore");
     84       rval=semctl(semid, 2 , IPC_RMID, 0);
     85    }
     Check the man pages of your installation but you would need to include some header files like the following
       2 #include
      3 #include 
 

      And would also need to declare a few things like
     10    short r[2];
     11    short o[2];
     12    struct sembuf sop;

 
Hope you find the blog useful. All the best ....
      
 In part II I will touch on Message Queues and ptrace


Further Reading

Wiki Semaphore
Dining Philosphers Problem
 

1 comment:

  1. Very Enlightening Post......!!! Thank You Sir....!!
    Shafique Khan

    ReplyDelete