Lab 3 Course: Operating Systems: Thanh Le-Hai Hoang Email: Thanhhoang@hcmut - Edu.vn
Lab 3 Course: Operating Systems: Thanh Le-Hai Hoang Email: Thanhhoang@hcmut - Edu.vn
Lab 3
Course: Operating Systems
Goal: This lab helps student to understand the definition of process, and how an
operating system can manage the execution of a process.
Content In detail, this lab reflects the theory of process into practical exercises. For
example:
• How to retrieve the information of running process? How is PCB table controlled
by OS?
Result After doing this lab, student can distinguish a program and a process. They
can create a program with multiple process and retrieve the information of processes.
1. Introduction
Informally, as mentioned earlier, a process is a program in execution. A process is
more than the program code, which is sometimes known as the text section. It also
includes the current activity, as represented by the value of the program counter and
1
the contents of the processor‘s registers. A process generally also includes the process
stack, which contains temporary data (such as function parameters, return addresses,
and local variables), and a data section, which contains global variables. A process may
also include a heap, which is memory that is dynamically allocated during process run
time.
As a process executes, it changes state. The state of a process is defined in part by the
current activity of that process.
To keep track of processes, the operating system maintains a process table (or list).
Each entry in the process table corresponds to a particular process and contains fields
with information that the kernel needs to know about the process. This entry is called
a Process Control Block (PCB). Some of these fields on a typical Linux/Unix system
PCB are:
• Owner (user identifier). This determines access privileges & signaling privileges
2
• Scheduling parameters
A process is identified by a unique number called the process ID (PID). Some operating
systems (notably UNIX-derived systems) have a notion of a process group. A process
group is just a way to lump related processes together so that related processes can be
signaled. Every process is a member of some process group.
3. Creating a process
The f ork system call clones a process into two processes running the same code. F ork
returns a value of 0 to the child and a value of the process ID number (pid) to the parent.
A value of -1 is returned on failure.
1 #include <s t d i o . h>
2 #include <s t d l i b . h>
3
4 int main( int argc , char ∗∗argv ) {
5 switch ( fork ( ) ) {
6 case 0 :
7 p r i n t f ( " I ␣am␣the␣ c h i l d : ␣pid=%d\n" , getpid ( ) ) ;
8 break ;
9 default :
3
10 p r i n t f ( " I ␣am␣the␣parent : ␣pid=%d\n" , getpid ( ) ) ;
11 break ;
12 case −1:
13 perror ( "Fork␣ f a i l e d " ) ;
14 }
15 return 0 ;
16 }
4
Compile and run the program observing the output of the program and giving
the conclusion about the order of letters “Hello, World!”.
This is because of the independent among porcesses, so that the order of execution is not
guaranteed. It need a mechanisim to suspend the process until its child process finised.
The system call wait() is used in this case. The example of wait() is presented in
appendix A.
In case of expanding the result to implement the reverse order which child process is
suspended until its father process is finished. This case is not recommended due to the
orphan process status. An example of such programs is presented in appendix B
$ g c c −o l o o p _ p r o c e s s l o o p _ p r o c e s s . c
$ ./ loop_process
Time : 0
Time : 1
Time : 2
Time : 3
Time : 4
...
5
7279 t c grep loop_process
6
b75e1000−b76f8000 r−xp 00000000 00:01 646 /lib/libc −2.17.so
b76f8000−b76fa000 r−xp 00116000 00:01 646 /lib/libc −2.17.so
b76fa000−b76fb000 rwxp 00118000 00:01 646 /lib/libc −2.17.so
b76fb000−b76fe000 rwxp 00000000 00:00 0
b7705000−b7707000 rwxp 00000000 00:00 0
b7707000−b7708000 r−xp 00000000 00:00 0 [vdso]
b7708000−b7720000 r−xp 00000000 00:01 648 /lib/ld−2.17.so
b7720000−b7721000 r−xp 00017000 00:01 648 /lib/ld−2.17.so
b7721000−b7722000 rwxp 00018000 00:01 648 /lib/ld−2.17.so
bf9a8000−bf9c9000 rw−p 00000000 00:00 0 [ stack ]
Comparing with the program (executable binary file) using ldd to read executable
binary file and readelf to list libraries that are used.
$ ldd loop_process
linux−gate . so .1 (0xb77dc000)
l i b c . so .6 => / l i b / l i b c . so .6 (0xb76b6000)
/ l i b /ld−linux . so .2 (0xb77dd000)
Following that, we can see the consistency of code segment between program and process.
6. Exercise
6.1. Questions
1. What the output will be at LINE A?
#i n c l u d e <s y s / t y p e s . h>
#i n c l u d e < s t d i o . h>
#i n c l u d e <u n i s t d . h>
int value = 5;
i n t main ( )
{
pid t pid ;
7
pid = f o r k ( ) ;
i f ( p i d == 0 ) { /∗ c h i l d p r o c e s s ∗/
v a l u e += 1 5 ;
return 0 ;
}
e l s e i f ( p i d > 0 ) { /∗ p a r e n t p r o c e s s ∗/
wait (NULL ) ;
p r i n t f ( "PARENT: ␣ v a l u e ␣=␣%d" , v a l u e ) ; /∗ LINE A ∗/
return 0 ;
}
}
2. When a process creates a new process using the fork() operation, which of the
following states is shared between the parent process and the child process?
A. Stack
B. Heap
C. Shared memory segments
After executing the program, we must see the following lines on the screen (in any order)
3
2
8
then we could display their relationship by a tree in figure 6.1. B is a child process of
A. A is the parent of both B and C.
A B C
Write a program that uses f ork system calls to create processes whose relationship is
similar to the one showed in Figure 6.2. Note: If a process has multiple children then
its children must be created from left to right. For example, process A must creates B
first then create C and finally D.
B C D
E F G
Submission The source code for problem 1 and 2 must be written in two single files
named "ex1.c" and "ex2.c, respectively. Those file are placed in a directory whose name
is your MSSV. Before submitting your work, please compress this directory in ZIP format
(has .zip extension) and name the compression file by your MSSV. You must submit the
ZIP file to Sakai.
9
A. System Call wait()
This example uses system call to guarantee the order of running processes.
1 #include < s t d l i b . h>
2 #include <s t d i o . h>
3 #include <u n i s t d . h> /∗ d e f i n e s f o r k ( ) , and pid_t . ∗/
4
5 int main ( int argc , char ∗∗ argv ) {
6
7 pid_t c h i l d _ p i d ;
8
9 /∗ l e t s f o r k o f f a c h i l d p r o c e s s . . . ∗/
10 child_pid = fork ( ) ;
11
12 /∗ c h e c k what t h e f o r k ( ) c a l l a c t u a l l y d i d ∗/
13 i f ( c h i l d _ p i d == −1) {
14 perror (" fork " ) ;
15 exit (1);
16 }
17
18 i f ( c h i l d _ p i d == 0 ) {
19 /∗ f o r k ( ) s u c c e e d e d , we ’ r e i n s i d e t h e c h i l d p r o c e s s ∗/
20 p r i n t f ( " Hello , ␣" ) ;
21 f f l u s h ( stdout ) ;
22 }
23 else {
24 /∗ f o r k ( ) s u c c e e d e d , we ’ r e i n s i d e t h e p a r e n t p r o c e s s ∗/
25 wait(NULL); /∗ w a i t t h e c h i l d
26 e x i t ∗/
27 p r i n t f ( "World ! \ n" ) ;
28 f f l u s h ( stdout ) ;
29 }
30
31 return 0 ;
32 }
10
B. Signal
This example illustrate the using of IPC signal() and kill() routines to suspend child
process until its parent process is finished.
1 #include < s t d l i b . h>
2 #include <s t d i o . h>
3 #include <u n i s t d . h> /∗ d e f i n e s f o r k ( ) , and pid_t . ∗/
4
5 int main ( int argc , char ∗∗ argv ) {
6
7 pid_t c h i l d _ p i d ;
8 s i g s e t _ t mask , oldmask ;
9
10 /∗ l e t s f o r k o f f a c h i l d p r o c e s s . . . ∗/
11 child_pid = fork ( ) ;
12
13 /∗ c h e c k what t h e f o r k ( ) c a l l a c t u a l l y d i d ∗/
14 i f ( c h i l d _ p i d == −1) {
15 p e r r o r ( " f o r k " ) ; /∗ p r i n t a system−d e f i n e d e r r o r
16 message ∗/
17 exit (1);
18 }
19
20 i f ( c h i l d _ p i d == 0 ) {
21 /∗ f o r k ( ) s u c c e e d e d , we ’ r e i n s i d e t h e c h i l d p r o c e s s ∗/
22 s i g n a l ( SIGUSR1 , p a r e n t d o n e ) ; /∗ s e t up a s i g n a l ∗/
23 /∗ S e t up t h e mask o f s i g n a l s t o t e m p o r a r i l y b l o c k . ∗/
24 s i g e m p t y s e t (&mask ) ;
25 s i g a d d s e t (&mask , SIGUSR1 ) ;
26
27 /∗ Wait f o r a s i g n a l t o a r r i v e . ∗/
28 s i g p r o c m a s k (SIG_BLOCK, &mask , &oldmask ) ;
29 while ( ! u s r _ i n t e r r u p t )
30 s i g s u s p e n d (&oldmask ) ;
31 s i g p r o c m a s k (SIG_UNBLOCK, &mask , NULL ) ;
32
33
34 p r i n t f ( "World ! \ n" ) ;
35 f f l u s h ( stdout ) ;
36 }
37 else {
38 /∗ f o r k ( ) s u c c e e d e d , we ’ r e i n s i d e t h e p a r e n t p r o c e s s ∗/
39 p r i n t f ( " Hello , ␣" ) ;
11
40 f f l u s h ( stdout ) ;
41 k i l l ( c h i l d _ p i d , SIGUSR1 ) ;
42 w a i t (NULL ) ;
43 }
44
45 return 0 ;
46 }
12