c代写-CSE 421
时间:2021-10-29
CSE 421 Recitation
Project 2 Phase 1: Argument Passing
Presented by Montana Lee
Agenda
1. Project 2 overview
2. Phase 1 objectives
3. Understanding the user stack
4. Taking our input to put onto the stack
5. Brief pointer review
6. Phase 1 files to work in and testing
7. Step-by-step
8. Ways to succeed
Project 2 Overview
● Project 2 does not depend on Project 1 whatsoever! Start a new repo if you
haven’t already according to lecture instructions.
● This project will deal with user programs.
● You will implement the functionality for this. The phases focus on argument
passing, safe memory access, and system calls, respectively.
● This project is not ‘less intensive’ than Project 1, but has less of a degree of
variation. The workload in hours needed to complete is the same as Project 1
(and even more!), so if you struggled with time management, now is the time
to plan better!
Phase 1 Objectives
● Be able to understand how the stack is utilized in order for a user to use
programs with passed arguments
● Become familiar with the src/userprog directory code
● Prepare for the following phases
Understanding the User Stack
Pintos User Stack
● Remember that we interpret a specific set of
memory addresses used by the OS for user
programs as a ‘stack’ - LIFO order!
● Stack will grow ‘down’ based on the image,
subtracting from the address.
● User stack begins at the global variable
PHYS_BASE, which is equal to 0xc0000000.
● Pintos currently can’t handle argument passing, so
you must first change the esp pointer in
setup_stack() and make process_wait() into a
timed loop.
Putting the Input onto the Stack
● To call a user program, a user will type a line in the shell with the needed
parameters (arguments)
● You will need to take this string, parse it (using strtok() is recommended), and
push it appropriately onto the stack
● Pintos will need the filename (the name of the program we want to run), the
arguments that will be passed to this program, and a structured ‘argv’ and
‘argc’.
● Recall that argv is the array of command line arguments, and argc is an
integer value of the number of command line arguments.
● We will repeat the example from lecture for this.
Putting the Input onto the Stack Example
● Consider typing the following in the shell (command line):
/bin/ls -l foo bar
● The steps that you must follow to put this onto the stack:
○ Parse the line (with space as the delimiter). strtok() is recommended
○ Starting from the last argument (bar), pass each argument onto the stack
○ Align the stack pointer (esp) if needed
○ Push a null pointer sentinel
○ Starting from the last argument, push the address of each argument (argv[arg])
○ Push argv, the address of argv[0]
○ Push the value of argc
○ Push 0 as a fake return address
● We will walk through these steps in the following slides.
Putting the Input onto the Stack Example Cont’d.
● Parse the line (with space as the delimiter). strtok() is recommended. Once
the line has been parsed, you should have separate strings like the following:
“/bin/ls\0”, “-l\0”, “foo\0”, “bar\0”
Putting the Input onto the Stack Example Cont’d.
● Starting from the last argument (bar), pass each argument onto the stack.
Once you have finished, your stack should look like the following. Note that
the stack is growing ‘downwards’.
Putting the Input onto the Stack Example Cont’d.
● The stack pointer must be kept in alignment, so it may need to be padded!
We need it to be an address divisible by 4, so after pushing on the arguments,
you must then push an appropriate amount of 0s in order to do this. You may
need to push on 0, 1, 2, or 3 bytes of 0 in order to preserve alignment. In this
example, we only need 1 byte of 0. When finished:
Putting the Input onto the Stack Example Cont’d.
● Push a null pointer sentinel. A ‘sentinel’ is a number that no valid value could
be, such that we can discern when certain inputs end and/or begin. Thus, our
sentinel is a char * with a value of 0. We do this to mark the end of the string
pushes on the stack and the beginning of our address pushes. After pushing
this, your stack should look like the following:
Putting the Input onto the Stack Example Cont’d.
● Now we need to push all the
addresses of the argument strings
onto the stack. Remember that
argv is a char **. This means that
each argv[arg] access itself is a
char * (a string representing an
argument such as “foo”).
● These addresses need to be
pushed on in the same order as the
strings themselves were, last
argument first. When finished:
Putting the Input onto the Stack Example Cont’d.
● Now push on the argv itself,
This is a char ** and its value
is the address of argv[0].
When finished:
Putting the Input onto the Stack Example Cont’d.
● Now push on the value of
argc - this is an int
indicating the number of
arguments passed. In this
example, argc == 4. When
finished:
Putting the Input onto the Stack Example Cont’d.
● Finally, push on a fake return
address. This function will
never return, but must follow
the same structure requiring a
return address at the end.
● And you’re done!! Using this
format, Pintos can run the user
program with the specified
arguments.
Brief Pointer Review
● This project uses pointers, pointer math, and pointer types very heavily. It is
important that you have a solid understanding of these.
● Important to remember:
○ You must cast a void pointer to a type before attempting access it.
○ Void pointers can store any type of data and assignment to a void does not need casting.
○ Accessing a double pointer will give you another pointer.
○ ‘Pointer math’ is adding/subtracting from a pointer address in order to increment/decrement
along addresses in the address space. If you want to store an address before manipulating it,
you must do so yourself.
○ Pointer math adds in increments of bytes of the type of the pointer you are doing math on.
○ * before a pointer variable is accessing the contents of it (also known as de-referencing), &
before a pointer variable returns not the contents, but the address of the pointer variable itself.
● See TAs ASAP if you want more pointer help!
Files to Work In and Tests
● Much of your work this phase will take place in src/userprog/process.c
● To get credit for this phase, you must pass the pa2_arg_test, which can be
downloaded from Resources in Piazza. It will verify that your setup_stack() is
correct by injecting a hex dump and comparing its output with a reference.
● Use the included hex_dump() function for testing! It will dump the hex values
and contents of your stack at the line of use, so you can track how you are
pushing the contents on!
E.g.: hex_dump((uintptr_t) *esp, *esp, PHYS_BASE-*esp, true)
● This phase is tiny compared to the following phases. Do not use this to gauge
the difficulty/length of the rest of the project (Just like in Project 1!) You should
finish this phase ASAP and move on- it is not supposed to take two weeks.
Step-By-Step
● Follow the Pintos code in the src/userprog directory to become familiar with it
and watch Thursday lecture recordings.
● To run before implementing, change *esp = PHYS_BASE to *esp =
PHYS_BASE - 12 in setup_stack() and make process_wait() into a timed loop
(e.g. for 5 seconds, using timer_sleep()).
● Follow the steps outlined earlier to implement argument passing (and remove
the above to test it)
● Verify you pass the given test for setup_stack() (under Resources in Piazza).
● Move on to the following phases as soon as possible!
Ways to Succeed in the Project and Course
● Don’t be afraid of the code! Explore everything and read through important
files
● Read the documentation!
● Visit office hours and ask questions early
● Start early. The projects are very time-consuming and require steady,
metered work
● Commit often to Github in case you need to revert back
● Communicate with your team member
● Get in contact with staff ASAP if problems arise
● Don’t cheat!
Good luck!

学霸联盟






































































































































































学霸联盟


essay、essay代写