‫Welcome back, everybody.
‫In this lecture, we're going to implement processes, so I just want you to go to the task directory
‫and we're going to create a new file called Protostar Hajj.
‫So the head of file will go if and death process Hajj to find process Hajj, hashtag and death.
‫Now we just construct a process.
‫This will be our process structure that describes the process that's running.
‫So what is a process?
‫Well, if you're running windows, you might open a notepad, you know, stuff like that.
‫I'm pretty sure all of you understand what the process is.
‫So this structure will define how the colonel sees the process.
‫OK, so we're going to include SAGD in it here and we're going to have a Unit 80 I.D. the process ID.
‫OK, now, I'll be honest, Apitz is quite low for an ID because it's quite possible that we could have
‫a lot more processes than 256.
‫So let's change it to you.
‫And at 16, I think that's more more appropriate.
‫And we're going to go to your file name and we're going to have Peatross Max path.
‫So we're going to include some figures on the Hajj by here, OK?
‫And yes, we have that.
‫That's good.
‫So when I now going to go struct task task and this will be the main process task.
‫So we're just going to include tasks of Hajj by here.
‫OK, so what else do we need in our process?
‫We need allocations.
‫So Peatross max allocations, max program allocations and we're going to have to define that.
‫Uh, so what is this allocation variable?
‫Well, in a process you can mallock and ask the kernel for memory.
‫OK, now what if you didn't free that memory?
‫What if.
‫No, PADI actually chose not to free the memory?
‫Well, you'd have a memory, wouldn't you?
‫So that's why we keep track here in this applications array.
‫We keep track of all the applications they've made.
‫And by keeping track of all the allocations they've made, it allows us to free all of the allocations
‫that they have and feed themselves upon process termination, which will resolve the memory leak.
‫So that's why we do this, guys, because if we didn't keep track of the memory that the process is
‫allocating, then we would rely on them to be good and free.
‫The memory and obviously in situations where the process crashes, that's not possible.
‫In situations where the program is sloppy, that's not possible.
‫So this is a failsafe here.
‫We set this array with allocations.
‫So whenever the process Matlock's we we at the address we've allocated into this array, OK, the physical
‫address, and then we can free that information as soon as this process dies.
‫So that's why we have this array.
‫So the alloca the memory.
‫Mallock.
‫Allocations of the process, so all the tasks who do mallock will fill this array.
‫OK, so let's let's copy and paste this into conflict outrage because we need to define that.
‫Right.
‫So we're just going to go hash tag to find Peatross Max program allocations.
‫I think we'll go for 1024, which is quite small, to be honest.
‫But this is a learning environment and in a better implementation, we might just have a void pointer
‫here, guys, and then we would essentially mallock the entire point later on.
‫And then we are reallocated every single time that the memory needs to be increased in size.
‫So that would be the better way of doing this.
‫But this array is perfectly acceptable for a learning scenario.
‫And you guys, you all know the C programming language anyway.
‫So you're a completely capable of improving this if you wanted to.
‫Its best to keep it simple for you guys.
‫OK, so now we're going to go void's pointer, OK, and this is the physical point to the process memory.
‫So notice how we're not caring about sections and all that.
‫That's because I plan to just load binary files.
‫You could implement LTH if you wanted to.
‫However, then this process structure would be a bit different.
‫You would have some sort of variable that determines what type of process this is.
‫Is it an L file?
‫Is it a binary file or something like that.
‫Right.
‫And then you'd have some sort of unión by here that would accommodate for all the different possible
‫process types.
‫But we're just going to work with real binary for now.
‫So this is the fiscal pointed to the process memory.
‫OK, once the process is loaded and I we're going to go void stack and this will be the physical point
‫to the stack memory.
‫So now we're going to go Unit 32 to size, and this will be the size of the data pointed to by Pinter.
‫Now, in the future will be dealing with things like keep keyboard strokes, receiving keys from the
‫keyboard and all that sort of stuff.
‫So it probably stole the keyboard buff in the process.
‫So the selected process, its keyboard buff, will be fulfilled when there's a key interrupt.
‫However, for now, we don't have the keyboard implemented, so this is perfectly acceptable how it
‫is.
‫So that's what our process structure should look like.
‫It's quite acceptable.
‫We can do a lot with this.
‫We know the process ID, we know the filename associated with the process.
‫We know the main process task in our current implementation.
‫There'll only be one task process.
‫We we know every single allocation to that process is done.
‫We know the physical pointer and memory that the process is loaded in that that's the code and the data.
‫Guys, we don't take sections into account here.
‫This this assumes a binary process.
‫You know, how we compiler kernel in as binary and Ilinka script, this assumes wallowed in the program
‫as binary.
‫There's no head, there's no sections.
‫OK, and here, you know, we have the points to the stack memory and we have the size of the data pointed
‫to by pointer.
‫So we can do a lot with this this space.
‫He describes our whole process.
‫OK, so yeah, this structure is perfect to begin with.
‫We can look on expanding this if we need to.
‫OK, guys, what I now want you to do is I want you to go to task the task directory and we're going
‫to create a new file called Process Dot C, I'm going to start C, we're just going to include process
‫stage and we're simply going to go struct process.
‫Current process equals zero.
‫So this will be the current process that is running OK.
‫And now we're going to go struct process processes and this will be all of the loaded processes in the
‫system.
‫And we're just going to go process max processes here and we're just going to go equals and then we're
‫going to just pass those two curly braces.
‫So just in config now we're going to copy and paste this definition.
‫And we're just going to go to find Peatross max processes and we'll just use something like 12.
‫That'll be enough, I think for the time being it's just experimental right now.
‫Try 12 and we can change that number if needed.
‫So.
‫OK, that's now resolved correctly.
‫Just include config Hideshi as well.
‫Guys, I think we do it in start.
‫Yes, we do OK, in which case we don't need to include that.
‫But I'm going to keep it there just to make sure it's clear what's going on and to avoid further dependency
‫on post start in the future.
‫So when I was going to go static void process and it.
‫Struck process process.
‫And I'll tell you what, guys, I also want this to be static.
‫This process is a way to set that static to now here we're just going to go said and we're going to
‫have to include memory, memory, dot Hajj for that.
‫So we're going to go said process zero size of struct process.
‫So that will just initialize the process memory that's passed to this process and it function when we're
‫going to go struct process process Curran's and this will simply return the current process.
‫So we're now going to create our process load function.
‫So we're going to go in it process load's for slot const char filename
‫struct process and this will be a multidimensional PENAGOS process and now we're going to go in it process
‫slots.
‫So process low for slot will take a file, name the address of a pointer to a process and the process
‫slot.
‫Now the process slot will be the index in the processes array by here.
‫OK, so essentially when we call process Hlophe Slope, we're trying to load the process into the array,
‫into an array index here.
‫So we basically tell the system what ID we want the process to have.
‫And then, you know, we'll later on we'll have a process load function that finds the free slot, you
‫know, stuff like that.
‫It's nice to break things down.
‫And that's exactly why we don't start here with a process load function.
‫But we instead have a process load for slots.
‫So yeah, we will have a process load later on and that will find a free slot in this array and then
‫we will call process load for slot.
‫So yes, simply process love a slot will load the given file name as a process into memory.
‫OK, now this is an incredibly long function, so it's going to take a while before we're done implementing
‫that, we need to create a few more functions first before we can start implementing this function.
‫So one of the functions we're going to create is the process function.
‫So this is a very easy function.
‫We just go in it process get and we're going to have the index here and we say if the index is below
‫zero or the index is above equal, Peatross max processes then return minus E an invalid argument.
‫OK, so let's just include, uh, status, not here, no.
‫OK, otherwise, we're going to return processes index.
‫OK, perfect.
‫So, simply put, this ensures that the index is in bounds.
‫This is the process, I'd really, to be honest with you.
‫That's just change this to process.
‫I'd actually so it's simpler to understand.
‫So, yeah, this is the process.
‫I'd, uh, if they provide something below zero or above the max processes, then we know it's invalid.
‫So we would send in a document.
‫Otherwise we're going to return the pointed to the process.
‫OK, OK, so in this function now we're going to go in.
‫It equals zero.
‫We're going to say struct task task equals zero and we're just going to include that now include the
‫task header guys task test stage and we're going to say struct process process.
‫OK, make sure to underscore Persis guys, because we already have a process variable here, OK, and
‫I were going to say void's program stack pointer and this will point to the stack for the new program
‫that we're loading.
‫So down here, we're just going to say if process gets process, slot does not equal zero, then race
‫equals minus E is taken and we don't have that yet.
‫So we'll correct that.
‫Uh, but essentially our gnat's is e estate end and essentially we can't load a process into a slot
‫that already has a loaded process.
‫So that's why we need to do this.
‫Check, guys, to avoid memory leaks and overwriting things.
‫We shouldn't be so down here.
‫We're just going to go to and we're going to have our label down here and we're going to go over to
‫address.
‫OK, so that's our function so far.
‫And let's take this copy and paste this definition we've done here, go to status stage and we're just
‫going to go define how we're going to paste that in and we're just going to put eight by there to find
‫is taken, OK?
‫Down here, when I was going to go process equals Kazai block size of struct process, so just scroll
‫up here and we're going to say includes
‫heap, keep that scroll back down.
‫You can see I put a capitalist that changed that to allow access when I was going to say if the process
‫is null for an explanation, Mark, there goes rests equals minus NMM and we're going to go to our OK.
‫So if we fail to allocate the memory, then we're done here because unfortunately we run out of memory
‫for everything.
‫So, OK, so far we're just going to go process in it and we're going to pass in the process so that
‫all know.
‫That's all for us.
‫I know Casula does, but we still need initialization functions.
‫It's good practice.
‫OK, so we're now going to want to say rest's equals process low data and we haven't created this function
‫yet and we're going to pass the filename and the process and then we're going to say if recist below
‫zero, you know, there was an error, then go to out.
‫Because remember, if we return lower than zero, there's an error.
‫So process low data will be in charge of looking into the file, finding out what type of file is.
‫Is it an executable?
‫Is it a real binary file?
‫And then it's responsible for loading the data.
‫So that's what process load data will do.
‫And we're going to create that function.
‫Now, however, bear in mind at the moment at least, we're only going to be loading raw binary files.
‫That is raw code and data combined.
‫OK, so just up here, then we're going to create that load data function.
‫So static init process load data struct.
‫No, no, no.
‫Const char file name struct process and that'll be the arguments.
‫And we're just going to go into Resko zero bress equals process load binary and we're going to pass
‫in the filename and the process and we're just going to say return rest's.
‫So it'll be as simple as that for now.
‫In the future.
‫We might check if it's in our file, if it's a P file, if it's some other type of executable file,
‫and then we would load it differently, maybe some sort of switch statement here or an if statement
‫or something like that.
‫However, for now we're just loading binary.
‫So let's create the process load binary function now.
‫So we're going to go static init process load binary const char filename struct process, process and
‫address equals zero return address.
‫OK, so we're going to load the binary file on this in this function body now and it F.T. equals f open
‫file name and we're going to open and remote now scroll scroller and we're going to include the header
‫files.
‫So include FS file dot org just like that.
‫OK, and now I f open functionality will work and we'll be able to open that file.
‫So we're going to say if the file doesn't exist I f open returns a negative or zero or something then
‫rascal's eio minus EIO.
‫I was just going to go to OK and we're going to have an out label by here as well guys.
‫OK, so first we check, we can open the file name and if we can't then obviously while we can't load
‫the process because either there was some problem opening the file or the file doesn't exist.
‫OK, we now need to stack the file for the file size.
‫So we're just going to go struct file start start and we're going to say REST's equals f stat and we're
‫going to go F.T. Ampersand stacked, OK?
‫And then we're going to say if rest does not equal Peko s all OK then go to I.
‫So now we're starting the file because we want to know it's file size, OK, because we need to know
‫how much memory we need to allocate for it.
‫I obviously if it's file size is one kilobyte, then we shouldn't allocate one megabyte.
‫Right.
‫That's why we need to know it's file size so we start the file to figure that out.
‫So now we're going to say void and this is a void pointer program.
‫Data pointer equals Kasar log stat file size so that here now where we're declaring the memory for our
‫program that we're loading.
‫All right.
‫And obviously if we fail to create that memory, then there's there's a problem where out of memory.
‫So we go rest equals minus Inamine go to out.
‫You see it's pretty straightforward so far.
‫And now the next step is to read the entire program into that.
‫We just created so we're going to say if Elfriede program dates, Appointer Statter, file size one.
‫So we're basically reading one block of the file size now.
‫OK, so the file size might be 50 bytes, for example.
‫And while loading one block, so we're loading one times 50.
‫OK, so basically the whole file.
‫So then we're going to go 50 does not equal one.
‫Then we failed to load the program data or at least some part of it.
‫And we're going to say equals minus EIO, go to ours, OK?
‫And now down here, we're going to go process Pointer Eco's program data point to process size equal
‫standard file size.
‫Now, in the future we might have something like process file type equals process file type binary.
‫Now because we're only dealing with binary files at the moment, there's no need to implement that.
‫So the final step now is to just go f close hefting as simple as that, and we can even put that in
‫the out label by there.
‫That's no problem, because if we take a look at our F close, we can see that if it can't get the descript,
‫it just leaves.
‫So if we pass null in there, there shouldn't be any issue.
‫No, because we we deal with that here.
‫So that's no problem at all.
‫So back to process start, see, the clothes should be under the old label so that the file handle is
‫always closed in the event we need to go to the out and leave this function.
‫So, yes, this function successfully loads the binary file into memory and we set the process point
‫to the processes.
‫And then, you know, we can call, uh, well, you can see we're calling process load data here.
‫Well, once we've called this, we know the process will be populated with the information we need.
‫OK, if there was multiple executable file types, then the type would be stored in the process structure.
‫Like I said, we don't deal with that yet because we only do a binary.
‫But the point is, after we call this function, everything we need to know about the process is loaded
‫into the process here.
‫This process variable.
‫OK, perfect.
‫Now, I'm sure you all know what the stack is in the stack is where all the local variables get stored.
‫It's where the return addresses gets stored when we call functions in C or assembly or something like
‫that.
‫And obviously we need some data for a stack for our process.
‫We can't let them use the kernel stack that's dangerous.
‫So we're going to declare some memory for them to do this with.
‫So how do we do that?
‫We just go program stack pointer equals Casar lock process.
‫Use a program stack size.
‫Simple as that, because remember we created this earlier on, so we have a 16 kilobytes stack.
‫You can see 1024 by multiply by 16.
‫That's not an awful lot of memory, but this is just training program for you guys, training course.
‫So you're welcome to tweak these values, but don't tweak them yet.
‫Follow the cost first because these values might matter.
‫And of course, it's very important.
‫Our program stack is aligned to page a page size because we're dealing with paging.
‫So must be aligned to four, nine, six guys.
‫How can you check something, Selinda?
‫Four, nine, six.
‫Very easy.
‫You just open up Python, you type in a number, let's say eight, nine to one.
‫You use modulus operator four nine six.
‫If the value it gives you is anything other than zero, then it's not aligned correctly.
‫1024 multiply by sixteen.
‫That's sixteen three a four.
‫We can see that, that, that goes into four four thousand eighty six.
‫Perfectly fine.
‫It's aligned correctly.
‫OK, so it must be aligned guys.
‫All the addresses must be aligned that we work with and that is because paging works on four thousand
‫ninety six byte boundaries.
‫So here we are going to say if programs stack pointer
‫is no, then race equals minus S.A.M..
‫Go to LB's.
‫So again, you know, if we fail to declare the stack memory, we need to deal with that.
‫OK, so the process load data function that's loading the data of the process into memory, it's not
‫really in charge of setting the fields such as the file name and all that sort of stuff.
‫Right.
‫It's more in charge of just loading these this pointer here, this physical pointer and set this size.
‫And we in the function process, like the slot, we're in charge of loading the stack while basically
‫setting up a memory for the stack, loading the file name and all that sort of stuff.
‫So we're going to do that now.
‫Just under program stack points.
‫We're going to go string and copy process file, name, file, name size of.
‫Process following, and now if you look in process stage, we can see that's an array ashara, so size
‫off will work perfectly fine here.
‫So we're just going to scroll up and we're going to include that had a five string string that Hajjaj.
‫I'm perfect, we can see that works now we're just here, we're going to go process stack equals program
‫stack pointer.
‫We're also going to go process ID equals.
‫Process, Slote.
‫And now it's time to load the task.
‫Well, quite a task, I should say, so essentially the process functionality just describes the process.
‫It allows basically a generic point for all tasks to talk about a particular process.
‫Right?
‫That's the whole point of the process structure and the process functionality processes should be able
‫to have many tasks.
‫However, in this educational context, it'll be just one for now.
‫So essentially the task itself is the code that's being run.
‫What is the description of the code that's being run?
‫The address in memory of where that code is being run, the state of the registers since the last save
‫and so on.
‫This is the state of the task.
‫OK, so think of what you can think of a task like a threat.
‫OK, essentially.
‫So we're going to create a task now.
‫So we're just going to go task equals task new and we're going to pass in the process.
‫Now, I know we haven't implemented this part of the task yet, but we will get to that.
‫And now we're going to say if error I.
‫TASC equals zero, wrests equals error I task and we look where error is, it is in Canada, the Hajj.
‫So in process Stazi just include Colonel Dot Hajj of the TOPIA.
‫OK, and that'll resolve that dependency that so this creates the new task for us.
‫So at this point, we have a task that's ready to be run.
‫So what we do now is we just go process.
‫Task was task.
‫So we just associate that task with the process.
‫And this is the main task of the process.
‫OK, now we're absolutely not done yet because because we use the paging model, we need to map the
‫memory.
‫OK, so what we need to do now is we need to say rascal's process, map, memory process.
‫And if the rest is below zero, there was an error go to out.
‫So we're going to create this process, my memory function shortly.
‫So at this point in time, we have mapped the process successfully.
‫We haven't made this functionality yet, but we will.
‫So we do askaris process equals underscore process.
‫So if you remember this this double pointer thing passed to us here, that's basically someone passing
‫the address of their process pointer.
‫OK, we need to set that to to our one that we've created here.
‫So the value, I should say.
‫So that's why we do askers process equals underscore process, because underscore process is the one
‫that we declare here the memory.
‫OK, so we're basically just setting the process of the call it to us.
‫But don't worry, you'll see more about that later for those more more proficient in C, you understand
‫what I'm saying right now.
‫So what we're now going to do is we're going to add the process to the array.
‫So when I extend in the array, we just send the index guys.
‫So we're going to a process process slot equals process and you don't have to worry about multi threading
‫and all this sort of stuff because we're only using one process, a call.
‫So there's there's no worry for any conflicts or any any collision, stuff like that.
‫As long as interrupts get disabled.
‫Whenever we are in Courland, there's absolutely no concern for us to clash and another interrupt happen
‫or something like that.
‫OK, so long as interrupts the disabled, that is OK.
‫So what we're going to say here now, just after the out label is if there was an error in the response,
‫the response code, then we need to clean up the memory basically.
‫OK, so what we say is we say if the process has memory and the task has memory.
‫Then TASC Free Process Task Sacha's frees the task.
‫Right, and then we'll also free the process memory here as well.
‫Now, this is not such a great function right now because we're just doing Caffery process.
‫There's a lot of free you know, that we've declared the law, we've declared STAC memory, we've declared
‫program data.
‫So rather than do Caffery process, we're actually just going to get rid of that for now.
‫And we can leave a comment for ourselves, free the process data.
‫And when we've created a proper function for unloading processes, then we'll come back here and place
‫that there.
‫OK, but for now that's perfectly fine.
‫So what are we left with then?
‫What we've just finished this function.
‫However, we need to implement the process map memory function now, which will basically take the process
‫we've loaded and it will map it to the virtual addresses of the page tables for the for the process.
‫OK, let's scroll up.
‫We're going to create the process map memory function.
‫So we're just going to go in a process, map memory, struct process process.
‫And this function obviously expects the process to be properly initialized at this point and have the
‫memory loaded in.
‫If you tried to call this function before you did that, you'll probably cause kernel panic so or some
‫or worse some unexpected behavior.
‫So just bear that in mind.
‫The process must be loaded at this point.
‫It's loaded when we get to this line here.
‫OK, so we're just going to go in at rest equals zero risk equals process map binary and we're just
‫going to pass the process and we're just going to go over to address.
‫So once again, we have this generic function in case we decide to support our files in the future or
‫something.
‫And then obviously, you know, we can call the correct map function here so that the process of slot
‫only has to call process map memory.
‫It doesn't have to worry about anything else.
‫So let's now create the process map binary function.
‫So we're just going to go in it process map binary struct process process and we're just going to say
‫in a press equals zero return address and then we're just going to say paging map two and we're going
‫to have to include the paging guys to scroll up.
‫And we're just going to go include paging paging Dr. Hadash.
‫So paging map too.
‫And we don't have that function yet.
‫OK, we'll have to create that as well.
‫But let's just continue here.
‫So we're going to go paging map to process task page directory, directory entry.
‫And it probably makes sense, to be honest with you, to create some sort of function, the task to
‫handle this.
‫But for now, we'll just do it like this, just so that's more straightforward for you.
‫So here we're going to go.
‫Void pointer posts program, virtual address, OK, and then we're going to pass in the process pointer
‫here.
‫And we haven't created this paging function yet, as I've said.
‫But don't worry, we will create it.
‫And finally, we're going to go paging align address and we also have and created that will be well,
‫this will just ensure that the address we provide gets aligned to the next page up, which is very important
‫because remember, paging only works with page aligned addresses, four, nine, six alignment.
‫So here we're going to go process point plus process size.
‫And now now comes the flags that we're trying to set.
‫OK, now remember when we initialize the task, memory and task, when we did task in it, we allowed
‫access to the whole four gigabyte address space.
‫We made it present and accessible from use of space and from kernel space.
‫Basically, we we we didn't care about whether they had the supervisor bit or not.
‫Now, in to start see here, we're going to provide the writable flag, which will allow us to write
‫into the process, memory that we've just loaded.
‫And the reason for that is because it's our memory.
‫Obviously, we're going to have some variables in the binary file that we want to set or read and and
‫so on.
‫So we're literally going to set the writable flag for this reason.
‫So what we're going to do is we're going to say paging page present, paging O.
‫Use the all flag here, guys.
‫Paging access from all paging page writable.
‫OK, and it should just look like that, guys, so we actually made a mistake here, guys, that should
‫be paging is present and paging is writable.
‫OK, perfect, so let me go over this with you then, so.
‫We are mapping, so this directory, this page directory.
‫OK, if we now go to page Dot S., we're going to implement this paging map to function.
‫So just in here, we're going to go in it.
‫Paging map to ask upswept directory Pintor, a virtual address, a physical address, a physical end
‫address and Aflex variable.
‫OK, so we're going to go Innovest equals zero return address and we're going to have the out label
‫here.
‫So we're going to say if the virtual address is not in line.
‫With the paging page size.
‫And we need to cast that to a unit three to two guys.
‫OK, so if it's not zero, then it's not aligned.
‫OK, rest equals minus invalid argument, OK?
‫And we're going to need to do that for all of these.
‫So we're going to copy and paste this and you know, you can use it or if you want, but I'm just going
‫to do it like this, OK?
‫And also we need go to out here as well, guys, or you could just return.
‫It's entirely up to you.
‫Returning might even be cleaner maybe.
‫However, this is how I'm going to do it for now.
‫So, yeah, we're going to go like that.
‫And we're also going to say if the physical end is below equal, you know, 30 to 40 physical.
‫I'll tell you, all this should just be below, actually.
‫OK, so these are conditions when things will go wrong and we can tidy this up if you wanted to, we
‫could make this into one statement.
‫However, it seems a bit more clear like this.
‫So we're now going to go unit 30 to 40 total pages equals physical and minus physical.
‫And so that's not total pages.
‫That's total bytes.
‫And here we're going to go in it.
‫Total pages equals total bytes, divided by paging page size.
‫And now we're going to say rest's equals paging map range.
‫Directory, virtual, physical, total pages and flags.
‫OK, so I hope that makes sense, guys.
‫And we're now going to have to create this paging map range function as well.
‫And that function will be in charge of mapping from the virtual and physical address by X amount of
‫pages.
‫OK, so what?
‫We will implement that one in a moment.
‫However, this lecture is starting to get very large, so we're going to have a part to for for this
‫process implementation just to avoid overwhelming you.
‫We don't want a two or three hour lecture here.
‫So, yes, we're going to finish up this part now.
‫And you can watch the next part and we will continue from here.
‫Thank you.