 All right, we got all right welcome back to whoa, that's not working welcome back to operating systems. Oh, that's like we all right, so Review I'm here for you. I will not continue that thought because it sounds really weird. So What we want to know Questions concerns comments take up random questions that the other sections asked context switching. Oh you you context stuff. Don't worry about it For the midterm, don't worry about it. I'll save you hours and hours of time Yeah, I wrote the midterm as far as I know I have a bad short-term memory So I kind of forget I wrote it like a week ago or something like that But as far as I know, there's no you context anything. Yeah, so threads are technically fair game I As far as my memory is concerned, I definitely did not write a big question on thread So it's definitely in the short question part. I don't think it's fairly major. So take with that what you will So we can all right So I have a virtual memory question primed up. Do we want to do virtual memory? Everyone loves virtual memory. All right. That's everyone's favorite so You might not have seen this but it's been on my website the whole time So in the three five three final, you know, that's also valid So you can look through that and see if there's questions that are Covered that you can have covered. So on that final, there's a virtual memory question so we can do that because everyone loves virtual memory virtual memory is Everyone's favorite topic so This is a really weird system that has a 12-bit virtual address 8-bit physical address and a page size of 16 bytes So whatever I see page sizes and bytes, I like writing them in powers of two quick What's 16 and powers of two? Four 16. All right quicker than any other section you guys win. So that's to the four Page table entry size is one byte. Well, I mean if I have to multiply or divide by one That's pretty easy. If I really want I can write to the power of zero seems kind of irrelevant But in case you really want to So questions also says it describes what is in the page table entry and what the layout is So you might notice that while each hex character represents four bits and I was nice to you Because I don't have you writing binary for this question because you can leave everything in hex so a page table entry will be one byte or eight bits and the top Hex character is going to be the physical page number and then the other four bits are all going to be the permissions So after describing that silly system, I give you a dump of virtual memory So remember virtual memory is byte addressable. So two hex characters is exactly a byte So this is the byte at address zero byte at address one two three four five six seven eight nine that the dot the dot the dot the dot and If you want to find any byte at any address Well, if I wanted to figure out what the byte was that address. I don't know two four. Well, that would be Two zero plus four. So the byte at address Two four is three f So any questions about how to read this virtual memory or this this is physical memory How to read this at all. So this is just added at each address. What is the byte? Okay, so we're good All right for first question How many bytes do we need if we just have a single large page table for the silly system and Remember the silly system has a 12-bit virtual address a eight-bit physical address and then a 16 or to the four page size so if I have a Single large page table. How much memory do I need to store that thing? So another way of asking this is like, oh, well How in the system? How many virtual pages do I have to translate? To the power of eight everyone agree with that? No, that's right. So However many virtual pages we have well that is just Two to the twelve. That's how many bytes are in virtual memory in total If you need to figure out how many virtual pages there are Used to buy by the page size, which in this case is just two to the four So this is to the eight so I need to keep track of mapping Two to the eight virtual page numbers to physical page numbers if I just had a single large page table So I need to the eight entries and I need one of those. Oh, yep Yeah, we got lucky then All right. So yeah, this is where it came from has nothing to do with the 8-bit physical address So we have to the eight virtual page numbers if we have a Gigantic page table. So for each of these we need a page table entry How big is our page table entry? One byte so Multiplying to the eight by one. It's pretty easy. So it's just to the eight. So that got us there so any questions about that so it would need two hundred and fifty six Bites if I want to be super explicit about it. So single page tables no fun For the remaining questions, you must use multi-level page tables assume each page tables fits on a physical page or frame which again is 16 bytes so If we need to figure out how many Levels we need to use remember our good old equation that you probably want to write down on your cheat sheet It's the number of levels we need is a ceiling of virtual bits Minus offset Bits Divided by the index bits So in this case, we already know virtual bits and offset bits. They are 12 and 4 how many index bits do I need? Which is again the same thing as asking well, I need to I need to be able to Address every single Entry that I can put on a page. How many page table entries can I fit on a page in this silly system? To the power four right so my page size is To the power of four Divided by my page table entry size Which is just to the power of zero or one or whatever so it just ends up being the same thing So I can fit 16 entries on every byte on every page. Yeah Yeah, so problem statement. This says our page table entry is One byte that's the important part and our page size is 16 bytes Yeah, so the offset bits correspond it's where you are within a page So it's log two of the page size So in this case offset bits is four because our page size is 16 bytes All right, so any questions about that? hopefully okay, so We figured out our index bits is thankfully four so 12 minus four is eight divided by four Well, that's a nice number. It's just exactly two so It's ceiling of two which is equal to two so we need two levels Make sense kind of so Next question is when things get more fun So we're going to do a full translation. So we're given the virtual address one two three in hex and Told that our highest level page table is currently at Physical page two which I will put in green so If we go back to here What might be easier to visualize is to take this memory and just divided into Physical pages so each physical page is 16 bytes. So let's draw this So above that blue line that those are 16 bytes And this would be represent physical page number Zero so those are the first 16 bytes and then the next 16 bytes Would be ppn One and let's get rid of this stuff. This would be ppn to this would be ppn Oh three Right any questions about just dividing it up in the pages so page size of 16 bytes One two three four five six seven eight is in a row. I got two rows per so I have 16 all right So now if we're doing the translation It says that our highest level page table is at Physical page number two. So if I go back to here, that means it is right here So this is our highest level of page table If I only have two levels, what level is this is this L3? L1 so this is L1 so L1 is The entire L1 is in green there So now if we are translating virtual address one two three Well, we already know that Three that's our offset. Which one of these hex numbers is our L0 index? two so This is our L0 index and this is our L1 index So yeah, so when you have multi-level page tables If you divide it out no matter what it looks like it always will be offset then L0 index and L1 index and How big these are depends on while the offset depends on the page size? And then the indexes depend on how many entries you can actually fit on a page So in this case luckily our offset well that's four bits because of our page size and also because while each page table entry is one byte and They fit on a page. Well There's four bits here four bits here and nicely that corresponds to the hex characters Yeah, so it's same system or page size doesn't change Yes. Yeah, so L1 L0 are all calculated from you know, it starts with this So we're using multi-level page tables given the system. How many levels do we need? from that we need to figure out the number of index bits and That corresponds to how many bits per index? so so in this case, they don't have to be the same because remember for like The addresses we use well, it's like nine Nine nine and the offset is 12 because our page table size entry is like eight Bytes so it's much bigger in this. It's only one byte. So they're all the same so in that case we can check off Let's use green. So we got that got that got that So any questions about just getting all those so we just read them off what what the offset is what all the indexes are So we're all good All right, at least some not and we got signs of life. So Next one says for this virtual address say whether What the value of the final page table entry is or the value of the page table entry that causes the fault is So we're going to have to use again this number. So this is the physical page number where the L one page table is so Using that and the indexes we get from our virtual address We can actually figure out where in physical memory this virtual address is supposed to map to so We're supposed to use index one in L In our L one page table. So what bite does that correspond to or what physical or what page table entry? Does that correspond to? Yeah, 0x1f so In the green that is the full L One page table it has 16 entries and because our virtual address is One two three or L one index is one. So we look at the entry in index one So this is index zero. This is one two three that the dot all the way up to 15 So there's 16 entries. So This is our page table entry in L One so if we look at this f corresponds to one one one So that means this entry is valid So it means we can continue and actually use that so if this is an entry in our L One page table. What does this physical page number actually correspond to? quite So what does the page table entry in L one tell us if it is valid? Yeah, it tells us where the L zero page table is we use next so Since it is one f and we separate it out that means it's valid and the physical page number is one So that means we use physical page one and this is our L Zero page table So we will use this as our L zero page table Right any questions about that we got some nodding. Oh, we got Oh You're good. Okay. You shook your head. All right. So in our L zero page table now working at index two What's the bite at index two? Yeah, hex ff So same thing. This is entry zero one two three That the dot the dot the dot so we're only looking at entry two so the page table entry there is ff Is this valid? Yes, because well the last hex is f so that means execute write read valid or all one so it means it's valid so We made it to the end. We made it to L zero. We're done. This is our physics or this is our page table entry in L zero So it's our last one. So any questions about that? made it so We made it to the end. We got ff so Remember this f is our physical page number and No matter how many levels of page tables at the end of the day when we're translating address like one two three Well, we're always translating no matter what this virtual page number an offset to an offset and Physical page number so because this could be any number since we're at the L zero page table The physical page number we found is actually our final translation. So it's what we use for this So what should I use for the offset here? Three I just keep it the same don't have to change it because everything is all page in line What is the physical page number that I wound up with at the end of the day in L zero? F so my physical address at the end of the day should be f3 So any questions about that? That's about as hard as virtual memory gets thankfully hopefully Ish All right. We sure we're good on virtual memory All right, so we have some options unless anyone has any. Oh, yep Pipes. Oh, can we have a review of pipes and how to IPC stuff with them? All right, so Here, let me see if there is a past question. Otherwise, I guess I can make something up The next question. Oh, here's a giant question with pipes All right, does this look good All right, so this is a giant question with pipes. Oh god. It's lots of pipes All right, so this code uses two pipes to collect results from an expensive independent calculation using two processes All right. Well, let's go I Haven't looked at this in a while. So let's figure out what this does so we will have one process executing this and It's going to declare two arrays and then call pipe twice So this should set up a bunch of file descriptors. So I Will go ahead and just draw two pipes. So Here is the first pipe pipe fd1 At index one would be the right end of the pipe So I'll draw it like this. So it's putting data into the pipe and this pipe is like a buffer That's just managed by the kernel and then pipe Fd1 at index zero This is the read end of the pipe. So read Right. All right. Is that okay so far? All right, so it's going to call pipe again Create another fun pipe So we'll have pipe fd 22 at index one pipe fd to at index zero This would be a read and this would be a right end and Let's write in. Oh, no purple. Let's just give them file descriptor numbers. Yep. Yeah, that's the rule Yeah, so if we give these actual file descriptor numbers that our process is actually using Zero one and two already taken this would probably get actual the value at this array index would probably be like file descriptor three file descriptor four file descriptor five file descriptor six so, oh This is this is this question gets fun fast. All right, so now it calls fork So we'll create a new process right everyone remember how fork works So we so we create a new process in this new process It would probably get the number. I don't know 101 Would it also have all these file descriptors open? Yeah, so Remember fork exact copy of the process of process 101 would have file descriptor Three four five six and they would all correspond to the same file descriptors because everything's shared So they're not shared everything's the exact copy of each other so process 100 and 101. Oh God that forks again. Jesus. Who did this? All right, so They are Two processes and the only difference is what gets returned from forks. So in process a hundred PID one equals what? 101 101 in process 101 PID one equals what zero and here I will draw the Family tree so process a hundred created 101 So at this point we have no idea what process is actually going to run So I will just for the sake of argument say process 101 runs So if process 101 runs, it would go into this if statement and then close file descriptor if pipe fd1 and the read so Let's just write out to the site here in 101 What all the file descriptors are so it would have file descriptor? three the three four five three is read of Pipe fd1 This is right of fd1 read fd oops Fd2 right Fd2 So what process 101 does is it closes pipe fd1 zero so it closes their read end of the pipe So that means that in process 101 This file descriptor is now not valid at all right So next thing it does is compute a value and then it writes to the right end of this pipe so Some value is going to be inside of it after it so let's just Say that there's some value in the pipe here that another process can read So it has filled up the pipe and then it closes that file descriptor So it has inserted some data in the pipe and now file descriptor 4 is no more and then the So if that process ends well, it would clean up all the file descriptors and it doesn't exist anymore So it just wrote some stuff into that pipe So now if process 100 executes, what's it going to do? Create a new process probably called in 102 So we would create 102 PID 2 in process 100 would be 102 in process 102 Well, PID 1 is going to be equal to 101 because it's a copy at the time of the fork and Then after that it would create PID 2 and then assign it to 0 So any questions about that? All right, we're good. So let's say 102 starts executing So 102 executes it would close the it would get its own file descriptors Oops 102 and it would have been a clone of its parent. So in its parent It would have had all these file descriptors open So 3, 4, 5, 6 Which is read FD1 write FD1 read FD2 write FD2 so it closes the read end of the pipe of FD2 writes a value to it So in here it would have a value in this pipe and then it closes the right end of the pipe and Then it calls exit and then process 102 is now gone So only process 100 can execute. So in process 100 It still has all of the pipes open. So it's whoops process 100 Still has file descriptor 3, 4 5 and 6 Which again is read FD1 write FD1 read FD2 write FD2 So what it does is it closes the right ends of the pipe So these are now no longer valid in that process and Then what does it do? So create some variable and then reads from the pipe FD1 so it's reading from the read end of the pipe. So it should read that value out of it, right? So it reads some value out of it and Then just adds it to this temp variable and then reads the net value out of FD pipe FD2 and Then reads that value and then adds to it and then it closes all of the file descriptors So at the end of the day it just communicated with two processes using pipes All right any questions about that whole flow before we get into what this question actually asks. Yeah joining. I can't join processes If I wait on them. Yeah, so now at this current juncture our Process 101 and 102 terminated Well, at least Yeah, at least the way I did they got terminated But they might not be terminated at this point if they were terminated would they be zombies orphans or chillin? Sorry. Yeah, so they could be terminated if they're terminated. They're technically zombies Yeah, so nothing would affect the result so Let's see what the questions are So would removing calls to close in the child process still allow the child process to behave normally? Explain your answer. So in this case It's just saying what would happen if I just like didn't do these calls to close here and In this particular case well, it doesn't really matter because whenever you exit from a process Well, it terminates and all the file descriptors get cleaned up anyways So did I really need to do this? Not really so remember the problem with pipes usually is if one process still has the right end of the pipe open it's going to cause lots of problems because it's Potentially more data will come into it So it won't report like the end of file and it'll just keep sitting at that read and blocking forever So in this case if I remove the calls to close Nothing bad happens because all I do is write to it and then I terminate the processes So any questions about that part? Okay, so next one Is it possible to modify the given code? So only one pipe is used between the processes if so explain how you would do this and modify the code listing if not Explain why it is not possible any guesses with this one Yeah, there's actually a lot of options here that I could actually do because they're both writing to it and also in this case If we look what we're doing here, we're just adding the two values together So the order doesn't actually matter either So I could just use one pipe and even if I didn't have an exact order between the processes It doesn't really matter if one writes its value first and then the other like is there a difference between adding two to one first adding one to two Yeah, so in this case pipes don't have data races because it's a system called the kernel handles any data races So you'll get one written completely and then two written completely You won't know what order they're in but they'll be complete. It won't be like halfway So in this case Well the answer is yes We could modify it so that only one pipe is used for several reasons So we could do what you said we could just make sure only one process happens at once Read the data from it launch the other one read the data from it or in this case because we're just adding them together Doesn't actually matter what order we get them in so either answer works fine So this one isn't necessary to call weight PID for the child processes so What we do so Here we didn't call weight PID Was that bad No So kind of bad kind of not why argue why it is not so bad read Yeah Yeah, so the reed will wait on the right So reads blocking waiting for information or if it's not possible for any more data to go into that pipe It'll just return zero and be done So in this case if you want to argue that it wasn't a big deal. Well process one oh One oh one and one oh two will be zombies, but we also terminate We don't keep them around the zombies for long So they will become our favorite orphan zombies get reparented to probably a knit and then a knit will wait on them And then clean them up so it's not that big of a deal which which close Yeah, so if you if you don't call these clothes here Yeah, then the reed will never return it will block forever Because you have the right end of the pipe open as long as there is at least one process with the right end of the pipe open Read won't return zero So in this case if we got rid of the closes in the if branches, it's fine. It doesn't matter because They'll immediately they'll write which doesn't block on anything and then terminate and then that clears up all its file descriptors and everything Yeah, if a hundred executes before one oh one terminates, they'll just block there until one oh one terminates But eventually one oh one is still Schedulable so it will run eventually So was that good enough for pipes or do you want any more pipe stuff? Oh? No, we're on your phone Pipes good or more pipes Okay, yeah Where the parent exits before the child so in this case Yeah, in this case the parent could exit before the child if it just read so it doesn't read the completion until it's empty If it just reads four bytes or something like that then and it doesn't wait for it to actually close Then yeah, the parent might actually die first in this case But that's like a corner cave. Yeah Default answer is to say always wait PID because you should be a good parent Unless you want them to last longer than your process so you don't create zombie processes In terms of order The parent process does wait for the results from the child process because the read will block anyways before they write data So it doesn't really matter so we know the parent will exit shortly after both child processes finish anyways So it's not that big of a problem. They won't be zombies for that long. You can make that argument Yeah, you can just say yeah it matters because I don't want to create zombie processes So I'll clean them up if you want to be contrarian and say it doesn't matter you have to argue better So either answer is valid as long as you could justify it So it's like that Standard C exception why they don't have to call free you can make that too, but you have to justify it All right Yep, so in the case of parent exits first, it's done out all its useful work. Anyways, so it doesn't really matter All the original process wants to do is just add two numbers together. It doesn't really matter if it dies first or not So when you clone The new process has the same file descriptors as the parent and you can think of file descriptors It's just like pointers. So if I close file descriptor three File descriptors are independent for processes. So your file descriptor three is not the same as another process as file descriptor three Yeah, so if you fork that means you have a file descriptor three because your parent had a file descriptor three at the time of the fork If after the fork you close file descriptor three you close your file descriptor three Yeah, all right any other questions Yeah, so in this case because like each Process only closes like the pipe it's using and leaves the other one open if The child process is stuck around for whatever reason and the parent was just Reading the pipe until it eventually couldn't get any more data out of it Yeah, it might hang forever because it's technically still possible for it to get data Yeah, if everything has the right closed, then it's fine But that takes more code modifications here than we can do quickly All right, any other yeah so The question is if for a pipe if the right end is closed will the read-end automatically close So no so the way pipes work is that well they can be shared Like different processes could have file descriptors that represent that pipe, right? So the rule is with pipes Usually you know if you can't get any data if you're at end of file as if you call read on something and you return zero That means no more data as possible You can stop using it. No more data is possible So for pipes that will only happen if no process at all has the right end of the pipe open and Also for that to happen. You have to have read all the data from the pipe in order to get zero Yeah Yeah, so the kernels managing the pipe, so it's like a system call, right? So the kernel knows keeps track of all the processes and knows what file descriptors they all have and how many of them are Referencing that pipe so in this case, it's not a problem if we don't close because it'll get closed when it's terminated anyways so the problem happens if like if We're sharing a pipe so unrelated questions, so say we have Process a hundred and process one oh one if this is like just doing like while Whoops If this is just doing like while read and Then say Whatever this is is The read end of the pipe so say this process is just constantly reading over and over again And we'll read as long as the answer is not zero if this process Just has file descriptor on a four open and this represents the right end of the pipe No matter what Process a hundred that read will never return zero Because it's still possible that process 101 writes data to it So it's possible that could still get data so I can't say it's not possible for it to get data anymore Nope pipes aren't special. It's just it's essentially occur no, it's essentially just a Buffer of bytes that the kernel manages for you that you can write to through a file descriptor and read from with another file descriptor But you can just read and write bytes to it. Yep Is there a limit to its size? Yeah, the kernel probably has some limit I mean you'll be limited by physical memory eventually and page size but Generally, it's pretty big It will probably complain it will just give you an error if it's full when you try and write more data to it It'll just be like Because right returns the number of bytes actually written to it So you try and write a million bytes to it. It'll be like yeah, I wrote a thousand of those. Good luck. Yeah Yeah, this is This is streamed Also to save you time so I had this question the other I guess I should tell you you context stuff Don't worry about it. Boom saved you like three hours Other stuff. Let's see Our threads on it. So here is a giant No, that's too far So our threads on it. So Yeah, so here's a giant question from like the CS111 final that has to do with Threads and processes and how they interact. So like what happens if you fork if you have multiple threads So technically this is in scope for you, but this question Don't worry about it so much because you know, I Don't remember writing about threads except for a short answer question So if you want to also save yourself a time in max Threads at most it would be worth like five marks out of Exams same thing. So it'll be a mark a minute. So 75 So there'll be some type of thread, but it's fairly small. It's not a gigantic question. All right any Anything else for like the last three minutes Yeah, I so I'm also bad about keeping secrets for exams, but I also have a short bad short-term memory So I don't quite remember what I wrote so you can try Yeah, so for this one this question with threads and processes section two did that if you want to go over that Unique stuff to section one section one asked about this So this is more fair game like what you would have if you want to do this So you can look at the recording for section one. It was also This was also at the very end of process practice lecture. So you also have this question as well So we can go over that. Oh and also another file thing. So Hey, you have a bunch of lab sections tomorrow. I highly doubt any of you will actually use it to the labs So Usually Wednesdays. I'm not in Toronto, but guess what I will be in Toronto tomorrow because I have to be so I will probably be in Your lab sections to answer any last-minute questions Because my office will probably not be big enough for all of you So I will be in there and I will Pretty much just tell you whenever I arrive in Toronto. I have no guarantees whenever I'm here Other than I will be in Toronto sometime before your midterm So aside from that, I will not guarantee but we can use the practical rooms and I will be there and you can Ask me questions. All right anything else for the last two minutes Questions concerns anyone want to try and sneak what's actually on the exam? Yeah Oh, yeah sockets who really cares about sockets. So sockets weren't really anything new They're essentially just file descriptors that take a bunch of setup Maybe the only thing that would be Somewhat useful is like oh, yeah For a server that would be like multiple file descriptors that you could Have Maybe you can use like threads or something like that with that Some fun stuff. Yeah. Yeah, so I will not ask you anything about The api for sockets anything like that, but Sockets are essentially just file descriptors, which we know Yeah, all right. So with that just remember pulling for you. We're all in this together and we'll survive the midterm. It won't be too