1 00:00:00,550 --> 00:00:04,390 So in case you are all worried that you may not 2 00:00:04,390 --> 00:00:07,496 be in the right class, you are still in 6.033. 3 00:00:07,496 --> 00:00:08,870 If you're wondering what happened 4 00:00:08,870 --> 00:00:10,500 to the Indian guy who normally lectures, 5 00:00:10,500 --> 00:00:11,750 he's sitting right over there. 6 00:00:11,750 --> 00:00:16,806 We are trading off lectures throughout the class. 7 00:00:16,806 --> 00:00:18,680 I'm going to do about the next eight lectures 8 00:00:18,680 --> 00:00:21,210 up until spring break, and then Hari will be back. 9 00:00:21,210 --> 00:00:23,500 So, my name is Sam, and feel free 10 00:00:23,500 --> 00:00:25,900 to address any questions about the lecture to me. 11 00:00:25,900 --> 00:00:28,380 So today we are going to keep talking 12 00:00:28,380 --> 00:00:31,070 about this concept of enforcing modularity that we started 13 00:00:31,070 --> 00:00:32,070 talking about last time. 14 00:00:41,180 --> 00:00:45,200 So last time we saw how we could use this notion of the client 15 00:00:45,200 --> 00:00:51,000 service model in order to separate 16 00:00:51,000 --> 00:00:52,640 two modules from each other. 17 00:00:52,640 --> 00:00:57,260 So the idea was by running the client and the service 18 00:00:57,260 --> 00:00:59,574 on separate machines, we can isolate these two things 19 00:00:59,574 --> 00:01:00,240 from each other. 20 00:01:00,240 --> 00:01:03,670 So we can make it so, for example, when the client wants 21 00:01:03,670 --> 00:01:06,620 to invoke some operation on the server, 22 00:01:06,620 --> 00:01:12,630 that the server can verify the request that the client makes, 23 00:01:12,630 --> 00:01:14,380 and make sure that the client isn't asking 24 00:01:14,380 --> 00:01:16,010 to do something malicious. 25 00:01:16,010 --> 00:01:21,790 Similarly, so this is what we saw last time was this client 26 00:01:21,790 --> 00:01:23,380 service model. 27 00:01:23,380 --> 00:01:27,760 And so the other benefit of the client service model 28 00:01:27,760 --> 00:01:29,440 was it meant that we could decouple 29 00:01:29,440 --> 00:01:31,440 the client from the service. 30 00:01:31,440 --> 00:01:34,070 So it meant that when the client issued a request 31 00:01:34,070 --> 00:01:39,190 against the service, it didn't necessarily 32 00:01:39,190 --> 00:01:42,150 mean that the client, if the service failed when 33 00:01:42,150 --> 00:01:44,440 the client issued the request, it wasn't necessarily 34 00:01:44,440 --> 00:01:46,710 the case that the client would also fail. 35 00:01:46,710 --> 00:01:49,916 So the server might crash executing the request, 36 00:01:49,916 --> 00:01:51,540 and then the client would get a timeout 37 00:01:51,540 --> 00:01:53,020 and would be able to retry. 38 00:01:53,020 --> 00:01:57,520 And similarly, if the client failed, 39 00:01:57,520 --> 00:01:59,340 the server could continue handling requests 40 00:01:59,340 --> 00:02:00,900 on the behalf of other clients. 41 00:02:00,900 --> 00:02:02,900 OK, so that was a nice separation, the ability 42 00:02:02,900 --> 00:02:07,090 to split the client and the server apart from each other. 43 00:02:07,090 --> 00:02:08,270 That's a good thing. 44 00:02:08,270 --> 00:02:09,690 But the problem with this approach 45 00:02:09,690 --> 00:02:11,905 is that we had to have two separate machines. 46 00:02:11,905 --> 00:02:14,280 The way we presented this was that the client was running 47 00:02:14,280 --> 00:02:15,980 on one computer, and the server was 48 00:02:15,980 --> 00:02:17,810 running on another computer. 49 00:02:17,810 --> 00:02:20,484 And if you think about this, this 50 00:02:20,484 --> 00:02:21,900 isn't exactly what we want, right? 51 00:02:21,900 --> 00:02:23,358 Because that means, suppose we want 52 00:02:23,358 --> 00:02:26,230 to build up a big, complicated computer system that's composed 53 00:02:26,230 --> 00:02:28,620 of multiple different modules. 54 00:02:28,620 --> 00:02:30,760 If we have to run each one of those modules 55 00:02:30,760 --> 00:02:35,237 on a separate computer, that's not really very ideal, right? 56 00:02:35,237 --> 00:02:36,820 To build up a big service, we're going 57 00:02:36,820 --> 00:02:37,830 to need a whole lot of computers. 58 00:02:37,830 --> 00:02:40,190 And clearly, that's not the way that computer systems 59 00:02:40,190 --> 00:02:42,710 that we actually interact with work. 60 00:02:42,710 --> 00:02:44,850 So what we've seen so far is this notion: 61 00:02:44,850 --> 00:02:50,770 we have a module per computer. 62 00:02:50,770 --> 00:02:53,630 OK, and what we're going to do today 63 00:02:53,630 --> 00:02:56,940 is see how we can generalize this 64 00:02:56,940 --> 00:02:59,150 so that instead of having one module per computer, 65 00:02:59,150 --> 00:03:01,840 we can instead have multiple modules running 66 00:03:01,840 --> 00:03:03,250 within a single computer. 67 00:03:03,250 --> 00:03:04,690 But when we do that, we still want 68 00:03:04,690 --> 00:03:07,660 to maintain these nice sort of protection benefits 69 00:03:07,660 --> 00:03:09,670 that we had between the client and service 70 00:03:09,670 --> 00:03:12,180 when these two things were running on separate computers. 71 00:03:12,180 --> 00:03:13,720 OK, so the way we are going to do 72 00:03:13,720 --> 00:03:19,050 that is by creating something we call a virtual computer. 73 00:03:19,050 --> 00:03:31,700 So -- What we're going to do is we're going to create this 74 00:03:31,700 --> 00:03:33,960 notion of multiple virtual computers. 75 00:03:33,960 --> 00:03:35,752 They're all running on one single computer. 76 00:03:35,752 --> 00:03:37,960 And then we're going to run each one of these modules 77 00:03:37,960 --> 00:03:39,210 within a virtual computer. 78 00:03:39,210 --> 00:03:40,810 OK, and I'll talk more about what 79 00:03:40,810 --> 00:03:43,950 I mean by a virtual computer throughout the next couple 80 00:03:43,950 --> 00:03:44,760 of lectures. 81 00:03:44,760 --> 00:03:49,430 But the idea is that a virtual computer has exactly the same, 82 00:03:49,430 --> 00:03:51,700 to a program that's running on it, 83 00:03:51,700 --> 00:03:53,750 a virtual computers looks just like one 84 00:03:53,750 --> 00:03:56,017 of these client or server computers might have looked. 85 00:03:56,017 --> 00:03:57,600 Now, in particular, a virtual computer 86 00:03:57,600 --> 00:04:00,680 has the same sorts of abstractions 87 00:04:00,680 --> 00:04:03,430 that we studied in the previous lectures available to it 88 00:04:03,430 --> 00:04:04,780 that a real computer has. 89 00:04:04,780 --> 00:04:10,580 So a virtual computer has a virtual memory -- 90 00:04:10,580 --> 00:04:14,205 -- and a virtual processor. 91 00:04:18,839 --> 00:04:22,350 So, today what we're going to talk about 92 00:04:22,350 --> 00:04:24,810 is this notion of a virtual memory. 93 00:04:24,810 --> 00:04:28,010 And so you guys have already probably seen 94 00:04:28,010 --> 00:04:29,936 the term virtual memory in 6.004. 95 00:04:29,936 --> 00:04:31,560 So, the word should be familiar to you. 96 00:04:31,560 --> 00:04:33,800 And we're going to use exactly the same abstraction 97 00:04:33,800 --> 00:04:35,440 that we used in 6.004. 98 00:04:35,440 --> 00:04:37,810 So we're just going to show how this abstraction can 99 00:04:37,810 --> 00:04:40,600 be used to provide this protection between the client 100 00:04:40,600 --> 00:04:41,940 and server that we want. 101 00:04:41,940 --> 00:04:44,840 OK, we're also going to introduce today this notion 102 00:04:44,840 --> 00:04:48,050 of something called a kernel. 103 00:04:48,050 --> 00:04:50,480 And a kernel is something that's in charge, basically, 104 00:04:50,480 --> 00:04:53,050 of managing all of these different virtual computers 105 00:04:53,050 --> 00:04:55,500 that are running on our one physical computer. 106 00:04:55,500 --> 00:04:57,900 So the kernel is going to be the sort of system that 107 00:04:57,900 --> 00:05:00,320 is going to be the piece of the system that actually knows 108 00:05:00,320 --> 00:05:02,403 that there are multiple, virtual computers running 109 00:05:02,403 --> 00:05:04,290 on this system. 110 00:05:04,290 --> 00:05:09,320 OK, so I want to start off by first just talking 111 00:05:09,320 --> 00:05:11,920 about why we want a virtualized memory, why virtualizing 112 00:05:11,920 --> 00:05:13,250 memory is a good thing. 113 00:05:13,250 --> 00:05:19,490 So I'm going to abbreviate virtual memory as VM. 114 00:05:19,490 --> 00:05:22,690 So why would we want to virtualize memory? 115 00:05:22,690 --> 00:05:25,810 Well, let's see what might happen if we build a computer 116 00:05:25,810 --> 00:05:27,790 system with multiple modules running on it 117 00:05:27,790 --> 00:05:31,930 at the same time that didn't have a virtualized memory. 118 00:05:31,930 --> 00:05:36,180 So suppose we have some microprocessor 119 00:05:36,180 --> 00:05:38,590 and we have some memory. 120 00:05:42,790 --> 00:05:48,190 And within this memory, we have the code 121 00:05:48,190 --> 00:05:51,110 and data for a couple of different modules is stored. 122 00:05:51,110 --> 00:05:54,500 So we have, say, module A and module B, 123 00:05:54,500 --> 00:06:02,430 and this is the things like the code and the data 124 00:06:02,430 --> 00:06:05,350 that these modules are using to currently execute. 125 00:06:05,350 --> 00:06:09,120 So, in this environment, suppose the module, A, 126 00:06:09,120 --> 00:06:10,335 executes some instruction. 127 00:06:12,960 --> 00:06:16,500 So if you think of this as memory, 128 00:06:16,500 --> 00:06:20,460 let's say that module A begins at address A here, 129 00:06:20,460 --> 00:06:23,860 and module B begins at address B here. 130 00:06:23,860 --> 00:06:26,840 So, suppose that module A executes 131 00:06:26,840 --> 00:06:34,780 some instruction like store some value, R1, in memory address, 132 00:06:34,780 --> 00:06:35,510 B. 133 00:06:35,510 --> 00:06:39,860 OK, so module A writes into memory address B here. 134 00:06:39,860 --> 00:06:42,540 So, this can be a problematic thing, 135 00:06:42,540 --> 00:06:45,280 right, because if the microprocessor just 136 00:06:45,280 --> 00:06:46,730 allows this to happen, if it just 137 00:06:46,730 --> 00:06:50,500 allows A to write into module B's memory, 138 00:06:50,500 --> 00:06:53,420 then module B has no way of being isolated 139 00:06:53,420 --> 00:06:55,070 from module A at all, right? 140 00:06:55,070 --> 00:06:58,344 Module A can, for example, write some sort of garbage 141 00:06:58,344 --> 00:06:59,510 into the memory of module B. 142 00:06:59,510 --> 00:07:04,130 And then when module B tries to read from that memory address, 143 00:07:04,130 --> 00:07:06,920 it will either, say, try and execute an illegal instruction, 144 00:07:06,920 --> 00:07:09,510 or it will read in some data that doesn't make any sense. 145 00:07:09,510 --> 00:07:15,260 So we've lost the separation, the isolation 146 00:07:15,260 --> 00:07:18,230 that we had between if module A and module B are a client 147 00:07:18,230 --> 00:07:20,457 and a service trying to interact with each other. 148 00:07:20,457 --> 00:07:21,790 We've lost this sort of ability. 149 00:07:24,640 --> 00:07:26,590 We've lost the ability to separate and isolate 150 00:07:26,590 --> 00:07:28,430 each other, isolate them from each other 151 00:07:28,430 --> 00:07:32,270 that we had when they were running on separate computers. 152 00:07:32,270 --> 00:07:37,730 Furthermore, this sort of arrangement of virtual memory. 153 00:07:37,730 --> 00:07:47,080 So one problem with this is A can overwrite B's memory. 154 00:07:47,080 --> 00:07:48,640 But we have another problem, which 155 00:07:48,640 --> 00:07:52,090 is that this sort of arrangement also is very, very 156 00:07:52,090 --> 00:07:52,970 difficult to debug. 157 00:07:52,970 --> 00:07:55,389 So, these kinds of bugs can be very hard to track down. 158 00:07:55,389 --> 00:07:57,430 And really, when we're building computer systems, 159 00:07:57,430 --> 00:07:58,680 we'd like to get rid of them. 160 00:07:58,680 --> 00:08:02,640 So, for example, suppose that A stores into B's memory, 161 00:08:02,640 --> 00:08:06,090 overwrites an instruction that somewhere sort of arbitrarily 162 00:08:06,090 --> 00:08:07,050 within B's memory. 163 00:08:07,050 --> 00:08:08,980 And then, 10,000 instructions later, 164 00:08:08,980 --> 00:08:10,810 B tries to load in that memory address 165 00:08:10,810 --> 00:08:12,080 and execute that instruction. 166 00:08:12,080 --> 00:08:13,740 And it gets an illegal instruction. 167 00:08:13,740 --> 00:08:15,781 Now, imagine that you have to debug this program. 168 00:08:15,781 --> 00:08:18,020 So you sort of are sitting there, 169 00:08:18,020 --> 00:08:23,870 and so you run application B, and it works just fine. 170 00:08:23,870 --> 00:08:26,610 And then you run application A, and A overwrites part 171 00:08:26,610 --> 00:08:27,590 of B's memory. 172 00:08:27,590 --> 00:08:30,420 And now, when program B runs sometimes 173 00:08:30,420 --> 00:08:33,210 long after program A, perhaps, is already terminated, 174 00:08:33,210 --> 00:08:35,091 B mysteriously crashes on you. 175 00:08:35,091 --> 00:08:37,049 So how are you going to track down the problem? 176 00:08:37,049 --> 00:08:38,965 It's very tricky, and it's the kind of problem 177 00:08:38,965 --> 00:08:41,330 that's extremely hard to debug these kinds of issues. 178 00:08:41,330 --> 00:08:42,780 So we really would like to make it 179 00:08:42,780 --> 00:08:46,260 so that A isn't able to simply overwrite arbitrary 180 00:08:46,260 --> 00:08:47,280 things into B's memory. 181 00:08:47,280 --> 00:08:48,876 We'd like to protect A from B. 182 00:08:48,876 --> 00:08:51,000 OK, and that's what this virtual memory abstraction 183 00:08:51,000 --> 00:08:54,070 that we're going to talk about today is going to do for us. 184 00:08:54,070 --> 00:08:59,290 So, if you think about how you might protect A from B, 185 00:08:59,290 --> 00:09:02,461 the solution that you sort of come up 186 00:09:02,461 --> 00:09:04,210 with after thinking about this and staring 187 00:09:04,210 --> 00:09:05,780 at this for a little bit is that you 188 00:09:05,780 --> 00:09:08,720 want to verify that all of the memory 189 00:09:08,720 --> 00:09:12,200 accesses that A does are actually valid memory 190 00:09:12,200 --> 00:09:14,300 accesses that A should be allowed to make, so 191 00:09:14,300 --> 00:09:16,970 for example, that refer to objects that are actually 192 00:09:16,970 --> 00:09:19,600 that A has allocated or that A owns. 193 00:09:19,600 --> 00:09:23,180 OK, so in order to do that, what we're going to need to do 194 00:09:23,180 --> 00:09:25,590 is to interpose some sort of software 195 00:09:25,590 --> 00:09:32,880 in between the memory accesses that each module makes, 196 00:09:32,880 --> 00:09:34,840 and the actual memory access. 197 00:09:34,840 --> 00:09:38,570 So the idea is as follows. 198 00:09:38,570 --> 00:09:40,690 So this is the virtual memory abstraction. 199 00:09:43,940 --> 00:09:45,720 OK, so the idea is as follows. 200 00:09:48,520 --> 00:09:54,250 For each one of our modules, say A and B, 201 00:09:54,250 --> 00:09:59,065 we're going to create what's known as an address space, OK? 202 00:10:02,850 --> 00:10:07,500 And this address space is going to be, for example, 203 00:10:07,500 --> 00:10:14,560 on a 32 bit computer, it's two to the 32 minus one, 204 00:10:14,560 --> 00:10:18,210 it's going to be a 32 bit memory space. 205 00:10:18,210 --> 00:10:23,440 So, this is the virtual address space of, say, a process, A. 206 00:10:23,440 --> 00:10:26,470 So, process A can use any memory address 207 00:10:26,470 --> 00:10:31,290 that's in this two to the 32 bit range, OK? 208 00:10:31,290 --> 00:10:33,940 But this is going to be a virtual address space. 209 00:10:33,940 --> 00:10:44,390 And what I mean by that is when process A refers 210 00:10:44,390 --> 00:10:46,930 to some address within its memory space, 211 00:10:46,930 --> 00:10:51,210 call it virtual address VA. 212 00:10:51,210 --> 00:10:54,750 That address is going to be mapped by the virtual memory 213 00:10:54,750 --> 00:10:58,140 system into a physical address, OK? 214 00:11:02,200 --> 00:11:07,240 So this virtual address here is going to be mapped into some 215 00:11:07,240 --> 00:11:10,980 physical address -- 216 00:11:10,980 --> 00:11:18,250 -- somewhere within the actual physical memory of the system, 217 00:11:18,250 --> 00:11:18,750 OK? 218 00:11:18,750 --> 00:11:24,650 So this physical memory of the system is also a 32 bit space. 219 00:11:27,910 --> 00:11:30,480 But the sort of mapping from this virtual address 220 00:11:30,480 --> 00:11:34,140 in A's memory into this physical address space 221 00:11:34,140 --> 00:11:37,820 is going to be handled by this virtual memory system. 222 00:11:37,820 --> 00:11:41,800 So now the idea is that each thing that, say, 223 00:11:41,800 --> 00:11:44,000 a process A or B might want to reference 224 00:11:44,000 --> 00:11:46,569 is going to be mapped into some different location 225 00:11:46,569 --> 00:11:47,360 within this memory. 226 00:11:47,360 --> 00:11:53,480 So, for example, the code from process A or from module A 227 00:11:53,480 --> 00:11:58,620 can be mapped into one location, and the code from module B 228 00:11:58,620 --> 00:12:01,750 is going to be mapped into a different location 229 00:12:01,750 --> 00:12:04,490 in the physical address space. 230 00:12:04,490 --> 00:12:06,539 OK, so we have this notion of address spaces. 231 00:12:06,539 --> 00:12:09,080 Each module that is running on the system in a virtual memory 232 00:12:09,080 --> 00:12:12,430 system is going to be allocated to one of these address spaces. 233 00:12:12,430 --> 00:12:15,920 This address space is going to be, 234 00:12:15,920 --> 00:12:20,900 and this address space is virtual in the sense 235 00:12:20,900 --> 00:12:24,290 that these addresses are only valid in the context 236 00:12:24,290 --> 00:12:26,190 of this given module, OK? 237 00:12:26,190 --> 00:12:30,760 And, they translate into, each address in the virtual space 238 00:12:30,760 --> 00:12:32,977 translates into some address in the physical space. 239 00:12:32,977 --> 00:12:34,560 Now, if you look at this for a minute, 240 00:12:34,560 --> 00:12:36,070 you might think, well, this is kind 241 00:12:36,070 --> 00:12:38,910 of confusing because now B and A both have a 32 bit address 242 00:12:38,910 --> 00:12:39,570 space. 243 00:12:39,570 --> 00:12:42,420 And the computer itself only has a 32 bit address space. 244 00:12:42,420 --> 00:12:45,240 So, there are sort of more addresses 245 00:12:45,240 --> 00:12:48,200 between all the modules than the computer itself physically has. 246 00:12:48,200 --> 00:12:50,630 And, if you remember back from 6.004, the story 247 00:12:50,630 --> 00:12:52,470 that we told you about that was that, well, 248 00:12:52,470 --> 00:12:54,520 some of these virtual addresses can actually 249 00:12:54,520 --> 00:12:56,490 be mapped into the disk on the computer. 250 00:12:56,490 --> 00:12:59,400 So in 6.004, virtual memory was presented as a way 251 00:12:59,400 --> 00:13:01,410 to create a computer that appeared 252 00:13:01,410 --> 00:13:05,080 to have more physical memory than it, in fact, did. 253 00:13:05,080 --> 00:13:06,660 And the way that that was done was 254 00:13:06,660 --> 00:13:10,250 to map some of these addresses onto disk. 255 00:13:13,964 --> 00:13:16,130 So you might have addresses from B mapped onto disk. 256 00:13:16,130 --> 00:13:18,338 And then, when B tries to reference an address that's 257 00:13:18,338 --> 00:13:22,850 mapped onto disk, the system would load that data 258 00:13:22,850 --> 00:13:25,570 from memory, load that data from disk and into memory. 259 00:13:25,570 --> 00:13:27,530 So, we're not going to talk about that aspect 260 00:13:27,530 --> 00:13:29,587 of virtual memory very much today. 261 00:13:29,587 --> 00:13:31,920 The thing to remember is just that these virtual address 262 00:13:31,920 --> 00:13:35,280 spaces, there may be parts of this virtual address 263 00:13:35,280 --> 00:13:36,780 space in each of the modules that 264 00:13:36,780 --> 00:13:39,540 isn't actually mapped into any physical address space. 265 00:13:39,540 --> 00:13:43,510 So if one of these modules tries to use 266 00:13:43,510 --> 00:13:45,660 one of these unmapped virtual address spaces, 267 00:13:45,660 --> 00:13:47,410 it's not allowed to do that. 268 00:13:47,410 --> 00:13:49,969 This virtual memory system will signal an error 269 00:13:49,969 --> 00:13:51,010 when it tries to do that. 270 00:13:51,010 --> 00:13:52,842 And on your computer, sometimes you'll 271 00:13:52,842 --> 00:13:54,300 see programs that will mysteriously 272 00:13:54,300 --> 00:13:58,030 crashed with things that say things like, tried to access 273 00:13:58,030 --> 00:13:59,880 an illegal memory address. 274 00:13:59,880 --> 00:14:02,220 When it does that, that's because the program 275 00:14:02,220 --> 00:14:05,377 tried to access some memory location that wasn't mapped 276 00:14:05,377 --> 00:14:06,585 by the virtual memory system. 277 00:14:11,600 --> 00:14:15,990 OK, so let's dive a little more into actually 278 00:14:15,990 --> 00:14:17,796 how this virtual memory abstraction works 279 00:14:17,796 --> 00:14:19,670 so we can try to understand a little bit more 280 00:14:19,670 --> 00:14:20,586 about what's going on. 281 00:14:20,586 --> 00:14:29,990 So this is going to be a simplified VM hardware, OK? 282 00:14:33,530 --> 00:14:35,830 It's a little bit simplified even 283 00:14:35,830 --> 00:14:37,710 from what you learned about in 6.004. 284 00:14:37,710 --> 00:14:40,170 So, the idea in this simplified hardware 285 00:14:40,170 --> 00:14:44,640 is that we have our processor. 286 00:14:44,640 --> 00:14:49,840 OK, and then we're going to have this VM system, which 287 00:14:49,840 --> 00:14:52,866 is sometimes called a memory management unit, MMU. 288 00:14:52,866 --> 00:14:54,490 And, this is a piece of hardware that's 289 00:14:54,490 --> 00:14:56,240 going to help us to do this mapping 290 00:14:56,240 --> 00:14:59,660 from these logical addresses in the modules' address spaces 291 00:14:59,660 --> 00:15:01,260 into the physical memory. 292 00:15:01,260 --> 00:15:04,400 And then, we're going to have the physical memory, OK? 293 00:15:08,090 --> 00:15:13,130 Now the idea is that when an instruction tries 294 00:15:13,130 --> 00:15:15,590 to access some virtual address, so for example 295 00:15:15,590 --> 00:15:19,990 suppose we execute instruction load 296 00:15:19,990 --> 00:15:24,806 some virtual address, load into R1 some virtual address, OK? 297 00:15:24,806 --> 00:15:26,180 What's going to happen when we do 298 00:15:26,180 --> 00:15:28,070 that is that the microprocessor is 299 00:15:28,070 --> 00:15:32,490 going to send this virtual address to the VM system. 300 00:15:32,490 --> 00:15:35,140 And then the VM system is going to translate that 301 00:15:35,140 --> 00:15:38,420 into some physical address that can be resolved 302 00:15:38,420 --> 00:15:40,400 within the memory itself. 303 00:15:40,400 --> 00:15:43,090 OK, and the way that the virtual memory system is going 304 00:15:43,090 --> 00:15:47,540 to decide this mapping between a virtual address 305 00:15:47,540 --> 00:15:49,630 and a physical address is by using something 306 00:15:49,630 --> 00:15:53,130 that we call a page map, OK? 307 00:15:53,130 --> 00:16:05,090 OK, so this table is an example. 308 00:16:05,090 --> 00:16:06,130 So this is a page map. 309 00:16:06,130 --> 00:16:07,660 And what a page map basically has 310 00:16:07,660 --> 00:16:11,940 is its just a table of virtual address to physical address 311 00:16:11,940 --> 00:16:12,645 mappings. 312 00:16:12,645 --> 00:16:14,770 So this is the virtual address to physical address. 313 00:16:14,770 --> 00:16:18,540 So the idea is that when some virtual address comes in here, 314 00:16:18,540 --> 00:16:20,190 the virtual memory manager looks up 315 00:16:20,190 --> 00:16:22,060 that virtual address in this page map, 316 00:16:22,060 --> 00:16:24,060 finds the corresponding physical address, 317 00:16:24,060 --> 00:16:25,770 and then looks that physical address up 318 00:16:25,770 --> 00:16:29,080 in the actual memory. 319 00:16:29,080 --> 00:16:33,040 OK, so now there's one more detail that we need, right? 320 00:16:33,040 --> 00:16:36,280 So what this gives us is we have this notion of a page map 321 00:16:36,280 --> 00:16:37,600 that does this mapping for us. 322 00:16:37,600 --> 00:16:39,870 But we're missing a detail that is, OK, 323 00:16:39,870 --> 00:16:43,610 what we wanted was for each one of these different modules 324 00:16:43,610 --> 00:16:46,610 that's running in the system to have a different address 325 00:16:46,610 --> 00:16:48,050 space associated with it. 326 00:16:48,050 --> 00:16:50,050 So what we want is we want to have separate page 327 00:16:50,050 --> 00:16:55,410 maps for each of these different modules, so, for A and B, 328 00:16:55,410 --> 00:16:57,680 OK, we're going to have a different page map. 329 00:16:57,680 --> 00:17:00,510 And we're going to have this sort of same, 330 00:17:00,510 --> 00:17:04,819 we might have multiple copies of a particular virtual address 331 00:17:04,819 --> 00:17:06,703 in each one of these page maps. 332 00:17:06,703 --> 00:17:08,119 And then what we're going to do is 333 00:17:08,119 --> 00:17:10,859 we're going to allocate a special register 334 00:17:10,859 --> 00:17:12,550 on the hardware, on the processor. 335 00:17:12,550 --> 00:17:15,700 We're going to add a little register that's 336 00:17:15,700 --> 00:17:18,490 going to allow us to keep track of which one of these page maps 337 00:17:18,490 --> 00:17:20,400 we are currently looking at, OK? 338 00:17:20,400 --> 00:17:25,319 So this thing is called the PMAR or the Page Map Address 339 00:17:25,319 --> 00:17:25,859 Register. 340 00:17:25,859 --> 00:17:37,370 OK, and the page map address register 341 00:17:37,370 --> 00:17:40,710 simply points at one of these page maps. 342 00:17:40,710 --> 00:17:45,340 OK, so what happens is that the virtual memory system, when 343 00:17:45,340 --> 00:17:47,840 it wants to resolve a virtual address, 344 00:17:47,840 --> 00:17:50,010 looks at this page map address register 345 00:17:50,010 --> 00:17:54,260 and uses that to find a pointer to the beginning of the page 346 00:17:54,260 --> 00:17:56,530 map that's currently in use. 347 00:17:56,530 --> 00:17:58,030 And then he uses the page map that's 348 00:17:58,030 --> 00:18:01,600 currently in use to resolve, to get 349 00:18:01,600 --> 00:18:03,490 what physical address corresponds 350 00:18:03,490 --> 00:18:04,570 to this logical address. 351 00:18:04,570 --> 00:18:08,130 OK so this is really the core concept from virtual memory. 352 00:18:08,130 --> 00:18:11,620 So what we have now is we have this page map address register 353 00:18:11,620 --> 00:18:14,780 that can be used to select which one of these address spaces 354 00:18:14,780 --> 00:18:16,110 we are currently using. 355 00:18:16,110 --> 00:18:19,270 OK, and so when we have selected, for example, 356 00:18:19,270 --> 00:18:24,540 the page map for module A, then module A 357 00:18:24,540 --> 00:18:27,530 can only refer to virtual addresses 358 00:18:27,530 --> 00:18:29,850 that are in its page map. 359 00:18:29,850 --> 00:18:32,860 And those virtual addresses can only 360 00:18:32,860 --> 00:18:34,920 map into certain physical addresses. 361 00:18:34,920 --> 00:18:37,860 So, for example, suppose this block here 362 00:18:37,860 --> 00:18:41,080 is the set of virtual addresses, the set of physical addresses 363 00:18:41,080 --> 00:18:44,480 that correspond to the virtual addresses in A's page map. 364 00:18:44,480 --> 00:18:46,790 OK, these are the only physical addresses 365 00:18:46,790 --> 00:18:48,040 that A can talk about. 366 00:18:48,040 --> 00:18:51,650 So if we, for example, have a different block of memory 367 00:18:51,650 --> 00:18:55,020 addresses that correspond to the virtual addresses 368 00:18:55,020 --> 00:18:57,330 that B can reference, we can see that there's 369 00:18:57,330 --> 00:19:02,930 no way for module A to be able to reference any of the memory 370 00:19:02,930 --> 00:19:03,690 that B uses. 371 00:19:03,690 --> 00:19:05,290 So we are able to totally separate 372 00:19:05,290 --> 00:19:07,610 the physical memory, pieces of physical memory 373 00:19:07,610 --> 00:19:13,360 that A and B can talk about by using this page map mechanism 374 00:19:13,360 --> 00:19:15,260 that virtual memory gives us. 375 00:19:15,260 --> 00:19:19,120 So, basically what we've done is we've 376 00:19:19,120 --> 00:19:21,510 sort of added this extra layer of indirection, 377 00:19:21,510 --> 00:19:27,200 this virtual memory system, that gets 378 00:19:27,200 --> 00:19:29,410 to map virtual addresses into physical addresses. 379 00:19:32,169 --> 00:19:33,710 So the rest of this lecture is really 380 00:19:33,710 --> 00:19:41,400 going to be details about how we make this work, about how 381 00:19:41,400 --> 00:19:45,920 we actually decide, how we assign this PMAR register based 382 00:19:45,920 --> 00:19:48,550 on which one of the modules is currently executing 383 00:19:48,550 --> 00:19:51,030 about things like what the format of this page map table 384 00:19:51,030 --> 00:19:52,510 is going to look like, OK? 385 00:19:52,510 --> 00:19:54,515 So this is really the key concept. 386 00:19:57,980 --> 00:20:02,790 So what I want to do now is sort of turn 387 00:20:02,790 --> 00:20:06,090 to this second question I asked which is, 388 00:20:06,090 --> 00:20:09,310 how does this page map thing actually work? 389 00:20:09,310 --> 00:20:11,490 How is it actually represented? 390 00:20:11,490 --> 00:20:14,400 So one very simple representation of a page map 391 00:20:14,400 --> 00:20:18,010 might be that it simply is a pointer to, 392 00:20:18,010 --> 00:20:22,220 the page map just says where A's memory begins on the processor, 393 00:20:22,220 --> 00:20:23,140 right? 394 00:20:23,140 --> 00:20:24,300 So it's just one value. 395 00:20:24,300 --> 00:20:26,410 It says A's memory begins at this location 396 00:20:26,410 --> 00:20:29,800 in the physical memory, and all virtual addresses 397 00:20:29,800 --> 00:20:32,590 should be resolved relative to this beginning 398 00:20:32,590 --> 00:20:35,830 location of A's memory. 399 00:20:35,830 --> 00:20:37,650 The problem with that representation 400 00:20:37,650 --> 00:20:40,690 is that it's not very flexible. 401 00:20:40,690 --> 00:20:49,410 So, for example, suppose there's a third module, C, 402 00:20:49,410 --> 00:20:53,090 which is laid out in memory right next So, 403 00:20:53,090 --> 00:20:55,740 its storage is placed right next to A in memory. 404 00:20:55,740 --> 00:20:58,810 And now, suppose that A wants to allocate some additional memory 405 00:20:58,810 --> 00:21:00,240 that it can use. 406 00:21:00,240 --> 00:21:05,700 Now, in order to do that, if the page map is simply 407 00:21:05,700 --> 00:21:08,010 a single pointer to the beginning of A's address space, 408 00:21:08,010 --> 00:21:08,840 we're kind of in trouble. 409 00:21:08,840 --> 00:21:10,506 We can't just add memory onto the bottom 410 00:21:10,506 --> 00:21:13,250 because then we would overlap C. 411 00:21:13,250 --> 00:21:15,010 So we're going to have to move all 412 00:21:15,010 --> 00:21:17,860 of A's memory around in order to be able to make space for this. 413 00:21:17,860 --> 00:21:20,110 OK, so this seems like a little bit problematic simply 414 00:21:20,110 --> 00:21:21,510 have it be a pointer. 415 00:21:21,510 --> 00:21:24,030 The other thing we could do is suppose we could, instead, 416 00:21:24,030 --> 00:21:26,550 have a different option where we could say, 417 00:21:26,550 --> 00:21:31,480 for example, for every virtual address in A's address space, 418 00:21:31,480 --> 00:21:37,640 so for each 32 bit value that A wants to resolve, 419 00:21:37,640 --> 00:21:40,350 there might be an entry in this page map table, right? 420 00:21:40,350 --> 00:21:42,300 So for every 32-bit virtual address, 421 00:21:42,300 --> 00:21:45,517 there would be a corresponding 32-bit physical address. 422 00:21:45,517 --> 00:21:47,350 And there would just be a one-to-one mapping 423 00:21:47,350 --> 00:21:48,391 between all these things. 424 00:21:48,391 --> 00:21:50,690 So, if A could reference a million blocks of memory, 425 00:21:50,690 --> 00:21:54,400 there would be a million entries in this page map table. 426 00:21:54,400 --> 00:21:56,840 So, if you think about this for a minute, that 427 00:21:56,840 --> 00:21:58,340 sounds like kind of a bad idea, too, 428 00:21:58,340 --> 00:22:01,200 because now these tables are totally huge, right, 429 00:22:01,200 --> 00:22:04,920 and in fact they are almost as big as the memory 430 00:22:04,920 --> 00:22:08,010 itself, right, because if I have a million entries, if A can 431 00:22:08,010 --> 00:22:09,670 reference a million blocks, then I'm 432 00:22:09,670 --> 00:22:11,545 going to need a million entries in the table. 433 00:22:11,545 --> 00:22:14,500 So the table becomes just as big as the memory itself. 434 00:22:14,500 --> 00:22:17,230 So we need some in between sort of alternative hybrid 435 00:22:17,230 --> 00:22:19,920 between these two extremes. 436 00:22:19,920 --> 00:22:23,490 And the idea, again, is very simple. 437 00:22:23,490 --> 00:22:25,430 And you saw it in 6.004. 438 00:22:25,430 --> 00:22:29,786 So the idea is to take this 32-bit virtual address. 439 00:22:35,160 --> 00:22:37,152 So suppose this is our 32-bit virtual address. 440 00:22:37,152 --> 00:22:38,610 Now what we're going to do is we're 441 00:22:38,610 --> 00:22:42,280 going to split it up into two pieces, a page 442 00:22:42,280 --> 00:22:47,590 number and an offset. 443 00:22:47,590 --> 00:22:52,970 OK, and we're going to choose some size for these two things. 444 00:22:52,970 --> 00:22:56,720 For now I'll just arbitrarily pick a 20 bit page 445 00:22:56,720 --> 00:22:59,000 number and a 12 bit offset. 446 00:23:03,737 --> 00:23:06,320 OK, so what this is going to do, so now what we're going to do 447 00:23:06,320 --> 00:23:11,500 is instead of storing a single word of memory 448 00:23:11,500 --> 00:23:12,990 at each entry in this table, we're 449 00:23:12,990 --> 00:23:16,020 going to store a page of memory at each entry in this table. 450 00:23:16,020 --> 00:23:31,990 So -- So this table is going to look like a mapping between 451 00:23:31,990 --> 00:23:35,650 a page, and a physical address. 452 00:23:35,650 --> 00:23:40,890 OK, so what a page is, so if the page number is 20 bits long, 453 00:23:40,890 --> 00:23:43,450 then that means that each page is 454 00:23:43,450 --> 00:23:48,120 going to be two to the 12th bits big, which is equal to, say, 455 00:23:48,120 --> 00:23:55,310 4,096 words, OK? 456 00:23:55,310 --> 00:24:00,160 So the idea is that we're going to have two 457 00:24:00,160 --> 00:24:03,160 to the 20th pages within each address space, 458 00:24:03,160 --> 00:24:10,070 and each page is going to map to one of these 4,096 byte blocks, 459 00:24:10,070 --> 00:24:10,580 OK? 460 00:24:10,580 --> 00:24:23,390 So, if we have our memory here this page, say, page one 461 00:24:23,390 --> 00:24:26,130 is going to map into some physical address. 462 00:24:26,130 --> 00:24:30,790 And page two is going to map into some other physical block, 463 00:24:30,790 --> 00:24:37,940 OK, so each one of these things is now 4,096 bytes, each block 464 00:24:37,940 --> 00:24:40,920 here, OK? 465 00:24:40,920 --> 00:24:45,940 And so this, let's just expand this. 466 00:24:45,940 --> 00:24:48,330 So this is now a page. 467 00:24:48,330 --> 00:24:51,624 And this 12 bit offset is going to be used in order 468 00:24:51,624 --> 00:24:53,790 to look up the word that we want to actually look up 469 00:24:53,790 --> 00:24:54,840 in this page. 470 00:24:54,840 --> 00:25:01,790 So, if the virtual address is, say, for example, 471 00:25:01,790 --> 00:25:06,260 page one offset zero, what that's going to do 472 00:25:06,260 --> 00:25:09,490 is we're going to look up in the page map. 473 00:25:09,490 --> 00:25:13,120 We're going to find the page number that corresponds to, 474 00:25:13,120 --> 00:25:14,734 we're going to find page number one. 475 00:25:14,734 --> 00:25:17,400 We're going to find the physical address that corresponds to it, 476 00:25:17,400 --> 00:25:22,170 we're going to go down here, and look at this block of memory. 477 00:25:22,170 --> 00:25:24,850 And then within this 4,096 block memory, 478 00:25:24,850 --> 00:25:28,990 we're going to take the address zero, the first word 479 00:25:28,990 --> 00:25:30,690 within that thing, OK? 480 00:25:30,690 --> 00:25:35,026 So now the size of these page tables is much smaller, right? 481 00:25:35,026 --> 00:25:36,650 They're no longer two to the 30th bits. 482 00:25:36,650 --> 00:25:38,400 Now they're two to the 20th bits, 483 00:25:38,400 --> 00:25:43,930 which is some small number of megabytes big. 484 00:25:43,930 --> 00:25:47,370 But we've avoided this problem that we have before. 485 00:25:47,370 --> 00:25:52,210 We have some flexibility in terms of how each page maps 486 00:25:52,210 --> 00:25:53,340 into the physical memory. 487 00:25:53,340 --> 00:25:59,070 So I can allocate a third page to a process. 488 00:25:59,070 --> 00:26:02,630 And I can map that into any 4,096 byte 489 00:26:02,630 --> 00:26:04,657 block that's in memory that's currently unused. 490 00:26:04,657 --> 00:26:05,740 OK, so I have flexibility. 491 00:26:05,740 --> 00:26:08,000 I don't have this problem, say, where A and C 492 00:26:08,000 --> 00:26:15,960 were colliding with each other. 493 00:26:19,170 --> 00:26:25,100 OK, so this is sort of the outline 494 00:26:25,100 --> 00:26:26,580 of how virtual memory works. 495 00:26:26,580 --> 00:26:28,830 But what I haven't yet described to you 496 00:26:28,830 --> 00:26:31,280 is how it is that we can actually 497 00:26:31,280 --> 00:26:36,170 go about creating these different address spaces that 498 00:26:36,170 --> 00:26:38,130 are allocated to the different modules, 499 00:26:38,130 --> 00:26:41,150 and how we can switch between different modules using 500 00:26:41,150 --> 00:26:43,110 this PMAR register. 501 00:26:43,110 --> 00:26:45,670 So I've sort of described this as, 502 00:26:45,670 --> 00:26:48,700 suppose these data structures exist, 503 00:26:48,700 --> 00:26:50,004 now here's how we can use them. 504 00:26:50,004 --> 00:26:52,170 But I haven't told you how these data structures all 505 00:26:52,170 --> 00:26:55,550 get together, and created, and set up to begin with. 506 00:26:55,550 --> 00:26:57,360 And I hinted at this in the beginning. 507 00:26:57,360 --> 00:26:59,850 But in order to do this, what we're going to need 508 00:26:59,850 --> 00:27:04,350 is some sort of a special supervisory module that's 509 00:27:04,350 --> 00:27:07,260 able to look at the page maps for all 510 00:27:07,260 --> 00:27:10,400 of these different, that's able to create new page maps 511 00:27:10,400 --> 00:27:11,830 and look at the page maps for all 512 00:27:11,830 --> 00:27:14,262 of the different modules that are within the system. 513 00:27:14,262 --> 00:27:15,720 And the supervisory module is going 514 00:27:15,720 --> 00:27:18,780 to be able to do things like add new memory to a page map 515 00:27:18,780 --> 00:27:24,720 or be able to destroy, delete a particular module 516 00:27:24,720 --> 00:27:25,940 and its associated page map. 517 00:27:25,940 --> 00:27:27,780 So we need some sort of a thing that can 518 00:27:27,780 --> 00:27:30,100 manage all this infrastructure. 519 00:27:30,100 --> 00:27:34,720 So, this supervisory module -- 520 00:27:34,720 --> 00:27:39,700 -- is called the kernel. 521 00:27:39,700 --> 00:27:44,354 OK, and the kernel is really, it's 522 00:27:44,354 --> 00:27:45,770 going to be the thing that's going 523 00:27:45,770 --> 00:27:48,660 to be in charge of managing all these data structures for us. 524 00:27:48,660 --> 00:28:02,890 So -- So here's our microprocessor with its PMAR 525 00:28:02,890 --> 00:28:03,780 register on it. 526 00:28:03,780 --> 00:28:05,280 And, what we're going to do is we're 527 00:28:05,280 --> 00:28:08,880 going to extend the microprocessor with one 528 00:28:08,880 --> 00:28:15,840 additional piece of hardware, and this is the user kernel 529 00:28:15,840 --> 00:28:17,330 bit, OK? 530 00:28:17,330 --> 00:28:21,310 So, this is just a bit specifies whether we are currently 531 00:28:21,310 --> 00:28:25,050 running a user module that is just a program that's 532 00:28:25,050 --> 00:28:27,860 running on your computer, or whether the kernel is currently 533 00:28:27,860 --> 00:28:29,386 executing, OK? 534 00:28:29,386 --> 00:28:30,760 And the idea with this kernel bit 535 00:28:30,760 --> 00:28:35,200 is that when this kernel bit is set, the code that is running 536 00:28:35,200 --> 00:28:36,700 is going to have special privileges. 537 00:28:36,700 --> 00:28:39,570 It's going to be able to manipulate 538 00:28:39,570 --> 00:28:43,090 special things about the hardware and the processor. 539 00:28:43,090 --> 00:28:45,740 And in particular, we're going to have 540 00:28:45,740 --> 00:28:55,800 a rule that says that only the kernel can change the PMAR, OK? 541 00:29:00,870 --> 00:29:03,880 So the PMAR is the thing that specifies which process 542 00:29:03,880 --> 00:29:07,480 is currently running, and selects which address space we 543 00:29:07,480 --> 00:29:09,310 want to be currently using. 544 00:29:09,310 --> 00:29:12,020 And what we're going to use is we're going to use, 545 00:29:12,020 --> 00:29:15,240 so what we're going to do is have the kernel 546 00:29:15,240 --> 00:29:17,560 be the thing that's in charge of manipulating 547 00:29:17,560 --> 00:29:20,290 the value of this PMAR register to select which thing 548 00:29:20,290 --> 00:29:22,610 is currently being executed. 549 00:29:22,610 --> 00:29:25,120 And we want to make it so that only the kernel can do this 550 00:29:25,120 --> 00:29:27,180 because if we, for example, allowed 551 00:29:27,180 --> 00:29:30,410 one of these other programs to be able to manipulate the PMAR, 552 00:29:30,410 --> 00:29:32,265 right, then that other program might 553 00:29:32,265 --> 00:29:34,390 be able to do something unpleasant to the computer, 554 00:29:34,390 --> 00:29:34,890 right? 555 00:29:34,890 --> 00:29:38,917 It changes the PMAR to point at some other program's memory. 556 00:29:38,917 --> 00:29:41,250 And now, suddenly all the memory addresses in the system 557 00:29:41,250 --> 00:29:44,106 are going to be resolved. 558 00:29:44,106 --> 00:29:45,480 Then suddenly, we are going to be 559 00:29:45,480 --> 00:29:47,740 sort of resolving memory addresses relative 560 00:29:47,740 --> 00:29:50,257 to some other module's page map. 561 00:29:50,257 --> 00:29:52,090 And that's likely to be a problematic thing. 562 00:29:52,090 --> 00:29:54,631 It's likely to cause that other module to crash, for example, 563 00:29:54,631 --> 00:29:58,199 because the processor is set up to be executing instructions 564 00:29:58,199 --> 00:29:59,240 from the current program. 565 00:29:59,240 --> 00:30:02,200 So we want to make sure that only something this kernel 566 00:30:02,200 --> 00:30:03,230 can change the PMAR. 567 00:30:03,230 --> 00:30:06,420 And this kernel is going to be this sort of supervisory module 568 00:30:06,420 --> 00:30:07,970 that all of the other modules are 569 00:30:07,970 --> 00:30:10,136 going to have to trust to kind of do the right thing 570 00:30:10,136 --> 00:30:13,160 and manage the computer's execution for you. 571 00:30:13,160 --> 00:30:17,130 And this kernel, except for this one difference 572 00:30:17,130 --> 00:30:18,710 that a kernel can change the PMAR, 573 00:30:18,710 --> 00:30:20,760 the kernel is, in all other respects, 574 00:30:20,760 --> 00:30:23,310 essentially just going to be another module that's 575 00:30:23,310 --> 00:30:24,900 running in the computer system. 576 00:30:24,900 --> 00:30:28,020 So in particular, the kernel is also 577 00:30:28,020 --> 00:30:30,990 going to have one of these 32-bit virtual address 578 00:30:30,990 --> 00:30:33,060 spaces associated with it, OK? 579 00:30:36,350 --> 00:30:37,850 But, what we're going to do is we're 580 00:30:37,850 --> 00:30:41,590 going to say that the kernel within its address space 581 00:30:41,590 --> 00:30:47,330 has all of the page maps of all the other programs that 582 00:30:47,330 --> 00:30:50,270 are currently running on the system mapped into its address 583 00:30:50,270 --> 00:30:50,950 space. 584 00:30:50,950 --> 00:30:52,570 OK, so this is a little bit tricky 585 00:30:52,570 --> 00:30:57,270 because I presented this as though A and B referenced 586 00:30:57,270 --> 00:30:59,255 totally different pieces of memory. 587 00:30:59,255 --> 00:31:00,880 So, I sort of have told you so far only 588 00:31:00,880 --> 00:31:02,910 about modules that are referencing 589 00:31:02,910 --> 00:31:04,360 disjoint sets of memory. 590 00:31:04,360 --> 00:31:07,150 But in fact these page maps, right, they just 591 00:31:07,150 --> 00:31:09,400 reside in memory somewhere. 592 00:31:09,400 --> 00:31:13,500 And it's just fine if I, for example, 593 00:31:13,500 --> 00:31:18,570 have multiple modules that are able to reference, that 594 00:31:18,570 --> 00:31:21,480 have the same physical addresses mapped 595 00:31:21,480 --> 00:31:23,690 into their virtual address space. 596 00:31:23,690 --> 00:31:25,990 So it's very likely that I might want 597 00:31:25,990 --> 00:31:28,080 to have something down here at the bottom 598 00:31:28,080 --> 00:31:30,760 that both A and B can access. 599 00:31:30,760 --> 00:31:33,020 So, this might be stuff that's shared between A and B. 600 00:31:33,020 --> 00:31:36,030 I can map that into both A and B's memory. 601 00:31:36,030 --> 00:31:38,510 In the same way, what I'm going to do is I'm going to map 602 00:31:38,510 --> 00:31:40,810 these page maps, which are also stored in memory 603 00:31:40,810 --> 00:31:43,940 into all of the page maps into the kernel's address space. 604 00:31:43,940 --> 00:31:47,050 So the kernel is going to be able to reference the address 605 00:31:47,050 --> 00:31:49,600 spaces of all the modules. 606 00:31:49,600 --> 00:31:51,470 And the kernel is also going to keep 607 00:31:51,470 --> 00:31:56,390 a little table of all the page maps for all of the currently 608 00:31:56,390 --> 00:31:58,250 running programs on the system. 609 00:31:58,250 --> 00:32:03,394 So these are, for example, page maps for A and B. 610 00:32:03,394 --> 00:32:04,810 And this is a list of all the maps 611 00:32:04,810 --> 00:32:07,030 that are currently running in the system. 612 00:32:07,030 --> 00:32:10,900 So what's going to happen, now what 613 00:32:10,900 --> 00:32:14,500 can happen is because the kernel is allowed to change the PMAR, 614 00:32:14,500 --> 00:32:16,940 and because it knows about the location of all 615 00:32:16,940 --> 00:32:19,940 the other address spaces that are in the system, when it 616 00:32:19,940 --> 00:32:22,560 wants to start running one of these programs that's running 617 00:32:22,560 --> 00:32:24,290 in the system, it can change the value 618 00:32:24,290 --> 00:32:29,520 of the PMAR to be sort of the PMAR for A or the PMAR to B. 619 00:32:29,520 --> 00:32:31,740 And, it can manipulate all the values 620 00:32:31,740 --> 00:32:33,500 of the registers in the system so 621 00:32:33,500 --> 00:32:36,550 that you can start executing code for one of these. 622 00:32:36,550 --> 00:32:38,730 You can switch between one of these two modules. 623 00:32:38,730 --> 00:32:41,740 So the actual process of switching between which module 624 00:32:41,740 --> 00:32:42,737 is currently running. 625 00:32:42,737 --> 00:32:44,570 We're going to focus on that more next time. 626 00:32:44,570 --> 00:32:45,930 So, don't worry too much if you don't understand 627 00:32:45,930 --> 00:32:48,660 the details of how you actually switch from executing 628 00:32:48,660 --> 00:32:50,200 one program to another program. 629 00:32:50,200 --> 00:32:52,070 But, you can see that the kernel can 630 00:32:52,070 --> 00:32:56,690 switch which address space is currently 631 00:32:56,690 --> 00:32:58,360 active by simply manipulating the value 632 00:32:58,360 --> 00:33:00,110 of this PMAR register. 633 00:33:00,110 --> 00:33:02,040 Furthermore, the kernel can do things 634 00:33:02,040 --> 00:33:04,550 like it can create a new map. 635 00:33:04,550 --> 00:33:05,940 So the kernel can simply allocate 636 00:33:05,940 --> 00:33:07,830 one of these new tables, and it can set up 637 00:33:07,830 --> 00:33:10,870 a mapping from a set of virtual addresses 638 00:33:10,870 --> 00:33:12,800 to a set of physical addresses so that you 639 00:33:12,800 --> 00:33:15,410 can create a new address space that a new module can 640 00:33:15,410 --> 00:33:17,120 start executing within. 641 00:33:17,120 --> 00:33:20,024 Similarly, the kernel can do things like allocate new memory 642 00:33:20,024 --> 00:33:21,190 into one of these addresses. 643 00:33:25,020 --> 00:33:27,830 So it can map some additional virtual addresses 644 00:33:27,830 --> 00:33:31,830 into real physical memory so that when one of these modules, 645 00:33:31,830 --> 00:33:34,700 say for example, requests additional memory to execute, 646 00:33:34,700 --> 00:33:39,050 the kernel can add that memory, add an entry into the table 647 00:33:39,050 --> 00:33:41,820 so that that new memory that the program has requested actually 648 00:33:41,820 --> 00:33:43,410 maps into a valid, physical address. 649 00:33:47,770 --> 00:33:53,020 OK, so the question, of course, then is, 650 00:33:53,020 --> 00:33:55,650 so you can see the value of having this kernel module. 651 00:33:55,650 --> 00:33:58,720 But the question is, how do we communicate 652 00:33:58,720 --> 00:34:02,470 between these modules that are running these user level 653 00:34:02,470 --> 00:34:07,270 modules that are running, and the kernel module that the user 654 00:34:07,270 --> 00:34:10,745 modules need to invoke, for example, request new memory. 655 00:34:10,745 --> 00:34:12,370 So the way that we are going to do this 656 00:34:12,370 --> 00:34:17,090 is just like we've done everything else in this lecture 657 00:34:17,090 --> 00:34:19,780 so far: by adding a little bit of extra, 658 00:34:19,780 --> 00:34:21,880 by changing the processor just a little bit. 659 00:34:21,880 --> 00:34:24,113 So in particular, what we're going to do -- 660 00:34:38,139 --> 00:34:41,199 What we're going to do is to is to add this notion 661 00:34:41,199 --> 00:34:42,449 of a supervisor call. 662 00:34:48,820 --> 00:34:50,409 Call that SVC. 663 00:34:50,409 --> 00:34:53,300 So a supervisor call is simply a special instruction 664 00:34:53,300 --> 00:34:57,170 that is on the processor that invokes the kernel. 665 00:34:57,170 --> 00:35:00,100 So when the supervisor call instruction gets executed, 666 00:35:00,100 --> 00:35:05,010 it's going to set up the state of these PMAR and user kernel 667 00:35:05,010 --> 00:35:10,000 bit instructions so that the kernel can begin executing. 668 00:35:10,000 --> 00:35:13,370 The supervisor call is also going. 669 00:35:13,370 --> 00:35:16,167 But when the supervisor call instruction is executed, 670 00:35:16,167 --> 00:35:18,250 we need to be a little bit careful because we also 671 00:35:18,250 --> 00:35:21,500 need to decide somehow which code within the kernel 672 00:35:21,500 --> 00:35:24,520 we want to begin executing when the supervisor call instruction 673 00:35:24,520 --> 00:35:25,400 gets executed, right? 674 00:35:28,090 --> 00:35:29,950 So what the supervisor call instruction does 675 00:35:29,950 --> 00:35:38,980 is it accepts a parameter which is the name of a so-called gate 676 00:35:38,980 --> 00:35:39,760 function. 677 00:35:39,760 --> 00:35:43,770 So a gate function is a well defined entry point 678 00:35:43,770 --> 00:35:50,276 into another module that can be used to invoke a piece of code 679 00:35:50,276 --> 00:35:51,150 in that other module. 680 00:35:51,150 --> 00:35:52,950 So, for example, the kernel is going 681 00:35:52,950 --> 00:35:55,380 to have a particular gate function which 682 00:35:55,380 --> 00:35:59,020 corresponds to allocating additional memory for a module. 683 00:35:59,020 --> 00:36:05,290 So when a user program executes an instruction, supervisor 684 00:36:05,290 --> 00:36:08,510 call, to gate say for example, this 685 00:36:08,510 --> 00:36:15,820 might be some memory allocation code, 686 00:36:15,820 --> 00:36:18,330 this special instruction is going 687 00:36:18,330 --> 00:36:21,320 to do the following things. 688 00:36:21,320 --> 00:36:28,680 First it's going to set the user kernel bit to kernel. 689 00:36:28,680 --> 00:36:33,760 Then it's going to set the value of the PMAR register 690 00:36:33,760 --> 00:36:38,360 to the kernel page map. 691 00:36:41,840 --> 00:36:45,550 It's going to save the program counter for the currently 692 00:36:45,550 --> 00:36:47,570 executing instruction, and then it's 693 00:36:47,570 --> 00:36:53,010 going to set the program counter to be the address of the gate 694 00:36:53,010 --> 00:36:55,370 function, OK? 695 00:36:55,370 --> 00:36:59,150 So we've introduced a special new processor instruction 696 00:36:59,150 --> 00:37:03,290 that takes these steps. 697 00:37:03,290 --> 00:37:05,470 So when this instruction is executed, 698 00:37:05,470 --> 00:37:10,960 we essentially switch into executing within the kernel's 699 00:37:10,960 --> 00:37:12,160 address space. 700 00:37:12,160 --> 00:37:15,540 OK, and this kernel, and we begin 701 00:37:15,540 --> 00:37:17,410 executing within the kernel address space 702 00:37:17,410 --> 00:37:21,590 at the address of this gate function within the kernel's 703 00:37:21,590 --> 00:37:23,280 address space. 704 00:37:23,280 --> 00:37:27,060 OK, so what this has done is this 705 00:37:27,060 --> 00:37:30,340 is a well defined entry point. 706 00:37:30,340 --> 00:37:34,050 If the program tries to execute this instruction 707 00:37:34,050 --> 00:37:36,780 with the name of a gate function that doesn't exist, 708 00:37:36,780 --> 00:37:38,680 then that program is going to get an error 709 00:37:38,680 --> 00:37:39,721 when it tries to do that. 710 00:37:39,721 --> 00:37:42,386 So the program can only name gate functions 711 00:37:42,386 --> 00:37:44,010 that actually correspond to real things 712 00:37:44,010 --> 00:37:48,400 that the operating system can do, that the kernel can do. 713 00:37:48,400 --> 00:37:50,790 And so, the kernel is then going to be invoked and take 714 00:37:50,790 --> 00:37:54,700 that action that was requested of it. 715 00:37:54,700 --> 00:37:57,930 On return, essentially, so when the kernel 716 00:37:57,930 --> 00:37:59,540 finishes executing this process, when 717 00:37:59,540 --> 00:38:03,130 it finishes executing this, say, memory allocation instruction, 718 00:38:03,130 --> 00:38:04,780 we are just going to reverse this step. 719 00:38:04,780 --> 00:38:07,760 So we are just going to set the PMAR 720 00:38:07,760 --> 00:38:10,850 to be, we're going to set the PMAR back 721 00:38:10,850 --> 00:38:13,170 to the user's program. 722 00:38:13,170 --> 00:38:16,190 We are going to set the user kernel bit back into user mode. 723 00:38:16,190 --> 00:38:18,630 And then we're going to jump back to the saved return 724 00:38:18,630 --> 00:38:21,250 address that we saved here, the saved program 725 00:38:21,250 --> 00:38:24,270 counter address from the user's program. 726 00:38:24,270 --> 00:38:27,200 So when the program finishes, when the kernel finishes 727 00:38:27,200 --> 00:38:29,340 executing this service instruction, 728 00:38:29,340 --> 00:38:31,000 the control will just return back 729 00:38:31,000 --> 00:38:33,360 to the program in the place where the program 730 00:38:33,360 --> 00:38:38,180 needs to begin executing. 731 00:38:38,180 --> 00:38:43,640 OK, so now using this gate, so using this notion of, 732 00:38:43,640 --> 00:38:48,600 so what we've seen so far now is the ability for the, 733 00:38:48,600 --> 00:38:51,960 we can use the virtual memory abstraction 734 00:38:51,960 --> 00:38:55,190 in order to protect the memory references of two modules 735 00:38:55,190 --> 00:38:56,020 from each other. 736 00:38:56,020 --> 00:38:58,270 And we see when we have this notion of the kernel that 737 00:38:58,270 --> 00:39:00,890 can be used to, for example, that 738 00:39:00,890 --> 00:39:04,270 can be used to manage these address spaces to allocate 739 00:39:04,270 --> 00:39:07,200 new memory to these address spaces, and in general, 740 00:39:07,200 --> 00:39:12,210 to sort of manage these address spaces. 741 00:39:12,210 --> 00:39:16,900 So this kernel is also going to allow 742 00:39:16,900 --> 00:39:22,350 us to do exactly what we set out trying to do, 743 00:39:22,350 --> 00:39:31,360 which is to act as the so-called trusted intermediary between, 744 00:39:31,360 --> 00:39:33,680 say for example, a client and a server running 745 00:39:33,680 --> 00:39:34,570 on the same machine. 746 00:39:40,780 --> 00:39:44,580 OK, so I trust that intermediary is just a piece of code. 747 00:39:44,580 --> 00:39:46,884 So suppose we have a client and a server, right, 748 00:39:46,884 --> 00:39:48,550 and these are two pieces of code written 749 00:39:48,550 --> 00:39:50,060 by two different developers. 750 00:39:50,060 --> 00:39:51,900 Maybe the two developers don't necessarily 751 00:39:51,900 --> 00:39:53,390 trust that the other developer has written 752 00:39:53,390 --> 00:39:55,890 a piece of code that's 100% foolproof because it doesn't 753 00:39:55,890 --> 00:39:56,550 have any bugs. 754 00:39:56,550 --> 00:39:59,312 But both of those developers may be 755 00:39:59,312 --> 00:40:00,770 willing to say that they will trust 756 00:40:00,770 --> 00:40:03,507 that the kernel is properly written 757 00:40:03,507 --> 00:40:04,840 and doesn't have any bugs in it. 758 00:40:04,840 --> 00:40:06,240 And so they are willing to allow the kernel 759 00:40:06,240 --> 00:40:08,030 to sit in between those two programs 760 00:40:08,030 --> 00:40:13,530 and make sure that neither of them 761 00:40:13,530 --> 00:40:16,310 has any bad interactions with each other. 762 00:40:16,310 --> 00:40:20,000 So let's see how we can use this kernel, the kernel combined 763 00:40:20,000 --> 00:40:22,210 with virtual memory in order to be able to do this. 764 00:40:22,210 --> 00:40:26,720 So suppose this is our kernel. 765 00:40:30,440 --> 00:40:33,580 So the idea is that this kernel running has, 766 00:40:33,580 --> 00:40:37,800 so suppose we have two processes A and B 767 00:40:37,800 --> 00:40:40,472 that want to communicate with each other in some way. 768 00:40:40,472 --> 00:40:42,930 And, we already said that we don't want these two processes 769 00:40:42,930 --> 00:40:45,660 to be able to directly reference into each other's memory 770 00:40:45,660 --> 00:40:48,240 because that makes them dependent on each other. 771 00:40:48,240 --> 00:40:50,020 It means that if there's a bug in A, 772 00:40:50,020 --> 00:40:53,005 that A can overwrite some memory in B's address space 773 00:40:53,005 --> 00:40:53,880 and cause B to crash. 774 00:40:53,880 --> 00:40:55,340 So, that's a bad thing. 775 00:40:55,340 --> 00:40:58,270 So instead, what we are going to do is we're going to create, 776 00:40:58,270 --> 00:41:00,490 well, one thing we can do is to create 777 00:41:00,490 --> 00:41:03,530 a special set of these supervisor calls 778 00:41:03,530 --> 00:41:06,310 that these two modules can use to interact with each other. 779 00:41:06,310 --> 00:41:10,830 So in particular, we might within the kernel 780 00:41:10,830 --> 00:41:14,500 maintain a queue of messages that these two programs are 781 00:41:14,500 --> 00:41:16,760 exchanging with each other, a list of messages 782 00:41:16,760 --> 00:41:17,920 that they're exchanging. 783 00:41:17,920 --> 00:41:21,590 And then, suppose A is, we're going to call this guy, 784 00:41:21,590 --> 00:41:23,190 A is a producer. 785 00:41:23,190 --> 00:41:24,630 He's creating messages. 786 00:41:24,630 --> 00:41:25,585 And B is a consumer. 787 00:41:28,180 --> 00:41:32,760 A can call some function like Put which will -- 788 00:41:32,760 --> 00:41:36,610 supervisor call like Put -- which will cause a data item 789 00:41:36,610 --> 00:41:38,300 to be put on this queue. 790 00:41:38,300 --> 00:41:42,220 And then sometime later, B can call this supervisor call Get, 791 00:41:42,220 --> 00:41:45,226 and pull this value out of the queue, OK? 792 00:41:45,226 --> 00:41:47,100 So in this way, the producer and the consumer 793 00:41:47,100 --> 00:41:48,100 can interact with each other. 794 00:41:48,100 --> 00:41:49,740 They can exchange data with each other 795 00:41:49,740 --> 00:41:53,242 and because we have this gate interface, 796 00:41:53,242 --> 00:41:55,200 this well-defined gate interface with these Put 797 00:41:55,200 --> 00:41:58,200 and Get calls being invoked by the kernel, 798 00:41:58,200 --> 00:42:00,510 the kernel can be very careful, just 799 00:42:00,510 --> 00:42:02,860 like in the case of the client and server running 800 00:42:02,860 --> 00:42:04,100 on two different machines. 801 00:42:04,100 --> 00:42:07,350 In this case, the kernel can carefully verify that these put 802 00:42:07,350 --> 00:42:11,200 and get commands that these two different modules are calling 803 00:42:11,200 --> 00:42:14,970 actually are correctly formed, that the parameters are valid, 804 00:42:14,970 --> 00:42:17,820 that they're referring to valid locations in memory. 805 00:42:17,820 --> 00:42:20,570 And therefore, the kernel can sort of 806 00:42:20,570 --> 00:42:23,050 ensure that these two modules don't 807 00:42:23,050 --> 00:42:24,450 do malicious things to each other 808 00:42:24,450 --> 00:42:27,010 or cause each other to break. 809 00:42:27,010 --> 00:42:29,970 So this is an example here of something 810 00:42:29,970 --> 00:42:33,440 that's like an inter-process communication. 811 00:42:33,440 --> 00:42:35,931 So you saw, for example, you've seen 812 00:42:35,931 --> 00:42:37,680 an instance of inter-process communication 813 00:42:37,680 --> 00:42:39,260 when he studied the UNIX paper. 814 00:42:39,260 --> 00:42:41,259 We talked about pipes, and a pipe abstraction, 815 00:42:41,259 --> 00:42:42,050 and how that works. 816 00:42:42,050 --> 00:42:43,560 Well, pipes are sort of something 817 00:42:43,560 --> 00:42:48,100 that's implemented by the kernel in UNIX 818 00:42:48,100 --> 00:42:52,000 as a way for two programs to exchange data with each other. 819 00:42:52,000 --> 00:42:55,120 And, there's lots of these kinds of services 820 00:42:55,120 --> 00:42:57,550 that our people tend to push into the kernel 821 00:42:57,550 --> 00:43:00,610 that the kernel provides to the other applications, the modules 822 00:43:00,610 --> 00:43:02,490 that are running, so that these modules can, 823 00:43:02,490 --> 00:43:04,980 for example, interact with hardware or interact 824 00:43:04,980 --> 00:43:05,840 with each other. 825 00:43:05,840 --> 00:43:07,850 So commonly within a kernel, you'd 826 00:43:07,850 --> 00:43:12,320 find things like a file system, an interface to the network, 827 00:43:12,320 --> 00:43:15,800 and you might, for example, find things like an interface 828 00:43:15,800 --> 00:43:19,070 to the graphics hardware. 829 00:43:19,070 --> 00:43:22,010 OK, there is some sort of -- 830 00:43:22,010 --> 00:43:24,570 so if you look at what's actually within a kernel, 831 00:43:24,570 --> 00:43:26,140 there is a huge amount of code that's 832 00:43:26,140 --> 00:43:27,181 going into these kernels. 833 00:43:27,181 --> 00:43:29,930 So I think we talked earlier about how the Linux operating 834 00:43:29,930 --> 00:43:32,000 system is many millions of lines of code. 835 00:43:32,000 --> 00:43:33,720 If you go look at the Linux kernel, 836 00:43:33,720 --> 00:43:37,800 the Linux kernel is probably today 837 00:43:37,800 --> 00:43:41,830 on the order of about 5 million lines of code, most of which, 838 00:43:41,830 --> 00:43:43,500 say two thirds of which, is related 839 00:43:43,500 --> 00:43:45,290 to these so-called device drivers that 840 00:43:45,290 --> 00:43:47,940 manage this low-level hardware. 841 00:43:47,940 --> 00:43:50,149 So this kernel has gotten quite large. 842 00:43:50,149 --> 00:43:52,440 And one of the side effects of the kernel getting large 843 00:43:52,440 --> 00:43:54,690 is that maybe it's harder to trust it, right? 844 00:43:54,690 --> 00:43:56,524 May be you sort of have less confidence 845 00:43:56,524 --> 00:43:58,690 that all the code in the kernel is actually correct. 846 00:43:58,690 --> 00:44:01,148 And you can imagine that if you don't trust the kernel then 847 00:44:01,148 --> 00:44:06,050 the computer is not going to be as stable as you like to be. 848 00:44:06,050 --> 00:44:09,777 And this is one argument for why Windows crashes all the time is 849 00:44:09,777 --> 00:44:11,360 because it has all these drivers in it 850 00:44:11,360 --> 00:44:15,221 and these drivers aren't necessarily all 851 00:44:15,221 --> 00:44:15,970 perfectly written. 852 00:44:15,970 --> 00:44:17,800 There are tens of millions of lines of code in Windows, 853 00:44:17,800 --> 00:44:18,910 and some of them crash some of the time, 854 00:44:18,910 --> 00:44:21,070 and that causes the whole computer to come down. 855 00:44:21,070 --> 00:44:23,361 So there's a tension in the operating systems community 856 00:44:23,361 --> 00:44:26,160 about whether you should execute these things, you should keep 857 00:44:26,160 --> 00:44:28,035 these things look the file system or graphics 858 00:44:28,035 --> 00:44:30,500 system within the kernel or whether you should move them 859 00:44:30,500 --> 00:44:35,930 outside as separate services, which can be invoked 860 00:44:35,930 --> 00:44:38,270 in the same way, for example, that A and B interact 861 00:44:38,270 --> 00:44:41,150 with each other, by having some data structure that's stored 862 00:44:41,150 --> 00:44:44,010 within the kernel that buffers the requests between, say, 863 00:44:44,010 --> 00:44:49,650 the service and this, say, for example the graphics service 864 00:44:49,650 --> 00:44:55,060 and the users' programs that want to interact with it. 865 00:44:55,060 --> 00:44:58,210 OK, so that's basically it for today. 866 00:44:58,210 --> 00:45:01,310 What I've shown you is, well, actually we 867 00:45:01,310 --> 00:45:02,310 have a few more minutes. 868 00:45:02,310 --> 00:45:03,599 Sorry. 869 00:45:03,599 --> 00:45:05,640 [LAUGHTER] I know you're all getting up to leave, 870 00:45:05,640 --> 00:45:12,560 but so, OK, I just want to quickly touch 871 00:45:12,560 --> 00:45:20,620 on one last topic which is that, so, what I've 872 00:45:20,620 --> 00:45:24,310 shown you so far is how we can use 873 00:45:24,310 --> 00:45:33,260 the notion of virtual memory in order to protect the data, 874 00:45:33,260 --> 00:45:35,065 protect two programs from each other 875 00:45:35,065 --> 00:45:36,690 so that they can't necessarily interact 876 00:45:36,690 --> 00:45:37,760 with each other's data. 877 00:45:37,760 --> 00:45:40,051 But there is some situations in which we might actually 878 00:45:40,051 --> 00:45:41,997 want to have two programs able to share 879 00:45:41,997 --> 00:45:43,080 some data with each other. 880 00:45:43,080 --> 00:45:44,621 So I don't know if you guys remember, 881 00:45:44,621 --> 00:45:46,180 but when Hari was lecturing earlier, 882 00:45:46,180 --> 00:45:48,560 he talked about how there are libraries 883 00:45:48,560 --> 00:45:50,820 that get linked into programs. 884 00:45:50,820 --> 00:45:52,980 And one of the common ways that libraries 885 00:45:52,980 --> 00:45:57,170 are structured these days is a so-called shared library. 886 00:45:57,170 --> 00:46:00,020 So a shared library is something that 887 00:46:00,020 --> 00:46:04,220 is only stored in one location in physical memory. 888 00:46:04,220 --> 00:46:05,790 But multiple different modules that 889 00:46:05,790 --> 00:46:09,290 are executing on that system can call functions 890 00:46:09,290 --> 00:46:11,280 within that shared library. 891 00:46:11,280 --> 00:46:13,520 So in order to make this work, right, we 892 00:46:13,520 --> 00:46:17,425 need to have mapped the memory for the shared library that 893 00:46:17,425 --> 00:46:19,550 has all the functions that these other modules want 894 00:46:19,550 --> 00:46:23,180 to call into the address spaces for both of these modules 895 00:46:23,180 --> 00:46:25,780 so that they can actually execute the code that's there. 896 00:46:25,780 --> 00:46:28,920 So the virtual memory system makes it very trivial 897 00:46:28,920 --> 00:46:29,880 to do this. 898 00:46:29,880 --> 00:46:34,530 So suppose I have my address space for some function, A, 899 00:46:34,530 --> 00:46:39,290 and I have my address space for some function, B. 900 00:46:39,290 --> 00:46:42,650 And suppose that function A references library 901 00:46:42,650 --> 00:46:49,020 one and module B references libraries one and two. 902 00:46:49,020 --> 00:46:56,610 OK, so using the virtual memory system, suppose we have, 903 00:46:56,610 --> 00:46:59,940 so this is our physical memory. 904 00:46:59,940 --> 00:47:04,440 So, suppose that module A, program A, is loaded. 905 00:47:04,440 --> 00:47:09,110 And when it's loaded, the program 906 00:47:09,110 --> 00:47:14,780 that runs other programs, the loader in this case, 907 00:47:14,780 --> 00:47:18,410 is going to load this shared library, one, 908 00:47:18,410 --> 00:47:21,070 as it loads for program A. 909 00:47:21,070 --> 00:47:23,890 So, it's going to first load the code for A, 910 00:47:23,890 --> 00:47:26,870 and then it's going to load the code for one. 911 00:47:26,870 --> 00:47:30,350 And, these things are going to be sitting in memory somewhere. 912 00:47:30,350 --> 00:47:35,607 So, within A's address space we're 913 00:47:35,607 --> 00:47:37,690 going to have the code for A is going to be mapped 914 00:47:37,690 --> 00:47:39,840 and the code for one is going to be mapped. 915 00:47:39,840 --> 00:47:43,240 Now, when B executes, right, what we want to avoid, 916 00:47:43,240 --> 00:47:45,440 so the whole purpose of shared libraries 917 00:47:45,440 --> 00:47:48,910 is to make it so that when two programs are running 918 00:47:48,910 --> 00:47:50,420 and they both use the same library 919 00:47:50,420 --> 00:47:52,253 there aren't two copies of that library that 920 00:47:52,253 --> 00:47:54,590 are in memory using twice as much of the memory up, 921 00:47:54,590 --> 00:47:58,750 right, because there's all these libraries that all computer 922 00:47:58,750 --> 00:48:00,440 programs share. 923 00:48:00,440 --> 00:48:04,776 For example, on Linux there's the libc library 924 00:48:04,776 --> 00:48:06,650 that implements all of the standard functions 925 00:48:06,650 --> 00:48:11,494 that people use in C programs. 926 00:48:11,494 --> 00:48:13,910 If there's 50 programs written in C on your Linux machine, 927 00:48:13,910 --> 00:48:16,576 you don't want to have 50 copies of this libc library in memory. 928 00:48:16,576 --> 00:48:19,580 You want to have just one. 929 00:48:19,580 --> 00:48:22,720 So what we want is that when module B gets loaded, 930 00:48:22,720 --> 00:48:26,440 we want it to map this code that's already 931 00:48:26,440 --> 00:48:29,280 been mapped into the address space of A into its memory 932 00:48:29,280 --> 00:48:30,894 as well, OK? 933 00:48:30,894 --> 00:48:32,560 And then, of course, we're going to have 934 00:48:32,560 --> 00:48:38,660 to load additional memory for B itself, and for the library two 935 00:48:38,660 --> 00:48:40,081 which A hasn't already loaded. 936 00:48:40,081 --> 00:48:41,580 So now, those are going to be loaded 937 00:48:41,580 --> 00:48:45,670 into some additional locations in B's memory, 938 00:48:45,670 --> 00:48:48,120 are going to be loaded into some additional locations 939 00:48:48,120 --> 00:48:51,220 in the physical memory and mapped into A's memory. 940 00:48:51,220 --> 00:48:53,260 So, this is just showing that we can actually 941 00:48:53,260 --> 00:48:55,360 use this notion of address spaces, 942 00:48:55,360 --> 00:48:57,810 in addition to using it to isolate 943 00:48:57,810 --> 00:48:59,580 two modules from each other so they 944 00:48:59,580 --> 00:49:01,180 can't refer to each other's memory, 945 00:49:01,180 --> 00:49:03,902 we can also use it as a way to allow two modules to share 946 00:49:03,902 --> 00:49:04,860 things with each other. 947 00:49:04,860 --> 00:49:09,880 And in particular, this is a good idea in the case of things 948 00:49:09,880 --> 00:49:11,920 like shared libraries where we have two things, 949 00:49:11,920 --> 00:49:14,500 both programs need to be able to read the same data. 950 00:49:14,500 --> 00:49:16,510 So they could use this to do that. 951 00:49:16,510 --> 00:49:19,300 OK, so what we saw today was this notion of virtual memory 952 00:49:19,300 --> 00:49:20,820 and address spaces. 953 00:49:20,820 --> 00:49:22,320 We saw how we have the kernel that's 954 00:49:22,320 --> 00:49:24,356 a trusted intermediary between two applications. 955 00:49:24,356 --> 00:49:25,730 What we're going to see next time 956 00:49:25,730 --> 00:49:29,070 is how we can take this notion of virtualizing a computer. 957 00:49:29,070 --> 00:49:30,890 We saw how to virtualize the memory today. 958 00:49:30,890 --> 00:49:33,390 Next time we're going to see how we virtualize the processor 959 00:49:33,390 --> 00:49:34,806 in order to create the abstraction 960 00:49:34,806 --> 00:49:37,250 of multiple processors running on just one 961 00:49:37,250 --> 00:49:38,750 single, physical piece of hardware. 962 00:49:38,750 --> 00:49:40,790 So I'll see you tomorrow.