Lab 2: Processes
These questions were written by Jerry Cain and Ryan Eberhardt.
Before the end of lab, be sure to fill out the lab checkoff sheet here!
Problem 1: Virtual Memory
Assume the OS allocates virtual memory to physical memory in 4096-byte pages.
- If the virtual address
0x7fffa2efc345
maps to the physical page in main memory whose base address is0x12345aab8000
, what range of virtual addresses around it would map to the same physical page? - What’s the largest size a character array can be before it absolutely must map to three different physical pages?
- What’s the smallest size a character array can be and still map to three physical pages?
- In Assignment 1, the starter code used a syscall called
mmap
to create a new segment in memory that is mapped to a file on disk. Whenever memory is read from offsetx
within that segment, the corresponding data is loaded from disk into the memory segment. Based on what you know about virtual memory, speculate about how this might be implemented. (You’re free to add any necessary data to rows in the page mapping table.) - The standard page size for most systems is 4KB. Why might it be helpful to use a larger page size? Why might it be helpful to use a smaller page size?
For fun, optional reading, read these two documents (though you needn’t do this reading, since it goes beyond the scope of my lecture discussion of virtual memory):
- http://www.cs.cmu.edu/afs/cs/academic/class/15213-f15/www/lectures/17-vm-concepts.pdf. These are lecture slides that Bryant, O’Hallaron, and their colleagues rely on while teaching the CMU equivalent of CS110 (they’re on a 15-week semester, so they go into more depth than we do).
- http://www.informit.com/articles/article.aspx?p=29961&seqNum=2: This is an article written some 15 years ago by two senior research scientists at HP Labs who were charged with the task of porting Linux to IA-64.
Problem 2: File descriptors
- Consider the following code:
int main() { int fd = open("/cplayground/code.cpp", O_RDONLY); printf("Using file descriptor %d\n", fd); // Try reading some bytes: char buf[16]; ssize_t num_read = read(fd, buf, sizeof(buf)); printf("Read %ld bytes\n", num_read); // Close file descriptor close(fd); }
-
What does
open
do to the file descriptor, open file, and vnode tables? What aboutread
? What aboutclose
?Open this Cplayground and press “Debug” to start the program. Navigate to the “Open Files” tab to see a visualization of the three tables. Try stepping through the code line-by-line to confirm your intuition.
-
What happens to the file descriptor, open file, and vnode tables if you add an extra
open
call?int fd = open("/cplayground/code.cpp", O_RDONLY); int fd2 = open("/cplayground/code.cpp", O_RDONLY);
Use Cplayground to confirm your intuition.
-
- The
dup
system call accepts a valid file descriptor, claims a new, previously unused file descriptor, configures that new descriptor to alias the same file session as the incoming one, and then returns it. Briefly outline what happens to the relevant open file table and vnode table entries as a result ofdup
being called. (Readman dup
if you’d like, though don’t worry about error scenarios).
Problem 3: Creating processes
- Consider the following code (try it on Cplayground):
int main() { int fd1 = open("/cplayground/code.cpp", O_RDONLY); printf("File descriptor 1: %d\n", fd1); fork(); int fd2 = open("/cplayground/code.cpp", O_RDONLY); printf("File descriptor 2: %d\n", fd2); close(fd1); close(fd2); }
What do the file descriptor, open file, and vnode table entries look like after each syscall? Use the Cplayground debugger to confirm your intuition.
- Consider the following code (try it on
Cplayground:
int main() { // Desired output: "Hello from child process" and // "Hello from parent process" (in no particular order) pid_t pid = fork(); // fork() returns twice: // * The child process will see a return value of 0 // * The parent process will see a return value of the child's PID if (pid == 0) { printf("Hello from child process!\n"); } printf("Hello from parent process!\n"); return 0; }
This prints “Hello from the child process!” in the child process, and prints “Hello from the parent process!” in the parent process. However, if you run it, there’s an extra print statement! Why does this happen? How can we fix the code to get rid of it?
- Your terminal can be configured so that a process dumps core – that is,
generates a data file named
core
– whenever it crashes (because it seg faults, for instance.) Thiscore
file can be loaded into and analyzed withingdb
to help identify where and why the program is crashing. Assuming we can modify the program source code and recompile, how might you programmatically generate a core dump at specific point in the program while allowing the process to continue executing? (Your answer might include a very, very short code snippet to make its point.)