CS 111: Processes, file descriptors & the Unix V6 filesystem

Terminal running ls -lOS layers: users, application programs, operating system, hardwareSSDRAM stickDeskUserCPUTicketDocument iconLibrarianCrash outcomes: journaling vs ordered writes vs fsckFile Allocation Table
mainprintfforkprintfreturnprintfreturn“Greetings…”“Bye-bye…”“Bye-bye…”PARENTCHILD
Unix V6 disk click anything, or step through a lookup
512 B each→ sizes of other regions16 inodes × 32 B per block0 = free, 1 = usedfiles, directories, indirect blocks
9 hops
Inode table · each inode is 32 B
Inode 1/
type: dir
mode: small
size: 96
nlink: 6 (refs)
i_addr:
Inode 3/usr
type: dir
mode: large
size: 131584
nlink: 4 (refs)
i_addr:
Inode 12
type: dir
mode: small
size: 544
nlink: 2 (refs)
i_addr:3241
Inode 14/usr/files
type: dir
mode: small
size: 64
nlink: 2 (refs)
i_addr:62
Inode 16/usr/note.txt
type: file
mode: small
size: 6
nlink: 2 (refs)
i_addr:
Blocks · 512 B each
Block 2
inode table
inodes 1–16
1, 3, 12, 14, 16 shown above
Block 56
dir /
.1
..1
bin13
tmp10
other9
usr3
Block 67
dir /usr
.3
..1
apps21
files14
no “note.txt” here
Block 122
indirect
872999135346…
Block 421
dir /usr
icon.png30
doc.pdf15
note.txt16
copy.txt16
Block 545
indirect
565
Block 876
data
hello!
How V6 finds a file

Inodes say where a file's blocks are; directory blocks map names to inode numbers. Click an inode to see the blocks it points to, click a directory entry to jump to its inode, or press Start to follow /usr/note.txt one disk read at a time.

block = 512 Binode = 32 Bdir entry = 14 B name + 2 B inumber32 entries per blocksmall: 8 directlarge: 7 singly + 1 doubly
Per processSystem-wide, sharedOne per filewrite(1, buf, 6) →read(3, buf, 4096) →close(fds[1]) →→ bytes from texture.png appearParent fd table · PID 111Child PID 112 (after fork)Open file tableVnode tablefd 0stdincin >>fd 1stdoutcout <<fd 2stderrcerr <<fd 3texture.pngfd 4fds[0]pipe readfd 5fds[1]pipe writefd 0closedfd 1closedfd 2closedfd 3closedfd 4closedfd 5closedTerminalread/write · refs 3texture.pngoffset 0 · refs 1Pipe read endread-only · refs 1Pipe write endwrite-only · refs 1Terminaldisk:inode 312 (/dev/ttys001)→ char device, major 16, minor 1memory:vnode → copy of inode 312 + refcount 1+ type "character device"texture.pngdisk:inode 37 → size 10000,blocks [812, 813, 950, …]memory:vnode → copy of inode 37 + refcount 1+ type "regular file"Pipe bufferdisk:none: a pipe has no inodeon diskmemory:vnode → refcount 2 + type "pipe"+ 64 KB buffer in kernel memory$ buf[4096]: (empty)
1 / 7 · Parent's table

The parent has fds 0–2 on the terminal, opened texture.png as fd 3, and called pipe(fds): fd 4 = read end, fd 5 = write end. An fd is just an index into this process's table. The entry it points to lives in the system-wide open file table, which counts references (refs). Each open file entry points at a vnode: the kernel's in-memory copy of the file's inode, with its own refcount of how many open file entries use it.

⚠ Important: This is why pipes need you to close unused ends. A reader only gets end-of-file (read returns 0) when the write end’s ref reaches 0. If the reader forgot to close its own copy of fds[1], the count never reaches 0, and it waits forever.
File
Descriptors
Array of
info about open
files for this process
Multi Processing
– Runs a program = new process with pid
→ clones 1st process into 2nd
parent
↓ 111
child
↓ 112
returns 112
returns 0
kill(process, SIG_KILL)
→ returns pid of exited child
(child)
(flags)
-1 for first termination
return 124 // timed out;
→ runs ANOTHER program in the current process
i.e. process → finished but not cleared up
Shell: forks off child process to run a command
(111)
fork()
child (112)
execvp(game)
child (112)
waitpid(112)
OS: Windows, Linux, iOS, Android, Linux
Files, VM
Network, I/O
Keyboard, USB
CPU, RAM, SSD
Disk/SSD
game.exe
photos.jpg
essay.pdf
save game
User
kernel
RAM
makes decisions
System Calls –
switches to kernel mode and then back to user mode
→ returns file descriptor (FD)
→ returns 0, -1
• ticket number, e.g. 3, 4, 5
• 0, 1, 2 are pre-opened
input, output, error
→ returns bytes read, 0 EOF, -1 error
↕ both may transfer fewer bytes
→ returns bytes read, 0 EOF, -1 error
Note: not present
in Unix V6
read only
or
1.
2.
3.
• Persistent
• Sector addressable
• 256–1024 GB
• Non-persistent
• Byte addressable
• 8–32 GB
fork ()
pid_t waitpid(pid_t pid, int *status, int options)
execvp(const char *path, char *argv[])
int open (const char *pathname, int flag)
int close (int fd)
ssize_t read (int fd, void *buf, size_t count)
ssize_t write (int fd, void *buf, size_t count)
mountv6
Unix V6
Claim inode 16: allocated, nlink 1, size 0
Set bitmap bit for block 876
Write the text into the block 876
4.
Update inode 16: size, i_addr[0] =
876
5.
Write disk and (16, “note.txt”) into free slot
100%