System call semantics and kernel design
- System call behavior affects kernel data structures
- The relationships between semantics and data structures are fascinating, important, and broadly applicable (e.g. to APIs); OS issues make these relationships clear
Process communication
- Many system calls involve process interactions
- How does a behave with respect to
fork? - Some system calls refer to shared resources, such as files; processes may interact there
- How does a behave with respect to
- Consider these interactions when designing a system call
Example: getppid, exit, waitpid
getppidreturns the parent process ID- Unless the parent process has exited, in which case it returns 1
exit(S)sets a process’s exit status and marks the process as non-runnablewaitpid(pid, status, options)blocks until a child process exits, then returns that process’s ID and sets*statusto its exit statuspid == 0matches any child process- If no matching child process exists, returns
E_CHILD - If no matching child process has exited and
options == W_NOHANG, returnsE_AGAIN - Otherwise, blocks until a matching child process has exited
- It is only possible to wait for a child process once
- A process ID is not reused until
waitpidhas returned the status
Questions
- What bookkeeping structures are required to support these semantics?
- What performance (e.g., computational complexity) ensues from different bookkeeping structures?
- What synchronization is required to access those bookkeeping structures?
- Often a tradeoff between bookkeeping and computational complexity
- Many points on the tradeoff are valid!
- Don’t overbuild!!
Motivating questions
- Support
getppid/exit/waitpidwith little additional state - …with efficient operations in terms of computational complexity
- …with minimal storage needs for exited processes
Example: fork return value
- Consider two possible
forksemantics - If
forksuccessfully creates a new process, then the new process ID…- Is any currently-unused process ID
- Is the smallest available currently-unused process ID
- Consequences?
Example: File-related system calls
-
fd = open(path, oflag, [mode]) -
close(fd) -
read(fd, buf, siz) -
write(fd, buf, siz) -
lseek(fd, off) -
dup2(oldfd, newfd) -
[rfd, wfd] = pipe() -
Console, pipe, disk files all support
readandwrite!
Specific and general questions
-
How extensible should the file interface be?
-
Where should this extensibility be implemented?
- In
readandwrite? - Somewhere else?
- In
-
Where is the file position stored?
-
Bookkeeping structures?
-
Performance?
-
Synchronization?