 All right. Welcome to the people who were notified about the room change. So yeah, this is like a snow day. So this will be good. So we can really explore things now and take questions, because it's not that many of us. So process management. We were talking about parents and children and that relationship. And today is how to maintain that and lots of fun stuff. But first, let's finish that example from last lecture with execvee. So we saw how to create a process. That was through fork, where you have an exact clone of the current running process. And then the only difference is the return value from fork. That's the only way to differentiate them. So the way to execute a different program and start running it is with the execvee system call. So there is a C function wrapper for it. So it'll do the system call for you. But yeah, it's essentially a one-to-one. So there's just an execvee function. First argument it takes is a path that is the entire directory to get to a program. That will be an l file, like we saw before, because we are on Linux. And then it takes some arguments. So the first argument it takes is argv. So you can think of it as this is what you get from main. If you have argc and argv, well, the way that gets populated is from an execvee system call. So your shell would have taken what you typed and converted it into this format. This format, it is an array of char stars. So it's an array of c strings. And the idea behind that is it's just supposed to end in null. So it's a null-terminated array of null-terminated character strings. So lots of fun. And then the other argument is environment variables called env. They're basically like global variables for processes. But we won't really get into them that much. Just they're passed as another argument. For our purposes, there are some wrappers. So execvee is like the actual system call. But there's a few C wrappers that will take care of passing environment variables and stuff for you. So you don't have to deal with it. But for this case, I'll just say it is null. Now, how execvee works that if it is successful, it will replace this process, load that new program, and start executing it instead. So if execvee is successful, this current process is no longer running this program. It is going to be running another program. In this case, it's going to be running ls. So that is one possibility. The other possibility is that it fails. If it fails and you read the documentation, it will return negative 1. So if it fails and returns negative 1, it would go into this if branch. Part of the spec of reading it is that it would also set this global variable called error-no. I save it here so I can keep track of the first error that happened. Because this pError function, if you read the documentation for it too, it also uses error-no. So there might be an error in printing as well. So I just want to save the first error that happens. This will take the current error-no and try and give you some more readable output with what the error actually is. And then it would return so this process will no longer exist. It will exit because returning from main is the same as just calling exit. So in that case, this line will never execute in either case. So either it will, execvee will be successful. This process will become ls. Or it will go in the error case. There is no case that this print f line will work. So if I go ahead and execute that, I see that I get my first print message. I'm going to become another process. And then I get the output of ls. So any questions about that? Yep. Yeah, so you might have noticed that even if you know, you strace, let's go way back because lecture two, I think. So even when we straced our little hello world example, the first line I told you to ignore from before was that line. But that's how the process started. So I didn't call that. But now we can kind of guess that our shell probably called it because our shell would have had to create a new process. It would have had to fork. And then it would have execveed. And that call is, yeah, from my shell. All right, any other questions about execvee? So we can kind of tell what our shell does now. It would have forked execveed. Anyone notice something a bit weird here too? Why is ls there twice? Yeah, well, this is the actual program to run. And then so for those of you that hopefully everyone that have written a main with argc and argv, does anyone want to tell me what the first argv always is? Or does anyone remember what it always is? Yeah, yeah, so argc is the number of arguments you have. And then argv is the list of the arguments. But specifically, what is argv at index 0, like the first thing? Yeah, yeah, so one guess is the path to the executable. But the answer to that is no. It's, well, in this case, it would be this. So ls would see this as arg0. You might see it as a path. Anyone else use it before and know what it says typically? So typically, it is just the name of whatever you type to run this process, which might not correspond with what the file is. So for instance, I could do that. So if I do this, so I can go ahead, do this. So I change the first argument. Still works. No problem, yep. Yeah, that's a good guess. So one guess is that, hey, is it an alias to run that program? So in this case, I don't have an alias called WTF. But there is a convention that that is supposed to represent what you type to run the program. So if it was an alias, your shell would set that to the alias. And it's meant to represent how you actually executed the program. Yeah. Yeah, so the question is, if I look at this in proc, will the name show up as whatever you have there? I believe so. So there's a few ways it gets names. So there's one way to set name. And then another way is that it looks at r0, in which case it would be this. So I think the default name would be this. But there's also a different name that's slightly different that's based off the path. So you might think this is a bit silly, but this is sometimes useful. For instance, there is just one executable that does CPLS and everything. And it just changes its behavior based off what this argument is. And so it actually reads arg0 and actually does something different to it. Again, typically I said this is a convention. So where it typically gets used is for help messages. So if I do something like this and look for the help message for ls, I see usage ls and then da, da, da, da, da. If I wanted to execute the same thing using execve, I could pass the argument here. And then I have a question. What does essentially this line do? This line just defines an array of characters supposed to represent the environment. I'm not going to define anything. So it's just a null terminated array. So if I just put a null pointer there, it means it's just size 0. So I'm not going to pass any arguments. So in this case, I will go ahead and do help. And then if I do execve this time, whoops. Wait, why did it say it wouldn't save? Overwrite, I don't care. So in this case, if I scroll up to the top and see its usage, it will actually follow the convention. Let's see. So there. So it uses that name there. Is this the name of ls? Not really. It's whatever I told it, I launched it as. So I could just set that to whatever I want. And one of the vulnerabilities is typically that's just a convention that's always set as the name of the program. Well, one day, so people have used sudo to access, become the root user to do something. And lo and behold, it assumed that you had arguments and someone did something like this to do sudo and just didn't pass anything. And sudo tries to access argument 0 without checking that there's at least one element. And that led to bad things where you could become root because you took over sudo because they didn't check the length of the argument. They just assumed it was always true. So that is a fun topic. My screen died. Cool. All right, so let us blast through some of the content because we're going to get into more fun, gruesome names. Oh, yep. Yeah, so the question, if you don't have an argc, you can't pass anything from the terminal. And yeah, so your terminal, whenever you type things into it, it will populate that arg, varray, and argc. And argc is just the number of arguments. So it could be 0 if you want it. So yeah, so it's a bit different. So this is like a go back. So the arguments for this is like a null terminated array of characters. For main, your argv is a bit different. It doesn't have a null pointer at the end. And the way it tells you how many elements there are is by argc. So it's a bit of a different format. But this will get translated into it by all the system calls and stuff like that. Yeah, so it gets translated. All right, so we saw that process state diagram before with the weighting state, which was also called ready, and the running state and blocked. So the Linux terminology is slightly different. The real technical details is it gets a little bit muddy. But in general, it kind of looks like this. You might have poked around in the PROC file system already for lab one. So in that, one of the things is called state. And it doesn't quite line up with our generic states we saw in the last lecture. And again, PROC, every directory there, that's a number. That's a processed ID or a PID. There's also a special one called self, which represents whatever process is currently accessing it, which is done by a bit of magic. But if you go off, read the states, you'll see something like this. There is a running and runnable state, which in our state diagram more or less corresponds to running and weighting slash ready. So Linux doesn't really differentiate between the two. And then it has two block states instead of one. So there is one block state called interruptable sleep, which we'll get into a bit more in the next lecture, which basically just means that that process could be woken up and it could do something, but it actually is waiting for something else to happen. And D, uninterruptable sleep, means that even if you poke and prod it, it can't execute no matter what. It's waiting for some network or something like that. So you can't wake it up whatsoever. And yeah, so you can tell going for the chat question, your shell would, whatever you type something to run, your shell would translate what you type, split it off into argv and then call execve for you. And that's how it runs your program. So now if you really want, you know how to write a shell. So your shell just takes some input, forks splits that input into strings, breaks it up into different string sections, and then calls execve to run that new program. You might notice two more states here that look a bit weird. So there is a stop state. So you can explicitly tell a process to stop executing and it will no longer be able to execute. We'll see how to do that later. And you might see this weird state called a zombie. That is a term the Linux kernel uses. And we will figure out how to create zombies today. It will be very exciting. So let's, there's another question of like, okay, if fork is the only way to create processes, how do you ever create the first process? So the Linux kernel as part of its process of starting, as soon as the kernel initializes all the hardware and everything, it launches one program and one program only and creates a single process. This process is special. It is called init. And by default it is in slash espin slash init. And it has the responsibility of launching every single other process on your machine. So every process on your machine, no matter what will be launched by init or a child of init and it could go on as deep as you want. But the ultimate grandparent or ancestor to every single process running on your machine is going to be init and it is special because it has process ID one. And what makes it really special is that, well, that's the only thing the kernel launches when it starts. And if init dies, well, guess what? Your machine is dead. That means you no longer want to run anything and the kernel will just stop running. All your processes will die. Your entire thing will just die. So if it's dead, the kernel just thinks you're shutting down so it'll just shut down your system. So there's lots of different things init could be. On Linux on your systems and your VMs it's something called system D. Some people get into religious wars over it but there's other options, the default one system D. For us it doesn't really matter. You could even write your own init if you really, really, really wanted. We'll see what an implementation of one is. One simple one would be okay. My init can just launch a shell and then I have one shell forever and that's the whole job of init. And then my shell can launch other stuff. So that could be a very, very, a very crude estimation of what init does. Some offering systems might also have an idle process that the scheduler can run to represent your CPU being idle. So you might see that on Windows. Yep, oh yeah. Yeah, the question is oh, well if init dies that means your computer's shutting down so that can that be used maliciously? The answer to that is it could way back in the day but nowadays it's protected. It will check access if you can actually kill it. If you can, you can probably also just type the shutdown command and just shut down the machine. So it's the same thing. So it wouldn't power off but your kernel would be like, okay, we're done here. Yeah, it would probably just get frozen. We'll figure out how to send things. You'll probably tell me to kill init and yeah. Yep, yeah. So when you first turn on, so for instance your VM, so because we're talking about Linux, after the kernel initializes all your hardware it will launch one user process and it will be process ID one and after that your kernel is like, you take care of it from here, I'm done. Yeah, so here we can see. So I have a slide for that. So here's like what a typical process tree looks like. So there is a child parent relationship between all of them. At the very top you'll see init. So init part of the things if you will see how to look around but it would launch something like these. These are system demons so they're just doing some background work for system stuff. Then eventually you would log into your machine so that would be a new process. So there is a user specific system D which is supposed to manage all the processes for your individual user you log in as. So this would be what it looks like after you've already logged in. So after you log in you get system D for your user. Then for your VM if you installed a desktop environment and you've logged into it you would also see a GNOME shell. This process represents your actual desktop environment what you see. And then through that you might go and click Firefox or something like that. Well guess what? That launches a process and that process would be Firefox. It would be a child of that GNOME shell that represents your desktop environment. And then Firefox or Chrome, every browser each of your tabs will be in its own process. So in this case it looks like I would have three tabs open and why would it do something like that? Well remember tabs are nice and independent and isolated from each other. So way back in the day Firefox did everything in a single process and if say you dereference the null pointer or something like that, that process dies your whole browser goes down, that's not good. So that's why they re-architected it so that each tab is a new process. So if something horrific happens to one of them it doesn't bring down your browser it just brings down an individual tab. Yeah, that means you have to power cycle it again and then it just restarts and then everything goes back. Like what you guys made me do when you fork-bomb me. All right, so yeah other things that it could look like. So I might launch a terminal and that would be its own process. Now a terminal that's responsible for taking what you type in on your keyboard translating it to bytes and doing the translating it to essentially standard in and then taking whatever bytes it reads from standard out and converting them to characters and drawing them so you can actually see them. And then as part of you interacting with it that terminal would launch a shell and that is what it looks like you're typing into that launches other processes. So our shell would be ZSH. In this case I'm running an application called Htop which I will now explain. So if you want to see this process tree you can run Htop. It's a nice little process manager which is going to be far more complicated than the one you're doing in lab one. And one of the other additional features it has is you can see the entire process tree. So if I go here and type Htop and look it will draw me a process tree. So at the top I see init process ID one and I can see all of its direct children. Then I can see this process also has a child. I could scroll down and see that there's a lot of processes running on the machine. Here I can see some SSH thing that has to do with me and that is running ZSH which is then running bash which is not what I'm currently doing. So that's kind of weird. There's a whole bunch of other processes that you are not expected to know what they do but eventually we can see, hey here's our good friend VS code server. So I can see that this represents the terminal I'm currently looking at. It is running ZSH and I am currently running Htop. So I can see that Htop is a child of ZSH which is a child of my terminal which is a child of some other stuff in VS code because VS code likes running processes. So you can go through, see the parent-child relationship for literally everything. All right, so with that, we will get into some gruesome fun. Oh yeah, and two before. So remember processes get assigned a process ID when they're created and it does not change as long as that process exists. It's just a number and it's unique for every active process and any kind of dying process that we'll see in a second. On most Linux systems, the PID goes up to 32,000. On Mac it's a bit different. I believe that limit is actually higher now on most systems on your VM. It's a configurable thing. So I think on your VM it's actually higher than that. Eventually you might see that the process IDs kind of go sequentially but they don't necessarily have to. It's just the way their algorithm works. Theoretically it could do whatever but computers just like doing things incrementally. So most of the time they'll be in sequential order. So whenever a process is completely dead and the kernel can recycle its process control block and process ID, another process can go ahead and take over that process ID. And also remember, think in this course, that each process has its own address space or independent view of memory and that's just another way of saying that each process has its own virtual memory. So you might hear the term address space. Yeah, so that's a question. Can I not have more processes running than the maximum PID and the answer that is, yeah, no. Because if you run out of numbers you can't assign anything to a new one and then your fork call would probably fail. And also like one of the defenses against the fork bomb if you try and run it on the ECF machines is they'll limit the number of processes you can create to something low, probably like 10. And then artificially you just can't create any processes. You won't get assigned any process IDs or anything like that. Yeah, so if you do exec VE, it just replaces the process and its process ID stays the same. So no matter if exec VE succeeded or failed doesn't matter, the process ID stays the same until it eventually calls exit. So yeah, it will stay the same. Yep, so yeah, this would be a limit of the number of Chrome tabs you were drawing but after 30,000 Chrome tabs you're probably just gonna run out of memory straight up instead of process IDs. So if that was like, if you were limited by the number of process IDs it's configurable so they would just say, okay, we'll just increase it until you run out of memory. So typically this would not be the limiting factor. Yep, yeah, that's a question. Does PID correspond to the memory that's actually accessible? And no, it's just a number. The refer to that process ID is nothing to do with anything special about it except for process ID one. That's the only thing that's any special whatsoever. And that's just the first thing that the kernel launches. Aside from that, they're just numbers. But yeah, it doesn't correspond to anything. Okay, so now we have to maintain parent-child relationships. So previously I kind of cheated a little bit and neglected to tell you things because I had that little sleep in my parent to make things easier. So I didn't have to explain this part but now we have to argue what happens when children and parents die in unintended orders. So for instance, what happens if my parent process exits first and no longer exists? So my process, which is a parent, has a child process and then I finish before my child. So in other words, the parent dies before the child. What happens to the child? It exists still, that's good, yeah. There's another, you could abort the process, the child. This child already exists so it's like, it's past that point. So this child's already running, it's, you know, it's however old you guys are. Yeah, so the colonel knows which one dies, right? So someone knows and if the parent's dead, well what happens to the child? Does, there has to be a parent-child relationship yet? Yeah, another parent can take over, is that what you're gonna say? It's an orphan, that's actually the correct answer. Well they're both correct, so there's an orphan but that orphan needs someone to take care of it. So you can tell, this is the actual terminology by the way, I do not write letters, I did not make this up, da, da, da, da, da. Like this is the actual terminology. So that is true, so first we have to talk about, well why would it even need to be responsible? So remember when you exit a process, well you call exit and you return a number and that number's supposed to indicate what happened to that process. So zero if it was successful and an error number anyways. So whatever a process exits or terminates, you can't actually reuse its process ID yet because someone needs to read its exit status to see what actually happened to it. So even though a process terminates, it still needs a process control block. So it might not be able to ever run again but it has a process control block that stays around and one of the things that would be in it is something like its exit status. So the rule is that if a process exits, someone has to acknowledge it in order for its process ID to get recycled in order to completely clean up the resources and completely delete it. Otherwise you might get in the situation like you might think, well why don't I just, I have a child, I know it's process ID, why don't I just pull it over and over again to see if it's still alive? Well that doesn't quite work because what happens if my child has a process ID of 60 or something like that, I look to see if it's alive, it's alive and then before I recheck process ID 60 again, my child could exit and then if it was immediately cleaned up, well then the kernel could reuse process ID 60 for some completely unrelated process that is not my child and then I would read it again and be like, oh my child's still alive when really that process is completely unrelated to me. So that is why there's this acknowledgement step because that's the only way the offering system knows that you're completely done with the process, you acknowledge that this is actually your child, it is now exited and terminated, you saw what happened to it, now I can clean it up. So with that, there is two situations. So either you can have a child process and then it terminates first and what is that called? That's called a zombie process. Again, technical term, we saw it at the beginning and that is what it is. So a zombie process, why is it called a zombie? Because it's a process that's not quite alive, it's terminated, it can't execute anymore, it can't run, it can't do anything, but it's not quite dead because it has a process control block still. Someone needs to read its exit code, it's still consuming some type of resources so it's not completely alive, it's not completely dead. Zombie is a perfect word to describe it. So that just means it's still around, it's consuming some resources and we need to do something about it. And the other one is like we said before, the parent exits first, in which case we have an orphan process, that child is now parentless. So the system call to actually acknowledge something is called wait, it has the following API, it takes an address to an int and then as part of this system call, it will block by default until the first of your children has terminated and it would acknowledge them and then fill in that status with a bunch of information that you can query to see what actually happened to that child, how did it get terminated and what are things about it. So wait will return a few things, will return a few things, so it will return negative one if it fails, like all the functions will pretty much see. It will return zero, which is an invalid PID because by default it will actually wait for a child to die, but if you don't want to wait and you want to just pull it and see, hey, do I have a child that's dead? Well, then there's an option to make it just query it and not wait around and not block. So that will return zero in the case that we acknowledged it, we will get the process ID of the child that has terminated. So that wait status contains a bunch of information, we'll just look at the example, you have to use macros to kind of query it and you'll have to read the man page for wait to figure out what you have to do with it. So if we go look at our wait example here, let's move this to do. So in this case, if I run it, oops, sorry, I will move this down. So I have main, it forks immediately, so it creates the child process and we still have our parent process. Here, the child would get process ID zero. So in the child, I sleep for two seconds, it just goes to sleep for two seconds. In the parent, I print f that I'm calling wait, I create a local variable called w status, which is an int, which I will give it the address of and then it will write a number to there that you shouldn't look at directly, you have to access some macros, but eventually wait will return whenever my child has exited. So the child should exit after two seconds, it would come out of, it wouldn't go in the else branch, it would return zero, which would exit the child. So the child should exit after two seconds. And here, I call wait and then when wait returns my child has exited. So this hopefully will happen after two seconds and I will get the process ID of my child, which is now dead. And I can check, if you read the documentation, you can ask the w status it fills in, w if exited, so that will return true if the process exited normally. In our case, we'll just assume it can always exit normally for now and the next lecture we'll see other ways the process can exit. But if you read the documentation, if this is true, then you can read the exit status through this macro and it will tell you the number it returned. So if we go ahead and run this, we should see calling wait, it'll wait two seconds for the child to die and then it will say wait return for an exit process gives us the process ID, which since it called wait and acknowledged it, this process ID now no longer exists because it can get cleaned up because it was acknowledged and the status that we read. So any questions about that? Yep. If wait returns zero? Oh yeah, so this is a child process here. It just goes to sleep for two seconds. Yeah, so the parent waits until the child exits. Yeah, so in this case, because the child takes two seconds to exit, wait won't return until the child's dead. Yep, yeah, so wait will return. If I had multiple children, wait by default returns whenever the first one exits. So if I launch a bunch of processes, I don't know which one's gonna terminate first. The kernel will wake this up with whatever terminated first. Yeah, so that's a good question. If I have multiple children, well, if you're a good responsible parent, you need to acknowledge your child. So if I had two, if I create two children, I need two waits. Yeah, they would each return the process ID of the child, right? And then you can query it. Yep, yeah, so that process ID is now, the kernel can reuse it for whatever it wants. Yep, yeah, and that was for the child process. And yeah, so in this case, wait won't return zero because that's like the non-blocking wait. You can, if you read the documentation for wait, you can just have wait, not wait until the first child to die and it can just be like return me the process ID of my terminated child if there is one, if there isn't return zero. So that's an option you can have. Okay, yep. Oh, yeah, so that's a good question. So what happens if the child calls wait here? Something like that. So without running it, because I think I have to go quick. So wait will return error code if you don't have any children because the kernel will be, the kernel knows all those relationships. So if you just call wait without a child, it'd be like, what the hell are you doing? You don't have a child. So that would, I would get the same thing if I also called wait again here. So I create one child, I wait once, now I don't have any children. And if I wait again, it's gonna be like, hey, you idiot, you don't have any children, you can't wait. Yeah. Yeah, so the wait, it's a system call. So they'll do that. And the kernel takes care of it. But you're responsible for calling it. Right, so that's part of being a good parent for your operating system. So there's the wait, so yeah, what's the zombie process? So it's waiting, a zombie process again, that child is gone and it is waiting for its parent to read its exit status. So there's a few things that happen. So whenever your process, your child process exits, we'll see how it does this in the next lecture, but the kernel will poke you and say, hey, while your children has terminated, you need to acknowledge it and you're free to ignore that. You can be a neglectful parent if you want. So no one tells you, like the kernel prods you that you should call wait, but you don't have to. So yeah, and that is basically a form of an interrupt. So the kernel will generate an interrupt to your process and say, hey, while your children terminated, you should probably acknowledge it. And because it's an interrupt that you write, you can be like, yeah, no, I'm good. I don't need to. So yeah, in which case the operating system has to keep that process control block around. And that's where it gets into that zombie state that I talked about earlier, where it's neither alive nor dead, yep. Yeah, so that's the question. So you said in practice, when you don't know how many children you have, is that an accurate statement? So waiting, you can only wait on your direct children. So why you say direct is because, well, you're the only one that can create processes so you know how many you make, right? But still the user is interacting with your code. Your code's still making the processes. So yeah, if you lose track of the number of children you have, like in real life, that's probably not good, right? So yeah, if you have children and you need to keep track of your direct children and say you were the one giving birth to the child, you'd probably know how many you had, right? So yeah, that would not be a great case, yep. Yeah, so that's a question, the example from yesterday was I created a zombie process and the answer to that was yes. But they just kind of waste resources so it's not a good thing but my code was not great. So let's look at a zombie process, so zombie. So here's an example of a zombie process. So I'll do the same thing, I will fork again, let's assume it's successful, the child's gonna do the same thing where it just sleeps for two seconds and then it terminates. Now in the parent, I will go ahead and sleep for only one second and then I'll get woken up so I should be woken up while the child still has two seconds left before it terminates and I will print off the child state and then I wrote this little helper function that just accesses the proc file system and prints off the state that it finds in the status file. So I'll read the state, check for any error codes, hopefully I can program and I don't get any errors but always good to check. Then the parent's gonna sleep for an additional two seconds so it's gonna wake up from this after three total seconds have elapsed so my child will now have exited but I didn't call wait or anything and then I will read the child's process state. So if I read that you should see that the term zombie is a real thing. So first time it's sleeping so that makes sense, it's still alive and then after another two seconds it's now in a zombie state which the kernel keeps track of, right? It's not some word I made up, it's literally called a zombie state. So it's process ID is still valid but it can't execute or anything and it can't get completely cleaned up it's wasting resources. So if you just launched infinite processes and they were all zombies then eventually you're gonna run out of process IDs or memory depending on how big the process control block is. Yep. I checked my child's state, yeah, with its process ID. Yep. So here the child sleeps for two seconds and then exits and then in the parent I sleep for one second and then I read it state and then I sleep for an additional two seconds so three seconds so the child should have exited by then and then I see it's a zombie, yep. Yeah, so that is the next thing we'll do. So the question was basically what happens if the other thing happens where the parent exits first and not the child? Well, that's an orphan process and it needs a new parent. So yeah, the child process lost its parent process. The kernel is really strict about maintaining that parent-child relationship. The child doesn't die, it's like real life just because a parent doesn't exist anymore doesn't mean you die. So the child needs a new parent. It is called an orphan and it still needs something to acknowledge it. By default the operating system is going to re-parent an orphan process to that special process init which again is process ID one. So we might have seen it before. Whenever I ran it I saw like the child's parent ID was one. Well, that was the rare case in that code where the parent exited first and it was an orphan process and it got re-parented to a init. So you can also think of init as the orphanage if you want, that is a good term for it. That is nicer than the real term, yep. Yeah, so by default whenever, like if there's a grandchild or something like that, the kernel only cares about direct relationships. So if you are an orphan process you just get re-parented to a init. There is an exception to that though and the exception is you can designate a process as being special to essentially become an orphanage and you will accept any grandchildren that die and they'll get re-parented to you instead of a init and that often is called being a sub-reaper. So a nice gruesome name and actually the technical name orphanage was a nice name for a init. Its technical name is the reaper, like the grim reaper. So yeah, so init, technically it's called a reaper and now we know kind of the other part that would be in init. So a init would just, a well-written init would launch some processes and then whenever it's done launching processes at the end of it it would be like, while true, wait and then it would clean up any orphans it gets. So here is the orphan example. Let's do this really quick. So in the orphan example, we'll fork again and in the child we'll see whatever its parent is immediately we'll sleep for two seconds and then we'll check what our parent is again and this time in the parent process we will only sleep for a second. So we will not last that long and we can see that we have an ID and then we see that the child's parent ID after the sleep is one, so it got reparented to init. All right, any questions about that? Yep, yeah, so that's a good question. If a zombie's parent dies does it become an orphan? So yeah, that child process could be a zombie because the parent process just never acknowledged it and then at that point it would become a zombie orphan process and then it would get reparented to init and then init would acknowledge it and then it would get cleaned up. Yep, yep, yep, yep, yep, yep, yep. Yeah, so the kernel will reparent it to init automatically that's just part of what the kernel does and then it would be init's responsibility to call wait. So because wait waits for the first process to die if you just had while true wait then you would acknowledge them as soon as they come in. As soon as they exit you acknowledge them you just do it over and over again. So the simplest init you could write would be like launch some process and then while true wait to clean up everything. Yep, no, so here the parent process just sleeps for a second and then it exits and returning from main is the same as exiting and exiting will terminate a process. Yep, so the question is if I am a process and my parent dies then yeah, then it would get reparented to init but your child is still your child it would still think it wouldn't get reparented to init because you're still alive. Yeah, so you only get reparented when your direct parent gets terminated. Yep, yeah if you wanna think of it that way but the kernel doesn't really care about grandchildren or anything it's just parent child. So it's like wherein this is the parent child so like here, oops, yeah, so this would be just a bunch of parent child relationships here. In init is the direct parent of journal D, system D, user and Udev or whatever and that's all the kernel cares about and the kernel just cares about this relationship and if for some reason you break this, like if this process dies before this one starts running this just gets reparented all the way to init. Like if this one dies? This? Yeah. Yeah, so if no shell dies then Firefox would get reparent, then just this process would get reparented to init. So the other ones would stay so this would just get reparented to init and all these processes, their parent's still alive because it's just this one, so nothing changes. Yeah, for them nothing changes just the direct parent changes. All right, I guess we're over time so just remember, pulling for ya. We're all.