1
00:00:00,294 --> 00:00:06,207
[MUSIC]. 

2
00:00:06,207 --> 00:00:09,735
Now that we know how, what a process is 
and how to create processes, let's see 

3
00:00:09,735 --> 00:00:13,192
how we do interesting things with 
processes. 

4
00:00:13,192 --> 00:00:16,900
We're going to be talking about this 
fork-exec model. 

5
00:00:16,900 --> 00:00:21,322
And as we saw before, fork creates a copy 
of the current process, the process that 

6
00:00:21,322 --> 00:00:25,414
called fork and execve what's going to 
do, is going to replace the current 

7
00:00:25,414 --> 00:00:31,850
process code and address space with a 
code for a different program. 

8
00:00:31,850 --> 00:00:34,408
okay? 
In fact there's a whole family of exec 

9
00:00:34,408 --> 00:00:38,144
calls I encourage you to explore them, 
'kay. 

10
00:00:38,144 --> 00:00:43,604
So for example here, in this, in this 
code we are calling fork so if the PID is 

11
00:00:43,604 --> 00:00:49,950
not zero, that's the parents they created 
a child, okay. 

12
00:00:49,950 --> 00:00:53,890
And otherwise if the PID is 0, that's the 
child, okay. 

13
00:00:53,890 --> 00:00:59,738
And when we coexecve the figure the child 
is going to replace its codes and its, 

14
00:00:59,738 --> 00:01:05,586
its data in its address space with the 
codes and addresses from a different 

15
00:01:05,586 --> 00:01:10,705
Program. 
And this line here is going to be printed 

16
00:01:10,705 --> 00:01:12,680
by the parent only. 
And we'll see. 

17
00:01:12,680 --> 00:01:15,620
And, and that's, that's because execv is 
now going to return. 

18
00:01:17,350 --> 00:01:20,770
So let's, let's see an animation, of how 
this happens. 

19
00:01:20,770 --> 00:01:22,674
Okay? 
So this, this is the parent process right 

20
00:01:22,674 --> 00:01:25,050
here. 
Parent process, okay? 

21
00:01:26,430 --> 00:01:31,960
So, and, when you say that's, that's, 
that's the bash process right the shell 

22
00:01:31,960 --> 00:01:37,840
that you might be probobaly running in 
your system, okay. 

23
00:01:37,840 --> 00:01:42,659
When you type alas for example, what its 
going to do is bash is going to fork 

24
00:01:42,659 --> 00:01:49,595
because it needs to create a new process 
to execute the command alas. 

25
00:01:49,595 --> 00:01:53,354
Okay and here's how its going to happen. 
So bash calls fork, okay. 

26
00:01:53,354 --> 00:01:57,434
So that's the parent, that's the original 
process here and now its going to create 

27
00:01:57,434 --> 00:02:01,340
a child, that at that point is exactly 
the same. 

28
00:02:01,340 --> 00:02:05,780
These two are the same but now what it 
needs to do, it needs to call exec and 

29
00:02:05,780 --> 00:02:10,590
replace what was there in the child with 
the stack, the, the address space, and 

30
00:02:10,590 --> 00:02:17,258
the codes for the program LS it's 
going to list a directory. 

31
00:02:17,258 --> 00:02:20,375
Okay? 
So that's a high level view, okay? 

32
00:02:20,375 --> 00:02:25,407
So the bash which is process happens to 
be the shell when you type LS, it's going 

33
00:02:25,407 --> 00:02:30,569
to create a new process. 
And it's going to replace the child 

34
00:02:30,569 --> 00:02:36,692
process with the code and address space 
for ls, because ls is, is just a program. 

35
00:02:36,692 --> 00:02:41,764
Okay? 
Okay, so now here is how execve works, in 

36
00:02:41,764 --> 00:02:46,545
more detail. 
That's the prototype of the function, 

37
00:02:46,545 --> 00:02:50,976
'kay, recieves three parameters. 
'Kay, one is a filename, it's a filename 

38
00:02:50,976 --> 00:02:56,694
of the executable containing the program 
that we want to, to exec. 

39
00:02:56,694 --> 00:03:01,530
Then the argument that were going to pass 
to, to, to the program in this MPSD 

40
00:03:01,530 --> 00:03:06,678
environment that the lift of environemt 
varibales things like for example the 

41
00:03:06,678 --> 00:03:13,755
current directory and so on. 
Now note that execve does not return, why 

42
00:03:13,755 --> 00:03:16,264
is that? 
Well, because it's going to be executing 

