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 5>
Further Reading
Wiki Semaphore
Dining Philosphers Problem
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
Very Enlightening Post......!!! Thank You Sir....!!
ReplyDeleteShafique Khan