1#!/usr/bin/env bash
2set -euo pipefail
3
4# Named Pipe (FIFO) Demonstrations
5# Shows how to use named pipes for inter-process communication
6
7# Cleanup function
8cleanup() {
9 echo
10 echo "Cleaning up..."
11 rm -f /tmp/demo_fifo_* /tmp/producer_done
12 jobs -p | xargs -r kill 2>/dev/null || true
13}
14
15# Set trap for cleanup
16trap cleanup EXIT INT TERM
17
18echo "=== Named Pipe (FIFO) Demonstrations ==="
19echo
20
21# --- Demo 1: Basic FIFO usage ---
22demo_basic_fifo() {
23 echo "1. Basic FIFO Usage"
24 echo "-------------------"
25
26 local fifo="/tmp/demo_fifo_basic"
27
28 # Create named pipe
29 mkfifo "$fifo"
30 echo "Created FIFO: $fifo"
31
32 # Producer (background)
33 {
34 echo "Producer: Starting..."
35 for i in {1..5}; do
36 echo "Message $i"
37 sleep 0.5
38 done
39 } > "$fifo" &
40
41 # Consumer (foreground)
42 echo "Consumer: Reading from FIFO..."
43 while IFS= read -r line; do
44 echo " Received: $line"
45 done < "$fifo"
46
47 echo "Consumer: Done"
48
49 rm -f "$fifo"
50 echo
51}
52
53# --- Demo 2: Producer-Consumer pattern ---
54demo_producer_consumer() {
55 echo "2. Producer-Consumer Pattern"
56 echo "----------------------------"
57
58 local fifo="/tmp/demo_fifo_pc"
59 local done_flag="/tmp/producer_done"
60
61 mkfifo "$fifo"
62 rm -f "$done_flag"
63
64 # Producer: Generate data
65 producer() {
66 echo "Producer: Generating data..."
67 for i in {1..10}; do
68 # Simulate some work
69 local result=$((i * i))
70 echo "$i squared is $result"
71 sleep 0.2
72 done
73 echo "DONE" # Signal completion
74 touch "$done_flag"
75 }
76
77 # Consumer: Process data
78 consumer() {
79 echo "Consumer: Processing data..."
80 local count=0
81 while IFS= read -r line; do
82 if [[ "$line" == "DONE" ]]; then
83 break
84 fi
85 ((count++))
86 echo " [$count] Processed: $line"
87 done
88 echo "Consumer: Processed $count items"
89 }
90
91 # Start producer in background
92 producer > "$fifo" &
93 local producer_pid=$!
94
95 # Start consumer in foreground
96 consumer < "$fifo"
97
98 # Wait for producer to finish
99 wait "$producer_pid"
100
101 rm -f "$fifo" "$done_flag"
102 echo
103}
104
105# --- Demo 3: Bidirectional communication ---
106demo_bidirectional() {
107 echo "3. Bidirectional Communication (Two FIFOs)"
108 echo "------------------------------------------"
109
110 local request_fifo="/tmp/demo_fifo_request"
111 local response_fifo="/tmp/demo_fifo_response"
112
113 mkfifo "$request_fifo"
114 mkfifo "$response_fifo"
115
116 # Server: Responds to requests
117 server() {
118 echo "Server: Starting..."
119 while IFS= read -r request; do
120 if [[ "$request" == "QUIT" ]]; then
121 echo "GOODBYE" > "$response_fifo"
122 break
123 fi
124
125 # Process request (simple echo server with uppercase)
126 local response="${request^^}"
127 echo "Server: Request='$request', Response='$response'"
128 echo "$response" > "$response_fifo"
129 done < "$request_fifo"
130 echo "Server: Shutting down"
131 }
132
133 # Client: Sends requests
134 client() {
135 echo "Client: Connecting..."
136 local -a requests=("hello" "world" "test" "QUIT")
137
138 for req in "${requests[@]}"; do
139 echo "Client: Sending '$req'"
140 echo "$req" > "$request_fifo"
141
142 # Read response
143 IFS= read -r response < "$response_fifo"
144 echo "Client: Got response '$response'"
145 sleep 0.3
146 done
147 echo "Client: Done"
148 }
149
150 # Start server in background
151 server &
152 local server_pid=$!
153
154 # Give server time to start
155 sleep 0.5
156
157 # Run client
158 client
159
160 # Wait for server
161 wait "$server_pid"
162
163 rm -f "$request_fifo" "$response_fifo"
164 echo
165}
166
167# --- Demo 4: Load balancing with multiple workers ---
168demo_load_balancing() {
169 echo "4. Load Balancing with Multiple Workers"
170 echo "----------------------------------------"
171
172 local job_fifo="/tmp/demo_fifo_jobs"
173 mkfifo "$job_fifo"
174
175 # Worker function
176 worker() {
177 local worker_id=$1
178 echo "Worker $worker_id: Started"
179
180 while IFS= read -r job; do
181 if [[ "$job" == "STOP" ]]; then
182 break
183 fi
184
185 # Simulate work
186 echo " Worker $worker_id: Processing job '$job'"
187 sleep 0.5
188 echo " Worker $worker_id: Completed job '$job'"
189 done
190
191 echo "Worker $worker_id: Stopped"
192 }
193
194 # Start multiple workers
195 local num_workers=3
196 echo "Starting $num_workers workers..."
197
198 for i in $(seq 1 $num_workers); do
199 worker "$i" < "$job_fifo" &
200 done
201
202 # Give workers time to start
203 sleep 0.5
204
205 # Dispatcher: Send jobs
206 echo
207 echo "Dispatcher: Sending jobs..."
208 {
209 for job_num in {1..6}; do
210 echo "Job-$job_num"
211 done
212
213 # Send stop signal to each worker
214 for i in $(seq 1 $num_workers); do
215 echo "STOP"
216 done
217 } > "$job_fifo"
218
219 # Wait for all workers
220 wait
221
222 rm -f "$job_fifo"
223 echo
224}
225
226# --- Demo 5: Pipeline with FIFO ---
227demo_pipeline() {
228 echo "5. Complex Pipeline with FIFO"
229 echo "-----------------------------"
230
231 local fifo1="/tmp/demo_fifo_pipe1"
232 local fifo2="/tmp/demo_fifo_pipe2"
233
234 mkfifo "$fifo1" "$fifo2"
235
236 # Stage 1: Generate numbers
237 {
238 echo "Stage 1: Generating numbers..."
239 seq 1 10
240 } > "$fifo1" &
241
242 # Stage 2: Square the numbers
243 {
244 echo "Stage 2: Squaring..."
245 while read -r num; do
246 echo $((num * num))
247 done
248 } < "$fifo1" > "$fifo2" &
249
250 # Stage 3: Sum the results
251 {
252 echo "Stage 3: Summing..."
253 local sum=0
254 while read -r num; do
255 ((sum += num))
256 done
257 echo " Total sum: $sum"
258 } < "$fifo2"
259
260 # Wait for all stages
261 wait
262
263 rm -f "$fifo1" "$fifo2"
264 echo
265}
266
267# --- Demo 6: Monitoring with timeout ---
268demo_timeout() {
269 echo "6. FIFO with Timeout"
270 echo "--------------------"
271
272 local fifo="/tmp/demo_fifo_timeout"
273 mkfifo "$fifo"
274
275 # Slow producer
276 {
277 sleep 2
278 echo "Delayed message"
279 } > "$fifo" &
280 local producer_pid=$!
281
282 echo "Consumer: Waiting for message (3 second timeout)..."
283
284 # Read with timeout using a background process
285 {
286 sleep 3
287 echo "TIMEOUT"
288 } > "$fifo" &
289 local timeout_pid=$!
290
291 # Read first message that arrives
292 IFS= read -r message < "$fifo"
293
294 if [[ "$message" == "TIMEOUT" ]]; then
295 echo " Result: Timed out!"
296 kill $producer_pid 2>/dev/null || true
297 else
298 echo " Result: Got message: '$message'"
299 kill $timeout_pid 2>/dev/null || true
300 fi
301
302 wait 2>/dev/null || true
303
304 rm -f "$fifo"
305 echo
306}
307
308# Main execution
309main() {
310 demo_basic_fifo
311 demo_producer_consumer
312 demo_bidirectional
313 demo_load_balancing
314 demo_pipeline
315 demo_timeout
316
317 echo "=== All Demos Complete ==="
318}
319
320main "$@"