X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Fuserprog.texi;h=7c835b680163662459113d1b37961894c696c13c;hb=74b32a20fdac074b17473333b55364209aaf9802;hp=bab70ec7c178094f1e1ef581b8dc18648c761acc;hpb=4ebf33908a571a7cde93fe618902b044e3633cdf;p=pintos-anon diff --git a/doc/userprog.texi b/doc/userprog.texi index bab70ec..7c835b6 100644 --- a/doc/userprog.texi +++ b/doc/userprog.texi @@ -16,8 +16,8 @@ relevant parts below. You can build project 2 on top of your project 1 submission or you can start with a fresh copy. No code from project 1 is required for this -assignment. The ``alarm clock'' functionality may be useful in later -projects, but it is not strictly required. +assignment. The ``alarm clock'' functionality may be useful in +projects 3 and 4, but it is not strictly required. @menu * Project 2 Background:: @@ -415,7 +415,7 @@ provide a little bit of helpful code: Returns true if successful, false if USRC is invalid. */ static inline bool get_user (uint8_t *kdst, const uint8_t *usrc) { int eax; - asm ("mov %%eax, offset 1f; mov %%al, %2; mov %0, %%al; 1:" + asm ("movl $1f, %%eax; movb %2, %%al; movb %%al, %0; 1:" : "=m" (*kdst), "=&a" (eax) : "m" (*usrc)); return eax != 0; } @@ -424,7 +424,7 @@ static inline bool get_user (uint8_t *kdst, const uint8_t *usrc) { Returns true if successful, false if UDST is invalid. */ static inline bool put_user (uint8_t *udst, uint8_t byte) { int eax; - asm ("mov %%eax, offset 1f; mov %0, %b2; 1:" + asm ("movl $1f, %%eax; movb %b2, %0; 1:" : "=m" (*udst), "=&a" (eax) : "r" (byte)); return eax != 0; } @@ -568,11 +568,15 @@ waits for @var{B}, then @var{A} waits for @var{C}), and so on. @deftypefn {System Call} bool create (const char *@var{file}, unsigned @var{initial_size}) Creates a new file called @var{file} initially @var{initial_size} bytes in size. Returns true if successful, false otherwise. + +Consider implementing this function in terms of @func{filesys_create}. @end deftypefn @deftypefn {System Call} bool remove (const char *@var{file}) Deletes the file called @var{file}. Returns true if successful, false otherwise. + +Consider implementing this function in terms of @func{filesys_remove}. @end deftypefn @deftypefn {System Call} int open (const char *@var{file}) @@ -585,10 +589,14 @@ File descriptors numbered 0 and 1 are reserved for the console: fd 0 is standard input (@code{stdin}), fd 1 is standard output (@code{stdout}). These special file descriptors are valid as system call arguments only as explicitly described below. + +Consider implementing this function in terms of @func{filesys_open}. @end deftypefn @deftypefn {System Call} int filesize (int @var{fd}) Returns the size, in bytes, of the file open as @var{fd}. + +Consider implementing this function in terms of @func{file_length}. @end deftypefn @deftypefn {System Call} int read (int @var{fd}, void *@var{buffer}, unsigned @var{size}) @@ -597,6 +605,8 @@ Reads @var{size} bytes from the file open as @var{fd} into 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}. + +Consider implementing this function in terms of @func{file_read}. @end deftypefn @deftypefn {System Call} int write (int @var{fd}, const void *@var{buffer}, unsigned @var{size}) @@ -604,11 +614,18 @@ Writes @var{size} bytes from @var{buffer} to the open file @var{fd}. Returns the number of bytes actually written, or -1 if the file could not be written. +Writing past end-of-file would normally extend the file, but file growth +is not implemented by the basic file system. The expected behavior is +to write as many bytes as possible up to end-of-file and return the +actual number written, or -1 if no bytes could be written at all. + Fd 1 writes to the console. Your code to write to the console should write all of @var{buffer} in one call to @func{putbuf}, at least as long as @var{size} is not bigger than a few hundred bytes. Otherwise, lines of text output by different processes may end up interleaved on the console, confusing both human readers and our grading scripts. + +Consider implementing this function in terms of @func{file_write}. @end deftypefn @deftypefn {System Call} void seek (int @var{fd}, unsigned @var{position}) @@ -623,30 +640,36 @@ have a fixed length until project 4 is complete, so writes past end of file will return an error.) These semantics are implemented in the file system and do not require any special effort in system call implementation. + +Consider implementing this function in terms of @func{file_seek}. @end deftypefn @deftypefn {System Call} unsigned tell (int @var{fd}) Returns the position of the next byte to be read or written in open file @var{fd}, expressed in bytes from the beginning of the file. + +Consider implementing this function in terms of @func{file_tell}. @end deftypefn @deftypefn {System Call} void close (int @var{fd}) Closes file descriptor @var{fd}. + +Consider implementing this function in terms of @func{file_close}. @end deftypefn The file defines other syscalls. Ignore them for now. You will implement some of them in project 3 and the rest in project 4, so be sure to design your system with extensibility in mind. -To implement syscalls, you need to provide ways to copy data -from user virtual address space into the kernel and vice versa. +To implement syscalls, you need to provide ways to read and write data +in user virtual address space. You need this ability before you can even obtain the system call number, because the system call number is on the user's stack in the user's virtual address space. This can be a bit tricky: what if the user provides an invalid pointer, a pointer into kernel memory, or a block partially in one of those regions? You should handle these cases by -terminating the user process. We recommend +terminating the user process. We recommend writing and testing this code before implementing any other system call functionality. @@ -783,6 +806,10 @@ user program C library does not have a @func{malloc} implementation. Modify @file{src/examples/Makefile}, then run @command{make}. +@item Can I run user programs under a debugger? + +Yes, with some limitations. @xref{Debugging User Programs}. + @item What's the difference between @code{tid_t} and @code{pid_t}? A @code{tid_t} identifies a kernel thread, which may have a user @@ -1041,8 +1068,9 @@ Thus, when the system call handler @func{syscall_handler} gets control, the system call number is in the 32-bit word at the caller's stack pointer, the first argument is in the 32-bit word at the next higher address, and so on. The caller's stack pointer is accessible to -@func{syscall_handler} as the @samp{esp} member of the @code{struct -intr_frame} passed to it. +@func{syscall_handler} as the @samp{esp} member of the +@struct{intr_frame} passed to it. (@struct{intr_frame} is on the kernel +stack.) The 80@var{x}86 convention for function return values is to place them in the @code{EAX} register. System calls that return a value can do