43
00:03:16,264 --> 00:03:19,060
a different program now. 
And the execve call was part of the 

44
00:03:19,060 --> 00:03:23,560
original program that was it's, it's part 
of the program was running that, that was 

45
00:03:23,560 --> 00:03:27,674
running before execve. 
So as soon as you do execve, that current 

46
00:03:27,674 --> 00:03:30,270
program is no longer running, that's why 
it doesn't return. 

47
00:03:30,270 --> 00:03:32,285
Unless there's an error, then it's going 
to return. 

48
00:03:32,285 --> 00:03:35,360
Okay. 
And as I said before it overrides the 

49
00:03:35,360 --> 00:03:40,050
code, the data, and the stack, okay. 
It keeps the, the process ID open files 

50
00:03:40,050 --> 00:03:42,540
and a few other files. 
Okay. 

51
00:03:42,540 --> 00:03:50,800
Now, let's see how this collection of 
data structures here look like in memory. 

52
00:03:50,800 --> 00:03:53,510
Okay, so, that's, that's a stack frame 
for main. 

53
00:03:53,510 --> 00:03:58,130
Now we have what, we have D argument 
count, the, vector of arguments. 

54
00:03:58,130 --> 00:04:03,230
Okay, that's five points to a list of, it 
points to a vector. 

55
00:04:03,230 --> 00:04:07,760
And it each intuit is vector is a 
pointer. 

56
00:04:07,760 --> 00:04:10,917
To the strings of the command line 
arguments. 

57
00:04:10,917 --> 00:04:15,168
Okay. 
Now the environment NP points to a, 

58
00:04:15,168 --> 00:04:19,608
another vector. 
It's a list of pointers to the contents 

59
00:04:19,608 --> 00:04:24,100
of the environment variables, so it's a 
pretty beefy data structure. 

60
00:04:24,100 --> 00:04:28,835
Okay. 
alright, so this is how exit field works. 

61
00:04:28,835 --> 00:04:32,960
And now how do we end the process? 
We're going to use a call called exit. 

62
00:04:34,230 --> 00:04:38,591
And we use a parameter a status of why 
the process exits. 

63
00:04:38,591 --> 00:04:43,147
So, status code zero is normally used for 
normal exits and non zero is abnormal 

64
00:04:43,147 --> 00:04:46,899
exit like, you know, there was an 
exception or there was something, 

65
00:04:46,899 --> 00:04:53,590
something happened to the process. 
Okay? 

66
00:04:53,590 --> 00:04:57,088
So, and if you, if you want to register 
functions to be executed when you exit 

67
00:04:57,088 --> 00:05:02,250
the process, you can call at exit, it's 
something to be executed at exit. 

68
00:05:02,250 --> 00:05:06,330
For example, say that you call cleanup 
here. 

69
00:05:06,330 --> 00:05:10,050
So if you say atexit cleanup, when, when 
the process here exits, it's going to 

70
00:05:10,050 --> 00:05:13,753
call this function cleanup here. 
Okay? 

71
00:05:13,753 --> 00:05:20,050
So, but once this happens it doesn't 
really completely destroy the process. 

72
00:05:20,050 --> 00:05:23,570
It creates what we call a zombie, zombie 
process. 

73
00:05:23,570 --> 00:05:26,570
Okay, so and the reason we call it a 
zombie is because when the process 

74
00:05:26,570 --> 00:05:31,055
terminates. 
It still consumes resources. 

75
00:05:31,055 --> 00:05:33,360
Okay. 
So things like, many tables in the OS 

76
00:05:33,360 --> 00:05:38,266
keep track of processes, and so on. 
We call it zombie because kind of like a 

77
00:05:38,266 --> 00:05:43,121
living corpse half alive and half dead. 
But what happens if they build up, well 

78
00:05:43,121 --> 00:05:48,269
there's a process called reaping that 
cleans up after a dead process and its 

79
00:05:48,269 --> 00:05:55,020
performed by the parent process on a 
terminated child. 

80
00:05:55,020 --> 00:05:59,794
OK, so when a parent process creates a 
child process, and the child process 

81
00:05:59,794 --> 00:06:04,799
exits, dies, the parent is given it's 
exit status information and with the 

82
00:06:04,799 --> 00:06:10,790
reaping process tell the kernels to 
discard. 

83
00:06:10,790 --> 00:06:15,433
Whatever was left from the process and 
recycle those, those resources mm-hm. 

84
00:06:15,433 --> 00:06:19,337
Now what if a parent doesn't reap? 
Well, that could be a problem if the 

