X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Fuserprog.texi;h=8524219bf0acc5052f5d75e52817fd4999b2bb79;hb=549e11aeae62a517eb513c6dc1e3e267b8293781;hp=a9a84b2dcd854609cbd40bd82648cf96b1a9773c;hpb=f415a37905c57f61b444806bf84f5405184452aa;p=pintos-anon diff --git a/doc/userprog.texi b/doc/userprog.texi index a9a84b2..8524219 100644 --- a/doc/userprog.texi +++ b/doc/userprog.texi @@ -20,10 +20,7 @@ assignment. The ``alarm clock'' functionality may be useful in projects 3 and 4, but it is not strictly required. You might find it useful to go back and reread how to run the tests -(@pxref{Testing}). In particular, the tests for project 2 and later -projects will probably run faster if you use the qemu emulator, e.g.@: -via @code{make check PINTOSOPTS='--qemu'}. The qemu emulator is -available only on the Linux machines. +(@pxref{Testing}). @menu * Project 2 Background:: @@ -304,7 +301,7 @@ regardless of what user process or kernel thread is running. In Pintos, kernel virtual memory is mapped one-to-one to physical memory, starting at @code{PHYS_BASE}. That is, virtual address @code{PHYS_BASE} accesses physical -address 0, virtual address @code{PHYS_BASE} + @t{0x1234} access +address 0, virtual address @code{PHYS_BASE} + @t{0x1234} accesses physical address @t{0x1234}, and so on up to the size of the machine's physical memory. @@ -317,11 +314,6 @@ the running process. However, even in the kernel, an attempt to access memory at an unmapped user virtual address will cause a page fault. -You must handle memory fragmentation gracefully, that is, a process that -needs @var{N} pages of user virtual memory must not require those pages -to be contiguous in physical memory (or, equivalently, in kernel virtual -memory). - @menu * Typical Memory Layout:: @end menu @@ -430,29 +422,37 @@ Therefore, for those who want to try the latter technique, we'll provide a little bit of helpful code: @verbatim -/* Tries to copy a byte from user address USRC to kernel address KDST. - Returns true if successful, false if USRC is invalid. */ -static inline bool get_user (uint8_t *kdst, const uint8_t *usrc) { - int eax; - asm ("movl $1f, %%eax; movb %2, %%al; movb %%al, %0; 1:" - : "=m" (*kdst), "=&a" (eax) : "m" (*usrc)); - return eax != 0; +/* Reads a byte at user virtual address UADDR. + UADDR must be below PHYS_BASE. + Returns the byte value if successful, -1 if a segfault + occurred. */ +static int +get_user (const uint8_t *uaddr) +{ + int result; + asm ("movl $1f, %0; movzbl %1, %0; 1:" + : "=&a" (result) : "m" (*uaddr)); + return result; } - -/* Tries to write BYTE to user address UDST. - Returns true if successful, false if UDST is invalid. */ -static inline bool put_user (uint8_t *udst, uint8_t byte) { - int eax; - asm ("movl $1f, %%eax; movb %b2, %0; 1:" - : "=m" (*udst), "=&a" (eax) : "r" (byte)); - return eax != 0; + +/* Writes BYTE to user address UDST. + UDST must be below PHYS_BASE. + Returns true if successful, false if a segfault occurred. */ +static bool +put_user (uint8_t *udst, uint8_t byte) +{ + int error_code; + asm ("movl $1f, %0; movb %b2, %1; 1:" + : "=&a" (error_code), "=m" (*udst) : "r" (byte)); + return error_code != -1; } @end verbatim Each of these functions assumes that the user address has already been verified to be below @code{PHYS_BASE}. They also assume that you've -modified @func{page_fault} so that a page fault in the kernel merely sets -@code{eax} to 0 and copies its former value into @code{eip}. +modified @func{page_fault} so that a page fault in the kernel merely +sets @code{eax} to @t{0xffffffff} and copies its former value +into @code{eip}. @node Project 2 Suggested Order of Implementation @section Suggested Order of Implementation @@ -566,13 +566,13 @@ word is the program name, the second word is the first argument, and so on. That is, @code{process_execute("grep foo bar")} should run @command{grep} passing two arguments @code{foo} and @code{bar}. -Within a command line, multiple spaces are equivalent to a single space, -so that @code{process_execute("grep foo bar")} is equivalent to our -original example. You can impose a reasonable limit on the length of -the command line arguments. For example, you could limit the arguments -to those that will fit in a single page (4 kB). (There is an unrelated -limit of 128 bytes on command-line arguments that the @command{pintos} -utility can pass to the kernel.) +Within a command line, multiple spaces are equivalent to a single +space, so that @code{process_execute("grep @w{ }foo @w{ }@w{ }bar")} +is equivalent to our original example. You can impose a reasonable +limit on the length of the command line arguments. For example, you +could limit the arguments to those that will fit in a single page (4 +kB). (There is an unrelated limit of 128 bytes on command-line +arguments that the @command{pintos} utility can pass to the kernel.) You can parse argument strings any way you like. If you're lost, look at @func{strtok_r}, prototyped in @file{lib/string.h} and @@ -619,10 +619,11 @@ the program cannot load or run for any reason. @end deftypefn @deftypefn {System Call} int wait (pid_t @var{pid}) -Waits for process @var{pid} to die and returns the status it passed to -@code{exit}. Returns -1 if @var{pid} +If process @var{pid} is still alive, waits until it dies. +Then, returns the status that @var{pid} passed to @code{exit}, +or -1 if @var{pid} was terminated by the kernel (e.g.@: killed due to an exception). If -@var{pid} is does not refer to a child of the +@var{pid} does not refer to a child of the calling thread, or if @code{wait} has already been successfully called for the given @var{pid}, returns -1 immediately, without waiting. @@ -674,6 +675,12 @@ as explicitly described below. Each process has an independent set of file descriptors. File descriptors are not inherited by child processes. + +When a single file is opened more than once, whether by a single +process or different processes, each @code{open} returns a new file +descriptor. Different file descriptors for a single file are closed +independently in separate calls to @code{close} and they do not share +a file position. @end deftypefn @deftypefn {System Call} int filesize (int @var{fd}) @@ -685,8 +692,7 @@ Reads @var{size} bytes from the file open as @var{fd} into @var{buffer}. Returns the number of bytes actually read (0 at end of file), or -1 if the file could not be read (due to a condition other than end of file). Fd 0 reads from the keyboard using -@func{kbd_getc}. (Keyboard input will not work if you pass the -@option{-v} option to @command{pintos}.) +@func{input_getc}. @end deftypefn @deftypefn {System Call} int write (int @var{fd}, const void *@var{buffer}, unsigned @var{size}) @@ -905,12 +911,6 @@ You can choose whatever suitable types you like for @code{tid_t} and @code{pid_t}. By default, they're both @code{int}. You can make them a one-to-one mapping, so that the same values in both identify the same process, or you can use a more complex mapping. It's up to you. - -@item Keyboard input doesn't work. - -You are probably passing @option{-v} to @command{pintos}, but -serial input isn't implemented. Don't use @option{-v} if you -want to use the shell or otherwise need keyboard input. @end table @menu