Q: What does it mean for readchar to handle EOF and newline characters "correctly"? Should it do something besides returning the ascii value for those characters? A: readchar() should return 0 on EOF (e.g., when ctrl-d is typed). See the man page of the read() system call. End-of-line characters in different systems include '\r' and '\n'. You may need to process them. See how the menu code reads from the terminal. -------------------------------------------------------------------------------- Q: When should EAGAIN be returned for fork? I've read the man pages and seen that I am supposed to return EAGAIN if I don't have a pid to assign. Does this mean that there is a maximum number of processes should be allowed to run at once? A: That depends on your implementation. If you choose to have a fixed maximum number of processes, then you should return EAGAIN if the number of processes exceeds this limit even if you have enough memory. You may also choose to allow an arbitrary number of processes to run as long as you have enough memory. If memory is exhaused, you should return ENOMEM. -------------------------------------------------------------------------------- Q: I am wondering how to to implement PIDs into the OS for lab 2. Should we create a process struct, with a pid_t and a thread struct in it? Or should we just add a pid_t as another field of the thread struct (since we were told that each process will only have one thread for our assignments)? A: You need to be able to map from a pid value to a thread struct. One possible implementation is to add a pid value to the thread struct and link all the thread structs in a linked list or hash table. Make sure to use appropriate locking while searching a thread struct (e.g., a thread could be killed and removed while looking it up). -------------------------------------------------------------------------------- Q: We have a problem when some header files are included. There are one or two source files that we have added to os161 and made sure to list in conf/conf.kern. The problem is that we are not able to include some header files provided in os161 in our new source files. The compiler lists various errors in the header files, even though these same header files are already included in other source files. Any suggestions why this might be happening? A. You may be including these header files, or other header files that these header files depend on, in the wrong order. -------------------------------------------------------------------------------- Q: Do we need to modify the runprogram function to take in arguments (currently it takes none)? A: Yes, runprogram() should also take arguments so that you can run programs that take arguments from the menu. -------------------------------------------------------------------------------- Q: We have managed to get forktest to run, but it only runs once or twice in a row before running out of memory. Should this be happening? A: OS161 does not reclaim memory right now. You will fix that in Lab 3. However, you should be able to run forktest about 4-5 times before the kernel runs out of memory. -------------------------------------------------------------------------------- Q: Is it safe to assume that only a thread's parent will be waiting for the thread? A: The assumption is correct. Only a parent can call wait on its child/children. -------------------------------------------------------------------------------- Q: Execv argument parsing problem (C strings) When I type into the kernel: p testbin/add add 5 6 I get a fatal error. However when I type: p testbin/add add 5 6\ The program works fine and produces the correct output. A: The problem may occur if the arguments that you pass onto the stack are not word (4 byte) aligned. -------------------------------------------------------------------------------- Q: Is the farm test supposed to work once we have execv working? All the other tests seem to work for us, and farm gets through the calls to hog(), but crashes on the cat(). We noticed there's a question mark next to it in the assignment sheet meaning that it might work only partially. A: cat opens a file. We haven't implemented the open system call yet. -------------------------------------------------------------------------------- Q: When we ran GDB, it reported the following error: **** Warning: GDB can't find the start of the function at 0x80000000. GDB is unable to find the start of the function at 0x80000000 and thus can't determine the size of that function's stack frame. This means that GDB may be unable to access that stack frame, or the frames below it. This problem is most likely caused by an invalid program counter or stack pointer. However, if you think GDB should simply search farther back from 0x80000000 for code which looks like the beginning of a function, you can increase the range of the search using the `set heuristic-fence-post' command. **** A: Addresses >= 0x8000000 lie in kernel space, while addresses below that lie in the user space. When you use gdb for the kernel, it is unable to access the user space. Instead, you will need to run gdb on your user test program directly (cs161-gdb testprogram). -------------------------------------------------------------------------------- Q: Perhaps I am not exactly understanding what the specifications of null-terminated argv means, but it seems that the cmd_dispatch function in menu.c does not add a null at the end of the arguments. A: That is okay, as long as you know the number of arguments in the kernel argv structure, copy them and initialize the user space argv structure correctly. -------------------------------------------------------------------------------- Q: When we run forktest we get the following message after the 0's, 1's, 2's and 3's: "pid:8 exit:1". In the forktest code, this is reached when the thread is not the child and nowait = 0, but nowait is never modified in the code and is initialized to 0. We do not know how this could happen. A: nowait=0 means that you need to wait. It seems that your waitpid() is returning an error, with x set to 1. You need to ensure that waitpid on the child pid is working correctly. -------------------------------------------------------------------------------- Q: The uio.c and copyinout.c files both seem to have the purpose of copying data between the kernel and user space, and in fact uiomove() calls copyout/copyin in one case. 1) What's the difference between the two, and when would one use each vs the other? 2) What is UIO_USERISPACE? There's the uio_userspace, and uio_sysspace (which I assume is kernel space), then this third one. 3) Isn't copyin() dangerous since a user program can copy data into the kernel? 1. uiomove is a general routine that calls copyin/copyout for moving data from user to kernel, and kernel to user (when uio->uio_segflg is set to UIO_USERSPACE). It also allows copying data within the kernel (when segflg is set to UIO_SYSSPACE). See mk_kuio() on how the uio struct can be setup before calling uiomove. 2. UIO_USERISPACE has to do with architectures in which the instruction cache is separate from the data cache. You do not need to worry about it. 3. copyin() is needed so that the operating system can copy the parameters of system calls from user space to the kernel space. Note that copyin() is used by the kernel. It is not used by user programs. However, since copying user data into the kernel is inherently dangerous, the OS must check the parameters that are passed in to ensure that they do not compromise the kernel. For example, in a read() system call, the OS must ensure that the buffer parameter is accessible to the user program making the read call. Otherwise, the kernel when writing data to this buffer (to update it) could corrupt the kernel or other user programs.