ECE344 Fall 2026 (Sec 1) Lec 7 - Advanced IPC
Watch on YouTube →
Overview
Jon Eyolfson explains how Unix pipes, file descriptors, fork, dup2, and exec combine to support interprocess communication and shell-style redirection. He emphasizes that closing unused pipe ends is essential for EOF and termination, then shows how close-on-exec flags both prevent descriptor leaks and enable reliable detection of exec failures.
Key takeaways
- A pipe’s read end reaches EOF only after its buffer is empty and every process has closed every descriptor referring to the write end.
- After fork(), parent and child have separate descriptor tables, but inherited descriptors can still refer to the same kernel pipe.
- dup2 is the core mechanism behind shell redirection: it makes standard input or output refer to a chosen file or pipe endpoint before exec.
- exec replaces a process’s program memory but normally preserves its open file descriptors, so unused descriptors must be closed or marked close-on-exec.
- A close-on-exec pipe provides an unambiguous exec-status channel: EOF means exec succeeded, while an error payload means it failed.
Chapters
0:00
Reviewing Shell Redirection and File Descriptors
- A shell typically calls fork, configures the child’s file descriptors, then uses execve to run a program.
- Input redirection makes file descriptor 0 refer to a file before the program starts.
- Lab 2’s suggested weekly schedule is flexible; the more confusing week 2 material follows this lecture.
3:00
The pipe System Call Creates a One-Way Byte Channel
- pipe() takes space for two integers and stores the read-end descriptor at index 0 and write-end descriptor at index 1.
- The kernel manages a shared byte buffer: read consumes bytes in order, and write appends bytes.
- A read blocks while the buffer is empty; a write blocks when it is full. Linux pipes are typically 64 KiB, though that size need not be memorized.
6:15
Using fork to Send a Message Between Processes
- Calling pipe() before fork() gives both parent and child descriptors referring to the same kernel pipe.
- In the example, the parent closes its read end and writes “Hello from parent”; the child closes its write end and reads the message.
- After fork(), the processes have independent descriptor tables, but corresponding descriptors still refer to the shared pipe resource.
11:00
Pipe EOF Requires Every Write End to Be Closed
- read() returns 0 after buffered data is drained only when no process has the pipe’s write end open.
- Leaving the parent’s write descriptor open keeps the child blocked in read(), while the parent may be blocked in wait().
- Close unused pipe ends immediately after fork(); process termination closes remaining descriptors, but explicit cleanup is better practice.
20:00
dup2 Connects Pipe Ends to Standard Input and Output
- dup2(oldfd, newfd) makes newfd refer to the same kernel resource as oldfd, closing newfd first if it was already open.
- A shell implements redirection by opening a file and using dup2 to replace descriptor 0 or 1.
- For a pipeline, dup2 can connect one process’s standard output to the pipe’s write end and another process’s standard input to its read end.
26:48
Running tr Through a Pipe and Avoiding Inherited Write Ends
- The child redirects descriptor 0 to the pipe’s read end, closes the original pipe descriptors, and execs tr to uppercase incoming text.
- The parent writes its message to the pipe and closes the write end so tr can observe EOF and terminate.
- If the child leaves a pipe write descriptor open, exec does not close it by default; tr can then wait forever for input that will never arrive.
34:13
Inspecting Leaked Descriptors and Setting Close-on-Exec
- On Linux, /proc can show a process’s open descriptors and whether they refer to a pipe’s read or write end.
- A useful exec convention is to leave the new program only descriptors 0, 1, and 2, connected to the intended resources.
- The close-on-exec flag automatically closes a descriptor during exec; pipe2 can create pipe descriptors with this flag set.
39:00
Close-on-Exec Flags and the Ambiguity of Exit Status
- Without extra communication, a parent cannot distinguish an exec failure from a successfully executed program that exits with the same status.
- Close-on-exec applies to individual descriptor numbers, not generally to every descriptor referring to the same resource.
- When dup2 duplicates a descriptor onto standard input or output, the target descriptor can remain open across exec while the original close-on-exec descriptors are closed.
43:13
Reporting exec Failures Through a Close-on-Exec Pipe
- Create a pipe with close-on-exec enabled before fork(); if the child’s exec succeeds, the kernel closes its pipe descriptors automatically.
- If exec fails, the child still has the pipe and can write the error number before exiting.
- The parent closes its write end and reads: EOF indicates successful exec, while received error data indicates failure, such as a missing executable.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Jon Eyolfson.