Linux fork() Introduction

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello I'm dr. Brian Frazer and in this video I'm going to show how to use the fork command in Linux so what is the fork command generally it is a way of taking your currently running process and spawning a new process and Linux has a rather unique way of doing this it just duplicates the current process for running so let's walk through and see what we can do with that so the first thing we might want to do is you know print out our process ID just to figure out kind of who we are so we can do that with the get PID command in Linux and so I'm going to do here for example just print it out so printf I am and present D to show it as a dolt as a decimal value it's actually a type def so I'm just going to cast it to an int to make sure it shows and then I can build this and it's going to say there's a problem because I haven't got the includes right yet so I move this up a little this is implicit declaration of get PID so anytime it tells you implicit declaration of something C is telling you you haven't yet included the appropriate header files to under to include the command you're looking for we can figure out what we should have included I can go to a console you can go alt commit ctrl alt T if you're on a normal keyboard and I can do man get pid' see if I can zip me up that's what we wanted it tells us here that we should probably be including sis types and uniess STD so let's do that here so hash include this slash type study CH and hash include and this is going to be uni STD dot H now rebuild that and it builds fine so I can run this from the command line here and that's my fork maybe that's just on-screen enough and so then we see that I'm currently running as ten thousand nine to nine and if I run this again my picture my my pit keeps changing because of course I'm the new process to Linux ok so let's bring in for what's four going to do for us so we're going to call the fork command I can bring up the man page for that now when I just do man Fork it brings up the new a WK extension modules that's not really what I wanted same sort of idea but not I want the programmers reference so I'm going to Amman to fork that'll force it to look in the Linux programmers manual and so here it tells us well it's in uni STD good I've already included that the fork command we're going to pass in no arguments and it returns to us 8p ID type deft which is the process ID so I can say here PID T let's name it type it equals fork so now when I run this not really going to see anything interesting happening what I can do is I can duplicate that line here at the top and I'm now going to make it just show it's not going to like that because I have some warnings turned on so let's put in here printf fork returned present D and I'm going to type this cast this okay so now I'm just going to call fork I'm going to print out whatever it returned and I'm going to print out who I am at the end so let's make that a game alright just clear the screen so it gets so I can call fork now we show off while I start off being 11 Oh 17 fork then says it returned 11 Oh 18 and fork returns zero and then we see that we have an I am 11 oh 17 and on I am 11 Oh 18 so what happened is we went into 4 kissed one of us we came out two of us which is to say that the currently running process got duplicated and this fork function returned twice once in each process and so my parent process came back and it was the value that had this return and my child process came back and the child process came back with the zero and in fact that's how we know where the child process when fork returns 0 so let's put that into some logic here so if the ID equals 0 now we know that we're the chance so printe or child printf I am the child with PID and I can't use the return value from fork because fork is going to tell me at 0 that's how I know I'm the child so I'm going to use int get PID and I'll get rid of this line down here cuz I don't need anymore now if it comes back as a positive value I can do else/if PID is greater than zero I am the parent and if it's less than zero it's an error so often we put that at the front here so I'm going to put at the front here if PID is less than zero and let's put this in here then I'm going to print an error fork failed and you can wake up a man page to figure out why fork will fail it can fail if you're running for example a lot of Forks if you've got a process that's continuously forking new processes you can run out of available processes with certain limits set by your restriction policy on your machine okay so let's get rid of that and now I'm going to move this up here so we can see exactly what fork returned and then it'll tell us kind of who we are so let me build that and then let's run it again so we start off as own ID fork returns a 91 and we therefore know that we are the parent and then we're done the other process comes back for return to zero therefore we know that I am the child and my pid' when I look it up is 91 so that's the very basics on getting that up and running let's do a little bit more here though so one thing that I'd often do is we are going to so we got the error we handle the error so that's all on its own oftentimes inside this child area I'm going to make it execute some code and then I'm just going to call exit so effectively this is all the child is going to exit execute until it hits this exit command this has the nice benefit of we can make everything after this we must be apparent because we've already handled the child and we've already handle the error case so I know I'm the parent and so then I can do whatever the parent should do so we kind of isolate the code for fork to just this section here let me save and run that and we're doing the same things before of course the pits are changing okay so let's demonstrate kind of this concurrency the reason we spawned two processes quite likely is we want some more concurrency in our program so let's make each of our child and our parent do something in the background so I could do for example I could do a sleep command it's sort of a very basics I can sleep for let's say sleep for five seconds printf child exiting and down here we could do some extra work but as it turns out one thing we're always going to are very often going to want to do is wait on our child process to terminate it turns out those good reasons to do this we'll talk about those in a few minutes but let's just put in the command that does that now so I can put weight and I'm going to put weight zero this effect in fact I want my to be weight null little clear this is going to wait until the child process terminates and we'll handle that event here so I am the parent waiting for child child to end and I can put down here parent ending because I'm not done we build that the error let's go to console make and it says implicit declaration of weight well I can do the same trick I did before man weight tells me it's the wrong module so I'm going to do weight - and it tells me that I should probably hash including sis / weight as well so going to put that in here weight dot H there you go we now build so fork and now we're waiting so the child is running the child then says is exiting and then the parent exited so we didn't have that little bit of a wait so what happened is the child began to run it then waited and then finally print out it is closing down the parent was waiting for that to happen and it then closed down as well so that's just a little bit going on in the background let's do some more something a little bit more interesting so let's well actually before I go into that let me just show you if you're not using a make file you can run the I'll show you the actual command to build with a fork so my the function that I must make clean just to get rid of everything so I'm building this fork file so I can use GCC I'm going to build fork dot C I'm going to output fork and for this code I might use a I going to use a for loop that has an embedded variable declaration so I can use STD equals C 99 and for me I always put on all warnings and turn warnings into errors I'll just move that over a smidge and so when I do that it will then build my fork file to us the command I'm running via my make file which is slightly more complicated but easier to use okay so let's now go back and revisit the work that we're doing here what I might want to do is rather than putting a bunch of code for my child actually in my main let's pull that out so I'm going to cult make a function here and call it do work I do some work and I'll get rid of that so let's go up top here and write a do some work function so void do some work no arguments get the right style here so what I'll do is I'm just going to go and through a loop and print out maybe a counter let's do that so I'm going to create a counter so Const int num and let's go through around five times so for int I equals zero I less than times I plus plus now each time through let's sleep and I'm going to sleep a kind of a random amount of time so I'm going to do round and I don't want this to be a huge amount of time so let's do R and say three so therefore so that'll do a sleep between zero and three seconds inclusive so I'm going to sleep and then I get a printf to do this is going to say done pass let's put out the number I looks not bad compile that and then let's run it so child is now running and pass zero FS one two there's three and so forth for when we're done so we can do some work I could do something very interesting doing a lot of processing in the background sleep puts me off the run queue so it's not a busy wait so it's great for putting in timing but you know if I had a lot of processor intensive tasks I could easily do it in this sort of function here this is just a normal function that I simply am calling from my child process or my child via a child process so let's see what's actually going on here I'm going to bring up my other comment line here and we're going to use PS which is going to show me the active processes so I can use PS dash a and list all of the processes that have been launched from this console and if I go back up here and I rerun Fork it'll list here I've got these two four executables now this is named Fork because that's what I named my executable but it'll list whatever it is you're actually running and so we have exactly two of them we really do have two I'll put a sleep here at the very front of my main so after I put I am put asleep for say five seconds rebuild that rerun fork rerun PS we see we only have one wait a second until we see the next output we've now spawned two so I have two of my Forks and then when it's all finished it'll come back together with no Forks because they both terminate very quickly so we can see that they both exist the actual kids are shown here on the left so we were 365 268 as shown here 365 and 368 the pits at Lennox was assigning to us okay so the next thing I want to show is sort of what does it mean to be a separate process so far we kind of have this idea that we're both both pieces of code are executing in the same same area we got the same you know kind of code base running but what does it mean to be separate processes so what I'm in fact going to do is I'm going to make this a global variable I'm gonna make I a global variable so int I equals 0 and in fact what I'll do is I'll even get out of the out of there so so far we're not really expecting any big change because only the client was executing this code I'm going to go and I'm going to make the parent also execute this code now to differentiate the two of them I'm going to make it parent I'm going to pass in an extra argument here to each of my do work functions child and so up here do work is now going to take a char star and this is name done executing that pass 4% s and I'll put in the name here build that we're all good I can show you here the make so what are we trying to show we're trying to show whether or not my two processes share a value each one is going to be editing this global variable named I and so we'll see what they have should happen if for example their sharing the value each one is going to be incrementing it and so will expect to see this number go up quite quickly on the other hand if they're different we'll see each my parent in my child get a full pass through one through five let's try that oops so we got past zero for both the parent and the child all the way down now I did this rend we are actually both running in the same sort of a pseudo-random sequence so maybe what I'll do is after fork just add a little bit of s so I'm going to seed based on the kid I think I want s ran in fact there we go so all I did is I'm just going to make it a bit more random so fork and so now they should wait for different amounts of time yeah we go that looks better so we can see that the parent counted up 0 1 2 3 4 and the child got 0 1 2 3 4 so they're both completely separate values so the global variable that is in each of the processes is completely different we have two separate address spaces that don't interrelate anything I do in one address space does not affect the add that the second address space unless I use special interprocess communication methods ok so that's a little bit of work we're doing here I'm going to go back get rid of that global variable because of course we all know global variables with evil int I equals 0 and we're back to some nice code I'll let the parent and the child both still doing a bit of work there that looked okay to me when you got the wait here now another thing that we can bring in is this whole return value from the child currently my child is returning 1-0 which is a the success this sort of standard value for success but I can return a number of other values here too so if I wanted to pass back or return a value of say 42 how do I get ahold of that inside of my parent process well it comes through this weight command so if I look at man wait man - wait this will tell us somewhere down here ah well their return about here we go so one success it returns the process ID that we're working with so I can say for example which process finished so let's do that kid T child kid so I'll put in here parent knows child present D finished and I will pass in the pit so int pit and childhood so if I run fork again when this all finishes its going to tell me the PID of which child finished because I might have multiple children spawned with different for calls to fork and this will now show me which one of those has finished so I know that it was 620 that finished which was the only child I ever had here now what about the actual return value that I mentioned a moment ago this return this exit 42 coming from the child process well that's what this null is for so what I can do is int status equals zero this is expecting a pointer to an integer so let's give it one so I'll give it the address of status now let's see what it comes back finished with status % D status now we'll just see what that actually comes back as let that run for a second it's going to turn the status isn't going to be quite as simple as you'd think it's not just going to be that 42 it's going to have enough bunch of other information encoded into the same value so it came back with status well ten seven five - that looks a little weird but what we can do is we can use a series of macros to interpret that so what we can do is say int return or say child return value equals and I can use the macro W exit status which I believe possibly stands for weight X's exit status and I can pass in the variable I used here which was status and this will mask off the only the only the portion of this status value that is going to be used for holding the return value which is to say this 42 so let's print that out so return value was percent D and that was child returns data and just to make it format lettering up with some spaces in front so fork when it comes back it's going to show us the return value that it's giving us back there we go the return value is 42 there's a sequence of others a large series of other macros here that you can use to find out was it a success or a failure what terminated it was it a signal and so forth so that's fairly powerful ok so the second to last thing I want to show here is what happens if you don't use a weight statement so this weight statement here so what I'm going to do is I'm going to before I do any work even on the parent I'm going to do a sleep and let's do a sleep 30 so I'm going to sleep for 30 seconds and then I'm going to change this up here to just go through twice make it faster so what's going to happen is the child is going to end relatively quickly it's going to take maybe you know on average kind of 4 to 6 seconds and the parent is not going to have called the weight function yet so it'll be sitting there sleeping and then it'll come through and actually do the weight function and what we're going to do is we're going to use PS a to list all of the processes and see what's going on so let's run that so make fork so I can use PS here and we see that both Forks are listed there as a 74 and 75 still there now the child has just finished so note that the child the 75 is now listed as defunct which means the process has finished but has not yet been waited on so it is waiting to be waited on this is known as a zombie process it has to be kept around because it has that return value that we wanted we couldn't just delete the entire process from the kernels memory space otherwise it would kind of lose that status about telling the parent why it ended in what it ended with so we had to keep it around which is why it's sitting there taking up a bit of memory now of course when I run this it's gone and it's been cleaned up if I add another let's make this down to a sleep 10 if I had another one down here at the end sleep let's make it pretty long just so I can catch it 60 rebuild so around fork or pardon me I can check it go switches to defunct and then as soon as the timeout expires the parent process basically collected it by calling wait and when it called wait it got rid of that defunct listing here so now all we're left with is the parent process running so oh seven so seven was this one and now when that expires of course it'll be removed from the static they're a removal problem II pardon me from the listing of processes okay so that's the the one thing I wanted to show here I want to know switch gears and I'm going to show a separate little program I've got written it's going to show what you can what happens if you call fork repeatedly so this sort of this non-intuitive behavior on fork that you get two returns from the same call so here's a simple program we're going to loop through in this case I'm only going through one and two so a couple times I'm going to call fork print out the pit of the process that we kind of returned into and at the very end I'm going to delay a slight bit and then print out my pit so your first guess if you didn't quite understand what fork was going to do for us do you think well I'm going to print out my own pit twice and then I'm going to print up my own pit a third time let's prevents true let's give it a fork save that build and this is called a fork loop so don't like fork loop so we print out our own pit twice and then we finally printed out a third time okay so it gets a little more interesting when we start calling fork why well we're going to return from this fork two times each time through so wait what just happened well the first time we went through the loop we ended up here returning twice and so we had 74 and 75 for the two processes that returned we then go through the same loop while each came back to the same point we had duplicated sort of the memory space so each one had just finished going through on I equals 1 now each one goes through an I equals 2 so each one calls fork again so I get 4 calls on the second pass so I now have 4 processes returned from this fork 2 multiplied by 2 we got 4 now and then at the very end I come a slight delay and then each one prints out their own pit at the end so here are the 4 that ended so now you can start to thinking well what's going to happen if I switch this to four each time through we double the number of processes we started with 1 so we end up with 2 to the 4th so I can be make and fork loop so go through here now I'm not calling weight on any of them so they're all just kind of gonna die when they do and we can see here that in fact the main one left and we return back to the command line and it printed this out in the middle but if we were to count these we'd see that there are 16 lines here we ended up having 16 processes that ended just by putting my fork in a loop so we want to be very careful about how we do this and a final note on this is a while 1 fork this has a special name let me get rid of that I can comment it all this code up here this is a fork bomb so a fork bomb will simply continuously fork every time through launching another process now I'm not going to run that because I really don't want to try and clean up a fork bomb off my system the the current Linux kernels are going to limit the number of processes it can begin X been in generating but this is going to be set up in that would've run in the loop and so I'd have to go through and kill a bunch of processes okay so that concludes the demo here on Fork what did we talk about well we first learned that fork is a function call that spawns a new process it duplicates the memory space of the current process and it returns twice so you basically come in returning to the parent process and returning into the child process we saw that we could check if it was an error by checking for pit less than 0 if it is 0 we knew that we were the child and otherwise we saw that it was greater than that we must be the parent we saw that we could do some work in each of the child and the parent and how we could work between those and then we really talked about how we could use weight how it would clean up zombie processes and help free some memory from that and we saw that we could sort of get information from the child back to the parent through that return statement yeah well thank you very much for watching
Info
Channel: Brian Fraser
Views: 220,901
Rating: 4.9391737 out of 5
Keywords: Fork, GNU/Linux (Operating System), Software (Industry)
Id: 9seb8hddeK4
Channel Id: undefined
Length: 29min 40sec (1780 seconds)
Published: Thu Jan 29 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.