wc calls read(0, buf, 512). Inside the kernel, fileread must decide whether this
read goes to a pipe, the console driver or a file on disk. What does it look at?
Test yourself · category 19 of 20
Files, pipes, the console and the UART
How one read or write is routed by struct file, how a pipe’s two counters and two channels move bytes between processes, and how the console and the UART share one wire between processes, interrupt handlers and printk.
A process creates a pipe and writes to it, and nobody ever reads. How many bytes can
it write into the empty pipe before pipewrite puts it to sleep?
True or false: after kfork, the parent and the child each have their own
struct file for the console, so the child moving a file offset or closing its copy
cannot affect the parent’s.
Why?
wc is reading from a pipe. The pipe is empty, and the last write end has been
closed (writeopen == 0). What does piperead do?
In piperead, click the line that checks whether any writer is still left on the
pipe.
Your pick: none yet (click a line in the code)
consoleintr treats some typed characters specially. Match each key with what the
kernel does when it arrives.
When you type a key, consoleintr echoes it with consputc, which calls
uartputc_sync and spins on the UART. Why does it not send the echo through
uartwrite, like a process’s write does?
A process with only descriptors 0, 1 and 2 open calls pipe(p), which succeeds.
Which statements are true right afterwards?
cat makes one write(1, buf, 512) to the console. How many times does
consolewrite call uartwrite for it?
When the last reference to a file goes away, fileclose copies *f into the local
ff, frees the slot and releases ftable.lock, and only then calls pipeclose
or iput. Why not do the cleanup while still holding ftable.lock?
In ls | wc, wc is asleep in piperead on an empty pipe. ls has written all
its output and now exits. Put the events that end wc’s reading in order.
pipeclosesetswriteopen = 0and callswakeup(&pi->nread)wcreturns fromsleep, retakespi->lockand re-checks the loop condition on line 119- The copy loop breaks at once with
i = 0, andreadreturns 0 towc wc’s read loop ends and it prints its countslscallsexit(0);kexitstarts closing its open descriptorsfileclosedrops the write end’srefto 0 and frees the ftable slot
nread and nwrite are never reset; they only count up, and positions are found with
% PIPESIZE. What does this design buy compared with two indices that wrap back to 0
at 512?
True or false: pipewrite calls copyin while holding the spinlock pi->lock, and
this is safe in this kernel.
Why?
cat with no arguments is in read(0, buf, 512) on the console. You type h, i,
then Control-D (no Enter). What does that read return?
Hart 2 is idle in its scheduler (between intr_on and intr_off) when a UART
interrupt arrives. uartintr calls consoleintr, which takes cons.lock and
echoes the key. Hart 2 is now inside uartputc_sync, just after its push_off().
What is its state?
uartwrite serializes writers with tx_lock, a sleep-lock. Why would an
ordinary spinlock not work here?
Three harts call printk at the same moment. Click the line that keeps their
messages from interleaving character by character.
Your pick: none yet (click a line in the code)
A program calls open("README", omode) with omode = 0x401. Using
kernel/fcntl.h and sys_open, decode it and predict the result.
Value: 0x401
A process’s write to the console goes consolewrite → uartwrite. Which of
these can happen on that path in this kernel?
A long program runs that never reads the console, so nobody calls consoleread.
Before it started, the console input buffer was empty (r == w == e). You now type
200 ordinary letters without pressing Enter. How many of them are echoed on the
screen?
On hart 0, cat is in uartwrite holding tx_lock, halfway through a 32-byte
batch. On harts 1 and 2 other things are happening. Which of these can put bytes on
the screen between two bytes of cat’s batch?
True or false: uartwrite calls sleep_prepare without holding any spinlock, so
if the transmit-done interrupt arrives between the LSR check on line 87 and the
sleep on line 91, the wakeup is lost and the process can sleep forever.
Why?
A program calls write(fd, buf, 10000) on a regular file, and every writei
succeeds. How many file-system transactions (begin_op … end_op pairs) does
filewrite run? (MAXOPBLOCKS is 10, BSIZE is 1024.)
Continue from cat reading h, i, Control-D: the first read returned 2. cat
writes hi and calls read(0, buf, 512) again. Why does this second read return 0
immediately instead of sleeping?
When both ends of a pipe are closed, pipeclose runs release(&pi->lock) on line
70 and only then kfree((char *)pi) on line 71. What would go wrong if the two lines
were swapped?