85
00:06:19,337 --> 00:06:24,812
parent runs for a long time. 
But if any parent terminates without 

86
00:06:24,812 --> 00:06:31,640
reaping, then the child will be reaped by 
init process, by the init process. 

87
00:06:31,640 --> 00:06:34,695
By the way the init process is a process 
that is a parent of all processes in your 

88
00:06:34,695 --> 00:06:37,740
system. 
'Kay, when your operating system boots, 

89
00:06:37,740 --> 00:06:41,260
and is ready to execute something it 
increases an init processes it's sort of 

90
00:06:41,260 --> 00:06:46,470
like the canonical process from which all 
other processes arrive, kay. 

91
00:06:46,470 --> 00:06:49,938
So if a parent terminates without reaping 
a child, then the child will be reaped by 

92
00:06:49,938 --> 00:06:53,215
the init process. 
Okay, but one thing to note is that if 

93
00:06:53,215 --> 00:06:56,887
you have a long running process you need 
to do explicit reaping otherwise nobodies 

94
00:06:56,887 --> 00:07:00,151
going to reaping and it's going to be 
using resource and it's eventually it's 

95
00:07:00,151 --> 00:07:05,712
going to exhaust it's resources. 
An example of long live processes that 

96
00:07:05,712 --> 00:07:10,084
need to do reaping are things like shells 
and servers and so on, okay. 

97
00:07:10,084 --> 00:07:14,572
Alright, so now that we know what happens 
when the process dies, let's see how we 

98
00:07:14,572 --> 00:07:19,509
use that for synchronization. 
There's this function called "wait" 

99
00:07:19,509 --> 00:07:22,315
that's used to synchronize with children 
processes. 

100
00:07:22,315 --> 00:07:24,586
'Kay? 
So, what it does is, when you call wait, 

101
00:07:24,586 --> 00:07:28,426
it suspends the current process, for 
example the parent, until one of its 

102
00:07:28,426 --> 00:07:33,236
children terminates, okay. 
And the return value is the PID of the 

103
00:07:33,236 --> 00:07:37,376
child process that terminated because a 
parent could have multiple child that its 

104
00:07:37,376 --> 00:07:41,604
waiting to die on. 
And on successful return the, the child 

105
00:07:41,604 --> 00:07:46,276
process is then reaped, okay? 
And by the way, if the child's status is 

106
00:07:46,276 --> 00:07:51,339
set to, this is a parameter to, to the 
wait function if it's set to not know, 

107
00:07:51,339 --> 00:07:56,817
then the, the integer that it points to, 
because note that's an integer pointer 

108
00:07:56,817 --> 00:08:02,046
and that it points to will be set to a 
status indicating why the child process 

109
00:08:02,046 --> 00:08:08,930
terminated. 
Okay? 

110
00:08:08,930 --> 00:08:13,580
So because now we can read the exit 
status of the process. 

111
00:08:13,580 --> 00:08:15,750
This int return here just returns the 
pid. 

112
00:08:15,750 --> 00:08:17,610
That's the pid. 
'Kay. 

113
00:08:17,610 --> 00:08:21,335
And this points to the status at exit 
that the child had. 

114
00:08:21,335 --> 00:08:25,302
'Kay. 
So and are there are special macros for 

115
00:08:25,302 --> 00:08:29,532
this to interpret this status. 
And you can see wait two[INAUDIBLE] , 

116
00:08:29,532 --> 00:08:35,428
wait two and, and see what those mean. 
So, now note that if apparent processes 

117
00:08:35,428 --> 00:08:40,048
multiple children, if you call wait, it 
will return the, when any of the children 

118
00:08:40,048 --> 00:08:45,504
terminates, that's why there's another 
call called waitpid. 

119
00:08:45,504 --> 00:08:50,679
And here's what it does, you can wait on 
a specific child process by passing it's 

120
00:08:50,679 --> 00:08:53,861
PID as a parameter. 
Okay? 

121
00:08:53,861 --> 00:08:59,014
So, let's an example of wait here. 
So, we have this function called fork 

122
00:08:59,014 --> 00:09:01,220
wait. 
It forks here. 

123
00:09:01,220 --> 00:09:04,700
If it's zero, again it's the child. 
It says hello from child. 

124
00:09:04,700 --> 00:09:09,457
Otherwise that's the parent, that's and 
it's going to do the following, the child 

125
00:09:09,457 --> 00:09:15,236
pid is going to wait on the, on child 
status, just an integer here. 

126
00:09:15,236 --> 00:09:18,340
Okay? 
And when, when that returns it's because 

