Processes & IPC — fork, exec, pipes
Unix এভাবেই নতুন প্রোগ্রাম তৈরি করে
1. What Is a Process?
Process = চলমান প্রোগ্রামের একটি instance। নিজস্ব memory space, file descriptor ও state থাকে। Linux/macOS-এ প্রতিটি command-ই একটি process।
2. fork()
#include <stdio.h>
#include <unistd.h>
int main(void) {
pid_t pid = fork();
if (pid < 0) {
perror("fork"); return 1;
} else if (pid == 0) {
printf("child: my pid = %d, parent = %d\n", getpid(), getppid());
} else {
printf("parent: my pid = %d, child = %d\n", getpid(), pid);
}
return 0;
}
fork দুবার return করে — parent-এ child-এর PID, child-এ 0। Error হলে -1।
3. exec — Replace the Program
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t pid = fork();
if (pid == 0) {
char *args[] = { "ls", "-l", NULL };
execvp("ls", args);
perror("exec"); // only if exec fails
return 1;
}
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) printf("ls exited with %d\n", WEXITSTATUS(status));
return 0;
}
exec current process-এর memory image replace করে — new program-এ রূপান্তর। সফল হলে কখনোই return করে না। fork+exec মিলে নতুন সেই program চালানো।
4. wait / waitpid
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status)) printf("exit=%d\n", WEXITSTATUS(status));
wait না করলে zombie হয়ে থাকে (kernel-এ entry রয়ে যায়)। Long-running server-এ সতর্ক থাকুন।
5. Pipes — One-Way IPC
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main(void) {
int fd[2];
pipe(fd); // fd[0] = read, fd[1] = write
pid_t pid = fork();
if (pid == 0) { // child — writer
close(fd[0]);
const char *msg = "Hello from child!";
write(fd[1], msg, strlen(msg));
close(fd[1]);
} else { // parent — reader
close(fd[1]);
char buf[64] = {0};
read(fd[0], buf, sizeof buf - 1);
close(fd[0]);
printf("parent got: %s\n", buf);
wait(NULL);
}
return 0;
}
6. Mini-Shell — ls | wc -l
Pipeline-এর সব কৌশল: fork পাইপের দু-পাশে, dup2 দিয়ে stdin/stdout redirect, তারপর exec। এটাই আসল shell-এর কাজ।
int p[2]; pipe(p);
if (fork() == 0) { // left: ls
close(p[0]);
dup2(p[1], STDOUT_FILENO);
close(p[1]);
execlp("ls", "ls", NULL);
}
if (fork() == 0) { // right: wc -l
close(p[1]);
dup2(p[0], STDIN_FILENO);
close(p[0]);
execlp("wc", "wc", "-l", NULL);
}
close(p[0]); close(p[1]);
wait(NULL); wait(NULL);
7. Practice Problems
- Fork a child and print PIDs from both sides.Fork করে দুই side থেকে PID।
✨ Show Answer
Section 2 reference।
- Fork + exec to run
ls -l.Fork+exec দিয়ে ls চালান।✨ Show Answer
Section 3 reference।
- Parent waits for child and prints its exit code.Parent wait করে exit code।
✨ Show Answer
waitpid(pid, &status, 0); WEXITSTATUS(status)— Section 3 reference। - Create a zombie process deliberately; then fix.Zombie তৈরি ও ফিক্স।
✨ Show Answer
Child exit করলে parent-এ wait না দেওয়া → zombie। Fix:
wait()call, বা SIGCHLD handler, বাsignal(SIGCHLD, SIG_IGN)। - Pipe between parent and child; child capitalizes text.Pipe দিয়ে child uppercase করুক।
✨ Show Answer
Two pipes (parent→child text, child→parent result)। Child loop-এ read-toupper-write। Parent text পাঠিয়ে উত্তর পড়ে।
ls | wc -lvia fork + pipe + exec.ls|wc -l।✨ Show Answer
Section 6 reference।
- Three-stage pipeline:
cat | grep | sort.Three-stage pipeline।✨ Show Answer
Two pipes, three forks। Middle child: stdin=pipe1-read, stdout=pipe2-write। Loop-এ n-stage generalize করুন।
- Write a mini-shell supporting cd, exit and simple commands.Mini-shell।
✨ Show Answer
Read line → parse tokens → built-in (cd, exit) হলে parent-এ handle, নতুবা fork+execvp। 50 লাইনেই একটা কার্যকর shell।
- Handle SIGINT so Ctrl-C doesn't kill your shell.SIGINT handle।
✨ Show Answer
Parent-এ
signal(SIGINT, SIG_IGN);। Child-এ default রাখুন — Ctrl-C শুধু foreground child-কে মারবে। - Spawn N children; measure creation time.N-টি child spawn time।
✨ Show Answer
Loop-এ fork; child immediately exit, parent wait।
clock_gettimeদিয়ে time। Linux-এ সাধারণত 50-200 µs/fork — copy-on-write-এর কারণে। - Use
popen/pcloseto read output of another command.popen/pclose।✨ Show Answer
FILE *f = popen("ls -l", "r"); char line[256]; while (fgets(line, sizeof line, f)) fputs(line, stdout); pclose(f); - Compare process creation cost (fork) with thread creation (pthread).Fork vs pthread creation cost।
✨ Show Answer
pthread সাধারণত 10-50× দ্রুত — shared address space, নতুন memory space copy লাগে না। fork copy-on-write হলেও new page table, file table-এর জন্য ~100 µs।
- Share memory with parent and child via
mmapMAP_SHARED.mmap shared memory।✨ Show Answer
void *p = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);— fork-এর পর parent এবং child উভয়ই একই pages share করবে। - Signal a child from parent and handle it.Parent child-কে signal।
✨ Show Answer
Child-এ
signal(SIGUSR1, handler);। Parent-এkill(child_pid, SIGUSR1);। Handler-এ async-safe কাজ করুন (printf safe নয়, volatile flag set OK)। - Why is copy-on-write crucial for fork's efficiency?COW fork-এ কেন জরুরি?
✨ Show Answer
fork-এ parent-এর সব page আসলে কপি হয় না — দুই process একই physical pages share করে। যতক্ষণ না কেউ write করছে, কপি হবে না। Exec করলে পুরোটাই discard — কোনো copy-ই অপচয় হতো।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Process | An independent running program with its own memory. | নিজস্ব মেমরি-যুক্ত একটি চলমান প্রোগ্রাম। |
| PID | Process ID — kernel's identifier for a process. | Kernel-এর দেওয়া process-শনাক্তকারী। |
fork | Creates a near-identical child process. | প্রায় সমান একটি child process তৈরি। |
exec family | Replaces the current process image with a new program. | চলমান process-কে নতুন program দিয়ে replace। |
wait / waitpid | Parent waits for a child to finish. | Parent child শেষ হওয়ার অপেক্ষা করে। |
| Zombie Process | Child has exited but parent has not yet reaped it. | Exit হওয়া child — যাকে parent এখনও reap করেনি। |
| Orphan Process | Child whose parent already exited; adopted by init. | Parent শেষ — init-এর কাছে দত্তক। |
| IPC | Inter-Process Communication. | Process-এর মধ্যে যোগাযোগ। |
| Pipe | One-way byte stream between related processes. | একমুখী byte-stream সংযোগ। |
| Named Pipe (FIFO) | Pipe accessible via a filesystem name. | Filename-যুক্ত pipe। |
| Signal | Asynchronous notification (SIGINT, SIGKILL...). | Asynchronous সংকেত। |
| Shared Memory | Region mapped into multiple processes for fast IPC. | একাধিক process-এ যুক্ত মেমরি। |
| Message Queue | Kernel-managed queue for IPC messages. | Kernel-managed message queue। |
| Copy-on-Write | Pages shared after fork until one writes. | Fork-এর পর page শেয়ার্ড — কেউ লিখলে কপি হয়। |
dup2 | Duplicates a file descriptor — used for redirection. | FD নকল করা — redirection-এ ব্যবহার্য। |
Summary — Module 37
fork নতুন process; exec program replace; wait reap করে; pipe+dup2+fork+exec = Unix shell। Backend system এই primitive-এর উপরেই দাঁড়িয়ে।