127
00:09:18,340 --> 00:09:22,447
the child has died. 
So, now when, when that happens we're 

128
00:09:22,447 --> 00:09:27,625
going to print the pid of the child, note 
that this returned by weight. 

129
00:09:27,625 --> 00:09:33,420
Okay, and it's going to say it has 
terminated, okay, and then it's goign to 

130
00:09:33,420 --> 00:09:36,920
say bye. 
So let's see how this works here. 

131
00:09:36,920 --> 00:09:38,729
There you have it, originally the process 
was running, then it forks, okay, then 

132
00:09:38,729 --> 00:09:45,256
eventually the child is going to say bye. 
Whenever the says bye its because he has 

133
00:09:45,256 --> 00:09:57,014
returned, therefore we come back here, 
and then the parent calls bye. 

134
00:09:57,014 --> 00:10:00,860
Pretty interesting, right? 
Super simple and effective, you can 

135
00:10:00,860 --> 00:10:04,604
imagine very complicated trees and what, 
arrangements of how, of how, parents and 

136
00:10:04,604 --> 00:10:10,177
childs, synchronize. 
So to, to summarize, recall that fork 

137
00:10:10,177 --> 00:10:15,570
gets two copies of the same process. 
Okay? 

138
00:10:15,570 --> 00:10:18,540
But it, but fork returns different values 
to the two process. 

139
00:10:18,540 --> 00:10:21,548
In fork is a special function. 
You call once, but return twice, because 

140
00:10:21,548 --> 00:10:24,854
that's the point where it replicates the 
process, okay? 

141
00:10:24,854 --> 00:10:30,090
So execve has a new process, replaces 
itself with one, with the one that called 

142
00:10:30,090 --> 00:10:34,700
it, okay? 
So it's a two process program, okay? 

143
00:10:34,700 --> 00:10:39,055
So when you you call fork, so heres an 
example of a two process you first call 

144
00:10:39,055 --> 00:10:45,507
fork and if the pid is zero thats a child 
code otherwise exit the parent code. 

145
00:10:45,507 --> 00:10:49,599
And that's where you'd use in the child 
code thats where you call exactly to 

146
00:10:49,599 --> 00:10:55,466
replace itself with a new program. 
Okay, so now at that point you have two 

147
00:10:55,466 --> 00:11:00,215
completely two completely different 
programs. 

148
00:11:00,215 --> 00:11:03,230
'Kay? 
Great. 

149
00:11:03,230 --> 00:11:07,902
So, inwait and waitpid is used to 
synchronize parent and child execution 

150
00:11:07,902 --> 00:11:12,574
and whenever you do this execution 
process, the child the like remains of 

151
00:11:12,574 --> 00:11:19,260
the child process is collected when it 
exits, okay. 

152
00:11:19,260 --> 00:11:23,745
So in the final sumary of this section we 
are now ending our section processes so 

153
00:11:23,745 --> 00:11:27,580
that keeping in mind that at any given 
time the system has a lot of active 

154
00:11:27,580 --> 00:11:31,805
processes in fact if you type in Linux PS 
for example minus ZF to, to, to make it, 

155
00:11:31,805 --> 00:11:39,380
to make it return here. 
To make it easy to read. 

156
00:11:39,380 --> 00:11:41,810
When you type that you're going to see 
the list of all processes running. 

157
00:11:41,810 --> 00:11:45,779
Okay, that's, that's your prompt here you 
type ps minus ef you're going to get a 

158
00:11:45,779 --> 00:11:49,108
list. 
But if you have a single CPU only one can 

159
00:11:49,108 --> 00:11:53,401
execute at a time. 
And the process has the illusion that it 

160
00:11:53,401 --> 00:11:56,500
has full control of the CPU. 
That's pretty cool right? 

161
00:11:56,500 --> 00:11:59,495
It's a really important abstraction 
Alright, okay. 

162
00:11:59,495 --> 00:12:02,897
And from time to time the OS has to do 
the context switch because there's a 

163
00:12:02,897 --> 00:12:08,310
single CPU, you want to give the illusion 
that things are running at the same time. 

164
00:12:08,310 --> 00:12:12,471
So, it keeps bouncing back and forth 
between, between the running processes. 

165
00:12:12,471 --> 00:12:14,846
Okay? 
So, and we do process management with 

166
00:12:14,846 --> 00:12:18,770
this fork-exec model that you just 
learned. 

167
00:12:18,770 --> 00:12:21,250
That concludes the section, see you soon. 

