এই পর্বে যা শিখবেন
- OS-এর লিখিত উত্তর পরীক্ষকের নম্বর-ভাগের ক্রমে সাজানো, আর ২, ৫ ও ১০ নম্বরের উত্তরে কতটুকু লিখতে হয়
- Process state, fork/exec, threading model, scheduling, critical section, deadlock আর Banker's-এর ক্লাসিক দীর্ঘ প্রশ্নের নির্ভুল মডেল উত্তর — প্রমাণসহ
- Paging বনাম segmentation, TLB ও EAT-এর সূত্র বের করা, Belady's anomaly আর stack algorithm-এর যুক্তি, thrashing আর working set
- File allocation, journaling, RAID, ACL বনাম capability, Popek–Goldberg, container বনাম VM আর Lamport clock — তুলনার টেবিল আর ছবিসহ উত্তর
- ভাইভায় এক–তিন বাক্যে নির্ভুল উত্তর, follow-up সামলানো, না জানলে সৎ থাকা, আর AI-এর দেওয়া উত্তর যাচাই করা
১ · পরীক্ষক কী খোঁজেন — OS উত্তরের কাঠামো আর নম্বর-ভাগ
MCQ-তে উত্তর হয় ঠিক, নয় ভুল। লিখিত পরীক্ষা আর ভাইভা আলাদা: দুজন প্রার্থী একই deadlock জানেন, কিন্তু একজন বেশি নম্বর পান — কারণ তিনি চারটি শর্ত নির্ভুল লিখেছেন, একটি resource-allocation graph এঁকেছেন, দুই থ্রেড আর দুই lock-এর উদাহরণ দিয়েছেন, প্রতিটি প্রতিরোধের দাম বলেছেন, আর শেষে বলেছেন Linux-এর lockdep কীভাবে নিয়ম-ভাঙা ধরে। খাতা দেখার সময় পরীক্ষকের হাতে থাকে একটি মার্ক-স্কিম — কোন অংশে কত নম্বর। উত্তর যদি সেই অংশগুলো চোখের সামনে সাজিয়ে রাখে, নম্বর হারায় না।
- সংজ্ঞা (এক–দুই বাক্য): নির্ভুল, শর্তসহ। “Semaphore হলো একটি পূর্ণসংখ্যা আর একটি অপেক্ষার সারি, যাতে শুধু দুটি অবিভাজ্য কাজ চলে — wait আর signal.”
- ছবি: state diagram, Gantt chart, page table, RAG, log-এর বিন্যাস — যা দশ বাক্যের কাজ এক নজরে করে। ছবির প্রতিটি তীর বা ঘরের নাম লিখুন।
- উদাহরণ: ছোট, নির্দিষ্ট সংখ্যায় — তিনটি প্রসেস, দুটি lock, একটি ঠিকানা। সংখ্যা দিলে হিসাব দেখান।
- সুবিধা ও অসুবিধা: প্রতিটি নকশার দাম আছে — গতি, জায়গা, ন্যায্যতা, জটিলতা। তুলনার প্রশ্নে একই মাপকাঠির সারি দিয়ে টেবিল।
- বাস্তব সিস্টেম: এক লাইনে Linux, Windows বা অন্য কোনো সিস্টেমে কোথায় এটি আছে — যেমন “Linux-এ PCB-র নাম task_struct”. এটি সাধারণত শেষ এক নম্বর এনে দেয়।
যেমন “Semaphore কী? — ৫ নম্বর”: সংজ্ঞা (১), মান আর অপেক্ষার সারির ছোট টেবিল (১), bounded buffer-এ ব্যবহার (১), ভুল ক্রমে wait দিলে deadlock (১), POSIX-এর sem_wait/sem_post (১)। নিচের প্রতিটি মডেল উত্তর এই ক্রম যথাসম্ভব মেনেছে।
প্রশ্নের ধরন অনুযায়ী নম্বর-ভাগ
| ধরন | যাতে নম্বর আসে | যাতে নম্বর কাটে |
|---|---|---|
| সংজ্ঞা ও পার্থক্য | নির্ভুল সংজ্ঞা; পার্থক্যে একই মাপকাঠির সারি (address space, খরচ, ব্যর্থতার প্রভাব, উদাহরণ) | দুই কলামে আলাদা আলাদা কথা; উদাহরণ নেই |
| ছবিসহ ব্যাখ্যা | প্রতিটি অবস্থা, তীর আর ঘরের নাম; ছবির নিচে প্রতিটি তীরের কারণ | নামহীন তীর; অসম্ভব transition (waiting → running) |
| প্রমাণ | অনুমান লেখা, বিপরীত ধরে বিরোধ বা exchange argument, শেষে ∎ | “উদাহরণে কাজ করে, তাই সঠিক” — একটি interleaving প্রমাণ নয় |
| Numerical | প্রথা লেখা (tie-নিয়ম, TLB-সময় গোনা হলো কি না), Gantt বা টেবিল, সূত্র, একক, চূড়ান্ত উত্তর আলাদা | শুধু শেষ সংখ্যা; idle ফাঁক বাদ; একক নেই |
| সংক্ষিপ্ত টীকা | প্রতিটি শব্দে সংজ্ঞা, কেন দরকার, একটি উদাহরণ — তিন–চার বাক্য | এক শব্দে আধা পাতা, অন্যটিতে এক লাইন |
| বাস্তব সিস্টেম | নির্দিষ্ট নাম (CFS, ext4-এর data=ordered, KVM) আর কোন OS-এ | Linux-এর আচরণকে “সব OS-এ” বলা |
কত লিখবেন: ২ নম্বর মানে দুই–তিন বাক্য; ৫ নম্বর মানে মোটামুটি ১২০–১৮০ শব্দ আর একটি ছবি বা টেবিল; ১০ নম্বর মানে ৩০০–৪০০ শব্দ, দুটি ছবি বা টেবিল, আর একটি উদাহরণ বা প্রমাণ। তিন ঘণ্টায় ১০০ নম্বর হলে প্রতি নম্বরে প্রায় দুই মিনিট। প্রশ্নগুলো মডিউল ধরে সাজানো:
| কোর্সের মডিউল | পর্ব | লিখিত প্রশ্ন | ভাইভা প্রশ্ন |
|---|---|---|---|
| ১–২ · ভিত্তি, প্রসেস ও থ্রেড | ০১–১৫ | অংশ ২ (ক-০১–ক-০৬) | ভ-০১–ভ-১৪ |
| ৩ · CPU scheduling | ১৬–২১ | অংশ ৩ (খ-০১–খ-০৪) | ভ-১৫–ভ-২০ |
| ৪ · কনকারেন্সি ও deadlock | ২২–২৯ | অংশ ৪ (গ-০১–গ-০৫) | ভ-২১–ভ-২৮ |
| ৫ · মেমরি ম্যানেজমেন্ট | ৩০–৩৮ | অংশ ৫ (ঘ-০১–ঘ-০৫) | ভ-২৯–ভ-৩৫ |
| ৬ · I/O, স্টোরেজ ও ফাইল সিস্টেম | ৩৯–৪৫ | অংশ ৬ (ঙ-০১–ঙ-০৫) | ভ-৩৬–ভ-৪১ |
| ৭–৯ · সুরক্ষা, ভার্চুয়ালাইজেশন, বাস্তব OS | ৪৬–৫৯ | অংশ ৭ (চ-০১–চ-০৮) | ভ-৪২–ভ-৫২ |
এই পাতার কোনো প্রশ্ন কোনো নির্দিষ্ট পরীক্ষার প্রশ্নপত্র বা কোনো প্রতিষ্ঠানের ইন্টারভিউ থেকে নেওয়া নয়; এগুলো এমন ধরনের প্রশ্ন, যা বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় প্রায়ই আসে। পাশের নম্বর শুধু আনুমানিক ওজন। প্রতিটি numerical-এর প্রথা প্রশ্নের ভেতরেই লেখা; আপনার বই অন্য প্রথা নিলে সংখ্যা বদলাতে পারে, পদ্ধতি নয়।
২ · অংশ ক — OS-এর ভিত্তি, প্রসেস আর থ্রেড (মডিউল ১–২)
রিভিশন: পর্ব ০৫ (system call), পর্ব ০৬ (kernel-এর গঠন), পর্ব ০৮ (state ও PCB), পর্ব ১০ (fork, exec, wait), পর্ব ১২ (IPC) আর পর্ব ১৪ (threading model).
ক-০১Dual-mode operation কী, কেন দরকার? একটি system call user mode থেকে kernel-এ গিয়ে কীভাবে ফেরে — ধাপে লিখুন। — ৫ নম্বর (সহজ)
সংজ্ঞা: CPU-র দুটি মোড — সীমিত user mode আর পূর্ণ ক্ষমতার kernel mode; কোনটি চলছে তা হার্ডওয়্যারের একটি mode bit জানায়। Privileged instruction (I/O, timer বসানো, page table বদল, interrupt বন্ধ) শুধু kernel mode-এ চলে; user mode-এ চালাতে গেলে exception, আর kernel সাধারণত প্রসেসটি বন্ধ করে। কেন: ভুল বা ক্ষতিকর একটি প্রোগ্রাম যেন হার্ডওয়্যার বা অন্যের মেমরি ছুঁয়ে পুরো সিস্টেম ফেলতে না পারে।
System call-এর পথ (Linux, x86-64 উদাহরণ): (১) প্রোগ্রাম library wrapper ডাকে, যেমন write(1, buf, n); (২) wrapper register-এ syscall নম্বর আর argument বসায়; (৩) trap instruction (syscall; ARM64-এ svc) — হার্ডওয়্যার মোড বদলে kernel-এর নির্দিষ্ট প্রবেশপথে লাফায়; (৪) kernel syscall table থেকে handler খুঁজে argument যাচাই করে কাজ করে; (৫) ফল register-এ রেখে বিশেষ return instruction দিয়ে user mode-এ ফেরে; ব্যর্থ হলে wrapper −1 ফেরত দেয় আর errno বসায়।
সীমা ও বাস্তবতা: প্রতিটি syscall-এ মোড বদলের খরচ, তাই printf লেখা জমিয়ে একবারে write ডাকে (printf নিজে system call নয়), আর Linux সময় জানার মতো কাজ vDSO দিয়ে user mode-এই সারে। Windows-এ Win32 ফাংশন API মাত্র; আসল syscall stub থাকে ntdll.dll-এ।
নম্বর কোথায়: দুই মোড আর mode bit (১), privileged instruction-এর উদাহরণ ও কারণ (১), পাঁচ ধাপের পথ (২), বাস্তব সিস্টেমের এক লাইন (১)। পর্ব ০৪ · পর্ব ০৫
ক-০২Monolithic, microkernel আর hybrid kernel-এর তুলনা করুন। প্রতিটির একটি বাস্তব উদাহরণ দিন। — ৬ নম্বর (মাঝারি)
মূল প্রশ্ন: OS-এর কোন অংশ kernel mode-এ, একই address space-এ চলবে, আর কোনটি user mode-এ আলাদা প্রসেস হয়ে? এই সিদ্ধান্তই kernel-এর গঠন।
| মাপকাঠি | Monolithic | Microkernel | Hybrid |
|---|---|---|---|
| Kernel mode-এ কী | সব: FS, network, driver, scheduler | শুধু IPC, scheduling, address space | microkernel-ধাঁচের নকশা, কিন্তু বেশিরভাগ সেবা kernel-এর ভেতরে |
| অংশগুলোর যোগাযোগ | সরাসরি ফাংশন কল | বার্তা (message passing) | মূলত ফাংশন কল |
| গতি | সবচেয়ে দ্রুত | প্রতিটি সেবায় বাড়তি বার্তা, mode বদল আর context switch | monolithic-এর কাছাকাছি |
| একটি driver-এর বাগ | পুরো kernel ফেলতে পারে | শুধু সেই server প্রসেস পড়ে, আবার চালু করা যায় | পুরো kernel ফেলতে পারে |
| উদাহরণ | Linux (module-সহ), পুরোনো Unix | QNX, L4/seL4, MINIX 3 | Windows NT, macOS-এর XNU |
Module: Linux চলন্ত kernel-এ রিবুট ছাড়া module জোড়ে — নমনীয়, কিন্তু module kernel mode-এ চলে, তাই নির্ভরযোগ্যতার দিক থেকে monolithic-ই। ১৯৯২ সালের Tanenbaum–Torvalds বিতর্ক এই trade-off নিয়েই; “সেরা” নকশা নেই, কাজ অনুযায়ী বাছাই — নিরাপত্তা-সংবেদনশীল embedded ব্যবস্থায় microkernel, সাধারণ সার্ভারে গতির জন্য monolithic.
নম্বর কোথায়: তিনটির সংজ্ঞা (২), অন্তত চার মাপকাঠির টেবিল (২), উদাহরণ (১), module বা trade-off-এর মন্তব্য (১)। পর্ব ০৬
ক-০৩Process state diagram এঁকে প্রতিটি transition-এর কারণ ব্যাখ্যা করুন। PCB-তে কী কী থাকে? একটি প্রসেস waiting থেকে সরাসরি running-এ কেন যায় না? — ১০ নম্বর (মাঝারি, ছবিসহ)
সংজ্ঞা: প্রসেস হলো চলমান প্রোগ্রাম — নিজের address space, register-এর মান, খোলা ফাইল আর একটি PID নিয়ে। জীবনভর সে পাঁচটি অবস্থার একটিতে থাকে, আর ছয়টি তীর ধরে বদলায়:
[new] --admit--> [ready] --dispatch--> [running] --exit--> [terminated]
^ ^ | |
| +-----timeout-------+ | I/O wait (or event wait)
| v
+--------I/O done------- [waiting]
- admit (new → ready): PCB আর মেমরির মানচিত্র তৈরি শেষ, প্রসেস ready queue-তে।
- dispatch (ready → running): scheduler তাকে বাছে, dispatcher register ফিরিয়ে CPU দেয়।
- timeout (running → ready): timer interrupt — সময়ের ভাগ শেষ (preemption).
- I/O wait (running → waiting):
read()-এর মতো blocking কাজ বা কোনো ঘটনার অপেক্ষা। - I/O done (waiting → ready): ডিভাইসের interrupt — ঘটনা ঘটেছে।
- exit (running → terminated): প্রসেস শেষ; parent
wait()না করা পর্যন্ত exit status রাখা থাকে (zombie).
উদাহরণ — এক CPU-তে দুটি প্রসেস: নিচে ধাপে ধাপে A আর B-এর অবস্থা। প্রতিটি ধাপে একটি ঘটনা; লক্ষ করুন ধাপ ৫-এ A waiting থেকে ready-তে যায়, running-এ নয়।
| ঘটনা | |
| A | |
| B | |
| CPU-তে | |
| ready queue | |
| disk queue | |
| transition |
- new. Shell fork আর exec দিয়ে A বানাচ্ছে; kernel PCB আর PID তৈরি করছে। CPU-তে B.
- admit. A-র প্রস্তুতি শেষ, সে ready queue-তে। CPU এখনো B-র হাতে — ready মানে “চলতে প্রস্তুত”, চলছে নয়।
- timeout আর dispatch. Timer interrupt-এ B-র সময় শেষ: B-র register তার PCB-তে যায়, B ready queue-তে, A CPU পায় — এটিই context switch.
- I/O wait. A ডিস্ক থেকে পড়তে
read()ডাকল। ডেটা আসতে মিলিসেকেন্ড লাগবে, তাই A disk queue-তে waiting, আর CPU ফিরে পেল B. - I/O done — ready, running নয়। ডিস্কের interrupt এল; kernel ডেটা A-র buffer-এ রেখে A-কে ready queue-তে পাঠাল। CPU এখনো B-র; কে চলবে তা ঠিক করে শুধু scheduler.
- exit আর dispatch. B শেষ হলো; scheduler ready queue থেকে A-কে বাছল।
- terminated. A
exit(0)ডাকল; parentwait()না করা পর্যন্ত exit status থাকে। CPU অলস।
PCB-তে যা থাকে: PID ও parent-এর PID; state; program counter আর CPU register (context switch-এ এখানেই জমা হয়); scheduling তথ্য (priority, queue-র pointer); মেমরির তথ্য (page table-এর ঠিকানা, base/limit); accounting (CPU-সময়, সীমা); I/O তথ্য (খোলা ফাইলের টেবিল, বরাদ্দ ডিভাইস)। Linux-এ এর নাম task_struct, xv6-এ struct proc.
Waiting → running কেন নয়: ঘটনা শেষের মুহূর্তে CPU-তে সাধারণত অন্য কেউ চলছে, আর CPU কে পাবে তা ঠিক করে শুধু scheduler; তাই জাগা প্রসেস আগে ready queue-তে দাঁড়ায়। একই কারণে ready → waiting-ও অসম্ভব — অপেক্ষা শুরু হয় কেবল চলার সময়।
নম্বর কোথায়: পাঁচ অবস্থা আর ছয় নামসহ তীরের ছবি (৩), প্রতিটি তীরের কারণ (২), PCB-র অন্তত ছয়টি ঘর (২), waiting → running-এর যুক্তি (২), বাস্তব নাম বা ৭-অবস্থার মডেলের উল্লেখ — ready/suspend আর blocked/suspend (১)। পর্ব ০৮ · পর্ব ০৯
ক-০৪fork(), exec() আর wait()-এর কাজ উদাহরণসহ লিখুন। পরপর তিনবার fork করলে মোট কতটি প্রসেস হয়? Zombie আর orphan প্রসেস কী? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: fork() ডাকা প্রসেসের একটি কপি বানায় — একবার ডাকলে দুবার ফেরে: child-এ 0, parent-এ child-এর PID, ব্যর্থ হলে −1 (child হয় না)। মেমরি সঙ্গে সঙ্গে কপি হয় না; page দুই দিকে শুধু-পড়া থাকে, কেউ লিখলে তবেই সেই page কপি — copy-on-write. exec নতুন প্রসেস বানায় না: একই PID-এ কোড, ডেটা, heap, stack আর stdio buffer বদলে নতুন প্রোগ্রাম বসায়; সফল হলে ফেরে না; খোলা fd থাকে (close-on-exec না থাকলে)। wait()/waitpid() দিয়ে parent child-এর শেষের অপেক্ষা করে আর status নেয় (WIFEXITED, WEXITSTATUS).
গোনা: লুপে পরপর n বার fork করলে প্রতিটি fork চলমান সব প্রসেসকে দ্বিগুণ করে, তাই মোট 2n — n = ৩-এ ৮টি, যার ৭টি নতুন। নিচের প্রোগ্রামে প্রতিটি প্রসেস নিজের child-দের wait করে, তাদের exit status-এ পাঠানো “পরিবারের আকার” যোগ করে, আর শুধু মূল প্রসেস ফল ছাপে — তাই আউটপুট সবসময় একই:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t root = getpid();
int mine = 0; /* children created by THIS process */
for (int i = 0; i < 3; i++) {
pid_t pid = fork();
if (pid < 0) { perror("fork"); return 1; }
if (pid == 0) mine = 0; /* a new child starts with no children */
else mine++;
}
/* every process: size of my family tree = 1 + sizes reported by my children */
int total = 1, status, reaped = 0;
while (wait(&status) > 0) {
reaped++;
if (WIFEXITED(status)) total += WEXITSTATUS(status);
}
if (getpid() != root) exit(total); /* report my subtree size to my parent */
printf("root created %d children and reaped %d\n", mine, reaped);
printf("total processes = %d (expected 2^3 = 8)\n", total);
return 0;
}আসল রানের আউটপুট:
root created 3 children and reaped 3
total processes = 8 (expected 2^3 = 8)
মূল প্রসেসের তিনটি child-এর পরিবার ৪, ২ আর ১; মোট ১ + ৪ + ২ + ১ = ৮. fork-এর আগে কোনো printf নেই, তাই buffer কপি হয়ে দুবার ছাপার ফাঁদও নেই — থাকলে আগে fflush(stdout) লাগত।
Zombie আর orphan: Zombie — child শেষ হয়েছে কিন্তু parent এখনো wait করেনি; PCB-র ছোট অংশে exit status আটকে থাকে (ps-এ Z). অনেক জমলে PID ফুরাতে পারে। Orphan — child চলছে কিন্তু parent আগে শেষ; তাকে PID 1 (init/systemd) বা একটি subreaper দত্তক নিয়ে পরে reap করে।
বাস্তব: Linux-এ প্রসেস আর থ্রেড দুটিরই ভিত্তি clone(); Windows-এ fork নেই, একটিই call — CreateProcess — যা নতুন প্রোগ্রাম নিয়েই প্রসেস বানায়।
নম্বর কোথায়: fork-এর তিন ফেরত মান ও COW (২), exec-এ কী থাকে-কী বদলায় (২), wait ও status (১), 2n-এর যুক্তি (১), zombie ও orphan (২)। পর্ব ১০ · পর্ব ১১
ক-০৫থ্রেড আর প্রসেসের পার্থক্য লিখুন। তিনটি multithreading model ব্যাখ্যা করুন; Linux আর Windows কোনটি ব্যবহার করে? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: থ্রেড হলো প্রসেসের ভেতরের একটি কাজের ধারা — নিজের program counter, register আর stack (আর thread-local storage) নিয়ে; code, global data, heap আর খোলা ফাইল প্রসেসের সব থ্রেড ভাগ করে।
| মাপকাঠি | প্রসেস | থ্রেড |
|---|---|---|
| Address space | নিজস্ব | প্রসেসের সাথে ভাগ করা |
| তৈরি ও switch-এর খরচ | বেশি — page table বদলায়, TLB-র ক্ষতি | কম — page table একই থাকে |
| যোগাযোগ | IPC (pipe, shared memory, socket) | সরাসরি shared ভ্যারিয়েবল — তাই lock লাগে |
| একজনের বাগ | সাধারণত শুধু সেই প্রসেস পড়ে | পুরো প্রসেস পড়ে |
| তথ্যের ঘর | PCB | TCB |
তিন model — user-level থ্রেড kernel-এর কতগুলো থ্রেডে বসে:
- Many-to-one: অনেক user থ্রেড, একটি kernel থ্রেড। দ্রুত switch, কিন্তু একটি blocking system call পুরো প্রসেস আটকায়, আর multicore কাজে লাগে না।
- One-to-one: প্রতিটি user থ্রেডের নিজের kernel থ্রেড। Blocking বা multicore-এ সমস্যা নেই; দাম — প্রতিটি থ্রেড তৈরিতে kernel-এর খরচ। Linux (NPTL) আর Windows এই মডেল।
- Many-to-many: m টি user থ্রেড n টি kernel থ্রেডে (n ≤ m) ভাগ হয়; two-level রূপে কিছু থ্রেড আলাদাভাবে বাঁধাও যায়। পুরোনো Solaris-এ ছিল; আজ Go-র goroutine আর Java-র virtual thread runtime-এর ভেতরে একই ভাবনা।
Linux-এর বাস্তবতা: থ্রেড আসলে CLONE_VM | CLONE_THREAD দিয়ে তৈরি একটি task, যা মেমরি আর ফাইল ভাগ করে; তাই ps -L-এ প্রতিটি থ্রেড আলাদা দেখা যায়। মাল্টিথ্রেডেড প্রসেসে fork করলে POSIX অনুযায়ী child-এ থাকে শুধু ডাকা থ্রেডের কপি।
নম্বর কোথায়: সংজ্ঞা আর কী ভাগ হয়-কী হয় না (২), পার্থক্যের টেবিল (২), তিন model-এর সুবিধা-অসুবিধা (৩), Linux/Windows (১)। পর্ব ১৪ · পর্ব ১৫
ক-০৬IPC-র দুই মডেল — shared memory আর message passing — তুলনা করুন। Pipe-এর read কখন 0 ফেরত দেয়? — ৫ নম্বর (সহজ)
সংজ্ঞা: প্রতিটি প্রসেসের নিজস্ব address space, তাই তথ্য দিতে-নিতে kernel-এর দেওয়া পথ লাগে — inter-process communication. Shared memory: kernel শুরুতে একই physical page দুই প্রসেসের address space-এ বসায়, তারপর প্রতিটি পড়া-লেখা সাধারণ মেমরি-কাজ — সবচেয়ে দ্রুত, কিন্তু সমন্বয় (lock, semaphore) প্রোগ্রামারের দায়। Message passing: প্রতিটি বার্তা kernel-এর মাধ্যমে কপি হয় (pipe, message queue, socket) — প্রতিবার system call, কিন্তু সহজ, নিরাপদ, আর socket হলে অন্য মেশিনেও যায়। নকশার প্রশ্ন: direct না mailbox, blocking না non-blocking, buffer zero/bounded/unbounded.
Pipe-এর নিয়ম: একমুখী বাইটের স্রোত; খালি হলে পাঠক অপেক্ষা করে, ভর্তি হলে লেখক। read() 0 (EOF) দেয় কেবল যখন buffer খালি এবং সব প্রসেসে লেখার সব মুখ বন্ধ। তাই fork-এর পর অব্যবহৃত মুখ বন্ধ না করলে পাঠক চিরকাল অপেক্ষা করে — shell-এর pipeline-এ সবচেয়ে চেনা বাগ।
বাস্তব: Linux-এ shm_open, FIFO, Unix socket; Windows-এ named pipe, file mapping আর ALPC; Android-এ Binder.
নম্বর কোথায়: দুই মডেলের সংজ্ঞা ও তুলনা (৩), EOF-এর শর্ত (১), একটি বাস্তব উদাহরণ (১)। পর্ব ১২
৩ · অংশ খ — CPU scheduling (মডিউল ৩)
রিভিশন: পর্ব ১৬ (মাপকাঠি), পর্ব ১৭ (FCFS, SJF, SRTF), পর্ব ১৮ (priority, RR), পর্ব ১৯ (MLFQ), পর্ব ২০ (RM, EDF) আর পর্ব ২১ (CFS, EEVDF). প্রথা: TAT = CT − AT, WT = TAT − BT, RT = প্রথম শুরু − AT.
খ-০১CPU scheduling-এর মাপকাঠিগুলো লিখুন — কোনগুলো বাড়াতে আর কোনগুলো কমাতে হয়? Preemptive আর non-preemptive scheduling-এর পার্থক্য কী? — ৫ নম্বর (সহজ)
মাপকাঠি: বাড়াতে হয় — CPU utilisation (CPU কত শতাংশ সময় ব্যস্ত) আর throughput (একক সময়ে কতটি প্রসেস শেষ)। কমাতে হয় — turnaround time (CT − AT), waiting time (ready queue-তে মোট অপেক্ষা, একটি burst হলে TAT − BT) আর response time (প্রথমবার CPU পাওয়া − AT). সঙ্গে ন্যায্যতা আর পূর্বানুমানযোগ্যতা।
সিদ্ধান্তের চার মুহূর্ত: (১) running → waiting, (২) running → ready, (৩) waiting → ready, (৪) প্রসেস শেষ। শুধু (১) আর (৪)-এ সিদ্ধান্ত নিলে non-preemptive — চলমান প্রসেস নিজে না ছাড়লে CPU কেড়ে নেওয়া হয় না; (২) আর (৩)-এও নিলে preemptive — timer বা উচ্চ-অগ্রাধিকারের আগমনে কেড়ে নেওয়া যায়। Preemptive-এ সাড়া ভালো, কিন্তু shared ডেটায় race-এর ঝুঁকি আর context switch-এর খরচ বাড়ে। আধুনিক Linux, Windows, macOS preemptive.
নম্বর কোথায়: পাঁচ মাপকাঠি সূত্রসহ, কোন দিকে নিতে হয় (৩), চার মুহূর্ত ধরে পার্থক্য (২)। পর্ব ১৬
খ-০২প্রসেস (arrival, burst): P1 (0, 8), P2 (1, 4), P3 (2, 9), P4 (3, 5). FCFS, SJF (non-preemptive), SRTF আর Round Robin (q = 4)-এর Gantt chart এঁকে গড় waiting, turnaround আর response time বের করুন, তারপর চারটি algorithm তুলনা করুন। প্রথা: tie হলে আগে আসা, তারপর ছোট id; RR-এ একই মুহূর্তে নতুন আগমন সময়-ফুরানো প্রসেসের আগে সারিতে ঢোকে। — ১০ নম্বর (মাঝারি)
Gantt chart:
FCFS │ P1 0-8 │ P2 8-12 │ P3 12-21 │ P4 21-26 │
SJF │ P1 0-8 │ P2 8-12 │ P4 12-17 │ P3 17-26 │
SRTF │ P1 0-1 │ P2 1-5 │ P4 5-10 │ P1 10-17 │ P3 17-26 │
RR 4 │ P1 0-4 │ P2 4-8 │ P3 8-12 │ P4 12-16 │ P1 16-20 │ P3 20-24 │ P4 24-25 │ P3 25-26 │
মূল সিদ্ধান্তগুলো: SJF-এ t = ৮-এ P2 (৪), P4 (৫), P3 (৯) অপেক্ষায় — ছোট আগে। SRTF-এ t = ১-এ P2 আসে, বাকি ৪ < P1-এর বাকি ৭, তাই P1 থামে; t = ৫-এ বাকি সময় P1 ৭, P3 ৯, P4 ৫ — P4. RR-এ t = ৪-এ P2, P3, P4 আগেই সারিতে, P1 যায় সবার পেছনে।
| Algorithm | CT (P1, P2, P3, P4) | WT (P1, P2, P3, P4) | গড় WT | গড় TAT | গড় RT |
|---|---|---|---|---|---|
| FCFS | 8, 12, 21, 26 | 0, 7, 10, 18 | ৮.৭৫ | ১৫.২৫ | ৮.৭৫ |
| SJF | 8, 12, 26, 17 | 0, 7, 15, 9 | ৭.৭৫ | ১৪.২৫ | ৭.৭৫ |
| SRTF | 17, 5, 26, 10 | 9, 0, 15, 2 | ৬.৫০ | ১৩.০০ | ৪.২৫ |
| RR (q = 4) | 20, 8, 26, 25 | 12, 3, 15, 17 | ১১.৭৫ | ১৮.২৫ | ৪.৫০ |
হিসাবগুলো নিচের simulator-এ মিলিয়ে নিন (সংখ্যা বদলে নিজের প্রশ্নও চালাতে পারেন):
// FCFS, SJF, SRTF, RR(q=4) on one set. Ties: earlier arrival, then lower id.
// RR: a process arriving when a slice ends joins the queue BEFORE the preempted one.
const P = [["P1", 0, 8], ["P2", 1, 4], ["P3", 2, 9], ["P4", 3, 5]]; // id, arrival, burst
const order = id => P.findIndex(p => p[0] === id);
function simulate(name, pick, q = Infinity) {
const rem = {}, ct = {}, first = {}, rq = [], seg = []; P.forEach(p => rem[p[0]] = p[2]);
let t = 0, next = 0;
const admit = () => { while (next < P.length && P[next][1] <= t) rq.push(P[next++][0]); };
admit();
while (Object.keys(ct).length < P.length) {
if (!rq.length) { t = P[next][1]; admit(); continue; }
const id = pick(rq, rem); rq.splice(rq.indexOf(id), 1);
if (!(id in first)) first[id] = t;
let run = Math.min(rem[id], q);
if (name === "SRTF" && next < P.length) run = Math.min(run, P[next][1] - t);
const last = seg[seg.length - 1];
if (last && last[0] === id) last[2] = t + run; else seg.push([id, t, t + run]);
t += run; rem[id] -= run; admit();
if (rem[id] === 0) ct[id] = t; else rq.push(id);
}
const avg = f => (P.reduce((s, p) => s + f(p), 0) / P.length).toFixed(2);
console.log(name.padEnd(5), seg.map(s => `${s[0]} ${s[1]}-${s[2]}`).join(" | "));
console.log(" avg WT", avg(p => ct[p[0]] - p[1] - p[2]), " avg TAT", avg(p => ct[p[0]] - p[1]),
" avg RT", avg(p => first[p[0]] - p[1]));
}
const shortest = (rq, rem) => rq.reduce((a, b) => rem[b] < rem[a] || (rem[b] === rem[a] && order(b) < order(a)) ? b : a);
simulate("FCFS", rq => rq[0]);
simulate("SJF", shortest);
simulate("SRTF", shortest);
simulate("RR", rq => rq[0], 4);আসল রানের আউটপুট:
FCFS P1 0-8 | P2 8-12 | P3 12-21 | P4 21-26
avg WT 8.75 avg TAT 15.25 avg RT 8.75
SJF P1 0-8 | P2 8-12 | P4 12-17 | P3 17-26
avg WT 7.75 avg TAT 14.25 avg RT 7.75
SRTF P1 0-1 | P2 1-5 | P4 5-10 | P1 10-17 | P3 17-26
avg WT 6.50 avg TAT 13.00 avg RT 4.25
RR P1 0-4 | P2 4-8 | P3 8-12 | P4 12-16 | P1 16-20 | P3 20-24 | P4 24-25 | P3 25-26
avg WT 11.75 avg TAT 18.25 avg RT 4.50
SJF আর SRTF-এ একই shortest বাছাই; পার্থক্য শুধু SRTF পরের আগমন পর্যন্ত চালিয়ে আবার বাছে। Non-preemptive দুটিতে RT = WT, কারণ প্রসেস একবার শুরু হলে শেষ পর্যন্ত চলে। RR গড় WT-তে সবচেয়ে খারাপ, কিন্তু RT-তে SRTF-এর কাছাকাছি — interactive কাজে ঠিক এটাই চাওয়া।
| মাপকাঠি | FCFS | SJF | SRTF | Priority | RR | MLFQ |
|---|---|---|---|---|---|---|
| Preemptive? | না | না | হ্যাঁ | দুই রকমই | হ্যাঁ | হ্যাঁ |
| Starvation | নেই | সম্ভব | সম্ভব | সম্ভব — aging লাগে | নেই | সম্ভব — boost লাগে |
| Burst জানা লাগে? | না | হ্যাঁ (অনুমান) | হ্যাঁ (অনুমান) | না | না | না |
| দুর্বলতা | convoy effect | লম্বা কাজ পিছায় | বেশি switch | priority inversion | q-এর ওপর নির্ভর | প্যারামিটার বাছা কঠিন |
বাস্তব: Linux-এর সাধারণ task-এ CFS আর ৬.৬ থেকে EEVDF — ন্যায্য ভাগের নীতি; real-time-এ SCHED_FIFO/SCHED_RR; Windows-এ ৩২ স্তরের priority আর dynamic boost — MLFQ-এর আত্মীয়।
নম্বর কোথায়: চারটি সঠিক Gantt chart, idle থাকলে তা-ও (৪), প্রতিটি প্রসেসের CT, TAT, WT আর গড় (৩), তুলনা ও সিদ্ধান্ত — গড় অপেক্ষায় SRTF সেরা, সাড়ায় RR (৩)। পর্ব ১৭ · পর্ব ১৮ · পর্ব ১৯
খ-০৩প্রমাণ করুন: সব প্রসেস t = 0-তে উপস্থিত থাকলে SJF গড় waiting time সর্বনিম্ন করে। — ৫ নম্বর (কঠিন)
অনুমান: এক CPU, n টি প্রসেস, সবাই t = ০-তে, প্রতিটির একটি burst b1, …, bn, switch-খরচ শূন্য, non-preemptive.
যুক্তি (exchange argument): যেকোনো ক্রম ধরুন যেখানে পাশাপাশি দুটি প্রসেস i আর j আছে, i আগে, অথচ bi > bj. এদের আগে যারা চলে তাদের মোট সময় s. এখন i-এর অপেক্ষা s, j-এর s + bi. দুটি অদলবদল করলে j-এর অপেক্ষা s, i-এর s + bj. বাকি সবার অপেক্ষা একই থাকে — আগের দলের কিছু বদলায়নি, আর পরের দল এখনো একই s + bi + bj পরে শুরু করে। মোট অপেক্ষার পরিবর্তন = (s + bj) − (s + bi) = bj − bi < ০. অর্থাৎ “বড় আগে, ছোট পরে” এমন যেকোনো জোড়া উল্টালে মোট অপেক্ষা কঠোরভাবে কমে। ক্রম সসীম, তাই বারবার উল্টাতে উল্টাতে একসময় এমন ক্রমে পৌঁছাই যেখানে কোনো উল্টো জোড়া নেই — অর্থাৎ burst ছোট থেকে বড়, যা SJF. যে ক্রমে উল্টো জোড়া আছে সেটি সর্বনিম্ন হতে পারে না, তাই সর্বনিম্ন মান SJF-এর ক্রমেই। ∎
সীমা: প্রমাণটি সবাই একসাথে থাকার অনুমানে; আগমন আলাদা হলে non-preemptive SJF আর নিশ্চিত সেরা নয়। বাস্তবে burst আগে জানা যায় না — অনুমান হয় τ(n+1) = α·t(n) + (1 − α)·τ(n) দিয়ে — আর লম্বা কাজের starvation হতে পারে।
নম্বর কোথায়: অনুমান (১), অদলবদলে বাকিদের অপরিবর্তিত থাকার যুক্তি (২), পরিবর্তনের হিসাব আর উপসংহার (২)। পর্ব ১৭
খ-০৪Rate Monotonic আর EDF scheduling তুলনা করুন। Liu–Layland সীমা কী? Task (c, p): T1 (25, 50), T2 (35, 80), deadline = period — কোনটি সব deadline রাখে? — ৬ নম্বর (মাঝারি)
সংজ্ঞা: Rate Monotonic (RM) — ছোট period মানে উঁচু, স্থির অগ্রাধিকার। EDF — যার deadline সবচেয়ে কাছে, সে আগে; অগ্রাধিকার প্রতি মুহূর্তে বদলায়।
Liu–Layland (১৯৭৩): n টি task-এর মোট utilisation U = Σ c/p ≤ n(21/n − 1) হলে RM নিশ্চিত সফল; n = ২-এ ০.৮২৮, n → ∞-এ ln 2 ≈ ০.৬৯৩. শর্তটি যথেষ্ট, আবশ্যক নয় — সীমা পেরোলে response-time analysis দিয়ে দেখতে হয়। EDF এক CPU-তে U ≤ ১ হলেই সফল, আর এটি optimal: যেকোনো সফল schedule-কে exchange argument দিয়ে deadline না ভেঙে EDF-এ বদলানো যায়।
উদাহরণ: U = 25/50 + 35/80 = ০.৫ + ০.৪৩৭৫ = ০.৯৩৭৫ > ০.৮২৮ — RM-এর সীমা পেরিয়েছে, তাই RTA: T2-এর R = 35 + ⌈R/50⌉ × 25; শুরু R = 35 → 60 → 35 + 2 × 25 = 85 > 80. T2 প্রথম period-এই deadline হারায়। EDF: U ≤ ১, তাই সব deadline রক্ষা হয়।
তুলনা ও বাস্তব: RM সরল, স্থির অগ্রাধিকার বলে RTOS-এ সহজে বসে, অতিরিক্ত চাপে কোন task আগে হারাবে তা জানা থাকে; EDF বেশি কাজ ধরে, কিন্তু চাপ বেশি হলে কে হারাবে তা অনুমান করা কঠিন। Linux-এ EDF-এর রূপ SCHED_DEADLINE.
নম্বর কোথায়: দুই নীতির সংজ্ঞা (১), সীমা আর “যথেষ্ট, আবশ্যক নয়” (২), U আর RTA-এর হিসাব (২), সিদ্ধান্ত বা বাস্তব উদাহরণ (১)। পর্ব ২০
৪ · অংশ গ — কনকারেন্সি, সিনক্রোনাইজেশন আর deadlock (মডিউল ৪)
রিভিশন: পর্ব ২২ (critical section, Peterson), পর্ব ২৪ (mutex, semaphore), পর্ব ২৫ (monitor), পর্ব ২৬ (ক্লাসিক সমস্যা), পর্ব ২৭ (চার শর্ত) আর পর্ব ২৮ (Banker's).
গ-০১Critical-section সমস্যার সমাধানকে কোন তিনটি শর্ত মানতে হয়? Peterson-এর সমাধান লিখে প্রমাণ করুন যে এটি তিনটি শর্তই পূরণ করে। আধুনিক CPU-তে এটি কেন সরাসরি চলে না? — ১০ নম্বর (কঠিন)
প্রেক্ষাপট: দুই থ্রেড একসাথে count++ করলে load-বদল-store মিশে ফল ভুল হয় — race condition. Shared ডেটা ছোঁয়ার অংশ critical section; প্রতিটি প্রসেস entry → critical → exit → remainder-এ ঘোরে।
তিন শর্ত (প্রসেসের আপেক্ষিক গতি বা CPU-সংখ্যা নিয়ে কোনো অনুমান ছাড়া): (১) Mutual exclusion — একসাথে সর্বোচ্চ একজন ভেতরে; (২) Progress — ভেতরে কেউ না থাকলে আর কেউ ঢুকতে চাইলে, কে ঢুকবে তার সিদ্ধান্তে শুধু entry-তে থাকারা অংশ নেয় আর সিদ্ধান্ত অনির্দিষ্টকাল পিছায় না; (৩) Bounded waiting — অনুরোধের পর অন্যরা কতবার ঢুকতে পারবে তার একটি সীমা আছে। প্রথমটি safety, বাকি দুটি liveness.
bool flag[2] = {false, false}; // shared: "I want to enter"
int turn; // shared: who yields on a tie
flag[i] = true; // entry section
turn = j; // "after you"
while (flag[j] && turn == j) ; // busy wait
/* critical section */
flag[i] = false; // exit section
/* remainder section */অনুমান: প্রতিটি load আর store অবিভাজ্য, আর সব প্রসেস সব লেখা একই ক্রমে দেখে (sequential consistency).
(১) Mutual exclusion: বিপরীত ধরি — কোনো মুহূর্ত t-তে দুজনই ভেতরে। তাহলে t-তে flag[0] = flag[1] = true. প্রত্যেকে ঢোকার আগে turn-এ একবার লিখেছে; সাধারণতা না হারিয়ে ধরি P1-এর turn = 0 পরে ঘটেছে। তার পর থেকে t পর্যন্ত কেউ turn-এ লেখেনি, তাই turn = ০. P1 নিজের লেখার পরে লুপ পার হয়েছে, অর্থাৎ তখন flag[0] false পড়েছে। কিন্তু P0 নিজের flag তুলেছিল নিজের turn-লেখার আগে, যা P1-এর লেখারও আগে, আর t পর্যন্ত নামায়নি — বিরোধ। ∎
(২) Progress: Pi আটকায় শুধু যখন flag[j] true এবং turn == j. Pj ঢুকতে না চাইলে flag[j] false, তাই Pi সাথে সাথে ঢোকে। দুজনই লুপে থাকলে turn-এর মান একটিই আর লুপে কেউ তা বদলায় না, তাই যার নামে turn নয় সে ঢোকে — দুজন একসাথে চিরকাল ঘুরতে পারে না। ∎
(৩) Bounded waiting (সীমা ১): Pi অপেক্ষায় থাকাকালে Pj বেরিয়ে আবার ঢুকতে চাইলে নিজেই turn = i লেখে; তখন Pj-এর শর্ত সত্য হয়ে সে আটকায়, আর Pi-এর শর্ত মিথ্যা হয়ে সে ঢোকে। অর্থাৎ Pj সর্বোচ্চ একবার আগে ঢুকতে পারে। ∎
আধুনিক CPU-তে কেন ভাঙে: sequential consistency-র অনুমান সত্য নয়। x86-এর store buffer-এ flag[i] = true আটকে থাকতেই পরের load অন্যজনের পুরোনো flag[j] = false পড়তে পারে — দুজনই ঢোকে। Compiler-ও ক্রম বদলাতে পারে। প্রতিকার: C11-এর seq_cst atomic বা পূর্ণ memory barrier; বাস্তবের কোডে নিজে lock না বানিয়ে OS-এর mutex. n প্রসেসের জন্য Lamport-এর bakery algorithm একই ভাবনা — টোকেন নম্বর।
নম্বর কোথায়: তিন শর্ত আর অনুমান (২), কোড (১), তিনটি প্রমাণ (৫), আধুনিক CPU-র সমস্যা ও প্রতিকার (২)। পর্ব ২২ · পর্ব ২৩
গ-০২Semaphore আর monitor-এর পার্থক্য লিখুন। Mutex কি binary semaphore-এর সমান? Hoare আর Mesa semantics কী? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: Semaphore (Dijkstra) — একটি পূর্ণসংখ্যা আর একটি অপেক্ষার সারি; P/wait মান ১ কমায়, শূন্যের নিচে গেলে ডাকা প্রসেস ঘুমায়; V/signal মান ১ বাড়ায়, কেউ অপেক্ষায় থাকলে একজনকে জাগায়। Monitor (Brinch Hansen ১৯৭৩, Hoare ১৯৭৪) — shared ডেটা, তার procedure আর condition variable-এর একটি মডিউল, যেখানে একবারে একটিই থ্রেড সক্রিয়; mutual exclusion ভাষা বা compiler নিজে দেয়।
| মাপকাঠি | Semaphore | Monitor |
|---|---|---|
| স্তর | নিচু স্তরের primitive | উঁচু স্তরের ভাষা-গঠন |
| Mutual exclusion | প্রোগ্রামার নিজে wait/signal বসান | স্বয়ংক্রিয় — procedure-এ ঢোকা মানেই lock |
| স্মৃতি | গণনা থাকে, তাই আগের signal মনে থাকে | condition variable-এর স্মৃতি নেই — কেউ অপেক্ষায় না থাকলে signal হারায়; শর্ত থাকে ভ্যারিয়েবলে |
| ভুলের ঝুঁকি | wait/signal উল্টানো, ভোলা, ভুল ক্রম — deadlock | কম; তবে while ছাড়া wait করলে ভুল |
| উদাহরণ | POSIX sem_wait/sem_post | Java-র synchronized + wait/notify, C#-এর Monitor |
প্রকাশক্ষমতা সমান: semaphore দিয়ে monitor বানানো যায় (mutex, next, next_count), আর mutex + condition variable দিয়ে semaphore.
Mutex ≠ binary semaphore: mutex-এর মালিক আছে — যে lock করে, সে-ই unlock করে; তাই priority inheritance আর ভুল-ধরা (যেমন অন্যের lock খোলা) সম্ভব। Semaphore-এর মালিক নেই, যেকোনো থ্রেড signal দিতে পারে — সংকেত পাঠানোর জন্য উপযুক্ত। নিয়ম: পাহারায় mutex, সংকেত আর গণনায় semaphore.
Hoare বনাম Mesa: Hoare-এ signal পেলে জাগা থ্রেড সাথে সাথে চলে, শর্ত নিশ্চিত সত্য (if যথেষ্ট); Mesa-য় (Lampson ও Redell, ১৯৮০) signal-দাতা চলতে থাকে, জাগা থ্রেড পরে চলে, ততক্ষণে শর্ত বদলে যেতে পারে — তাই while বাধ্যতামূলক। আজকের প্রায় সব সিস্টেম Mesa; spurious wakeup-ও এই কারণে নিরাপদে সামলানো যায়।
নম্বর কোথায়: দুটির সংজ্ঞা (২), তুলনার টেবিল (৩), mutex বনাম binary semaphore (১), Hoare বনাম Mesa (২)। পর্ব ২৪ · পর্ব ২৫
গ-০৩Semaphore দিয়ে bounded-buffer (producer–consumer) সমস্যার সমাধান লিখুন। Producer-এ দুটি wait-এর ক্রম উল্টালে কী হয়? — ৬ নম্বর (মাঝারি)
তিনটি semaphore: mutex = 1 (একবারে একজন buffer ছোঁবে), empty = n (খালি ঘরের গণনা), full = 0 (ভরা ঘরের গণনা)। Invariant: empty + full = n.
producer: consumer:
item = produce() wait(full) // a filled slot?
wait(empty) // a free slot? wait(mutex)
wait(mutex) item = remove()
insert(item) signal(mutex)
signal(mutex) signal(empty) // one more free slot
signal(full) // one more item consume(item)ক্রম উল্টালে: producer আগে wait(mutex), তারপর wait(empty) করলে — buffer ভর্তি অবস্থায় producer mutex ধরে empty-এ ঘুমায়। Consumer জিনিস সরাতে wait(mutex)-এ আটকে যায়, তাই কখনো signal(empty) দিতে পারে না — deadlock. শিক্ষা: তালা ধরে এমন কিছুর জন্য ঘুমাবেন না, যা ঘটাতে অন্যকে সেই তালাই লাগবে। signal-এর ক্রম উল্টানো ক্ষতিকর নয়, শুধু একটু কম দক্ষ।
বাস্তব: web server-এর অনুরোধের সারি, logging-এর ring buffer, Go-র buffered channel — সবই bounded buffer; সীমা থাকাই backpressure দেয়।
নম্বর কোথায়: তিন semaphore আর শুরুর মান (২), দুই দিকের কোড (২), উল্টো ক্রমের deadlock-এর ধাপ (২)। পর্ব ২৬
গ-০৪Deadlock-এর চারটি প্রয়োজনীয় শর্ত লিখুন। প্রতিটি শর্ত ভেঙে কীভাবে deadlock প্রতিরোধ করা যায়, আর তার দাম কী? Resource-allocation graph-এ চক্র থাকলেই কি deadlock? — ১০ নম্বর (মাঝারি)
সংজ্ঞা: একদল প্রসেস deadlocked, যদি প্রত্যেকে এমন একটি ঘটনার (সাধারণত সম্পদ ছাড়ার) অপেক্ষায় থাকে, যা কেবল দলেরই অন্য কেউ ঘটাতে পারে। উদাহরণ: T1 ধরে আছে lock A, চায় B; T2 ধরে আছে B, চায় A.
চার শর্ত (Coffman ও সহকর্মী, ১৯৭১) — চারটি একসাথে সত্য না হলে deadlock হয় না:
| শর্ত | অর্থ | ভাঙার কৌশল | দাম |
|---|---|---|---|
| Mutual exclusion | সম্পদ একবারে একজনের | ভাগযোগ্য করা — read-only ফাইল; প্রিন্টারে spooling | lock-এর মতো সম্পদের উদ্দেশ্যই একচেটিয়া হওয়া; সবখানে চলে না |
| Hold and wait | কিছু ধরে রেখে আরও চাওয়া | শুরুতেই সব একসাথে চাওয়া; অথবা নতুন চাওয়ার আগে হাতের সব ছেড়ে দেওয়া | সম্পদ অকারণে আটকে থাকে, utilisation কমে, starvation; কী লাগবে তা প্রায়ই আগে জানা যায় না |
| No preemption | সম্পদ জোর করে কেড়ে নেওয়া যায় না | অনুরোধে আটকালে হাতের সম্পদ কেড়ে নেওয়া; পরে সব একসাথে ফেরত | শুধু যার অবস্থা সংরক্ষণ করা যায় (CPU, মেমরি); mutex বা প্রিন্টারে নয় |
| Circular wait | P1 → P2 → … → P1 অপেক্ষার চক্র | সব সম্পদে একটি global ক্রম; সবাই সেই ক্রমে চাইবে | ক্রম মানার শৃঙ্খলা লাগে; সবচেয়ে বাস্তব উপায় |
Lock ordering কেন কাজ করে (ছোট প্রমাণ): প্রতিটি সম্পদের একটি rank. সবাই শুধু নিজের হাতের সর্বোচ্চ rank-এর চেয়ে বড় rank চায়। চক্র P1 → P2 → … → Pk → P1 থাকলে, শিকল ধরে প্রতিটি ধাপে চাওয়া সম্পদের rank কঠোরভাবে বাড়ে, তাই চক্রের শেষে ফিরে আসা প্রথম সম্পদের rank নিজের চেয়েই বড় হতে হতো — অসম্ভব। ∎
Graph আর চক্র: resource-allocation graph-এ চক্র নেই মানে deadlock নেই। প্রতিটি resource type-এর একটিই instance হলে চক্র মানেই deadlock; একাধিক instance হলে চক্র থাকলেও deadlock না-ও হতে পারে — চক্রের বাইরের কেউ একটি instance ছাড়লেই চক্র ভাঙে; তখন detection algorithm চালাতে হয়।
বাস্তব: Linux-এর lockdep lock-ক্রমের নিয়ম ভাঙলে আগেই সতর্ক করে; database deadlock হতে দেয়, তারপর ধরে একটি transaction বাতিল করে।
নম্বর কোথায়: সংজ্ঞা ও উদাহরণ (১), চার শর্ত (২), প্রতিটির কৌশল ও দাম (৪), চক্রের প্রশ্ন (২), বাস্তব বা প্রমাণ (১)। পর্ব ২৭
গ-০৫Safe state কী? প্রমাণ করুন safe state-এ deadlock অসম্ভব। নিচের অবস্থায় Banker's safety algorithm চালান, তারপর P2-এর অনুরোধ (1, 0, 1) বিচার করুন। মোট resource (A, B, C) = (9, 5, 7); Allocation: P0 (2, 1, 0), P1 (3, 0, 2), P2 (1, 1, 1), P3 (0, 2, 1); Max: P0 (7, 3, 3), P1 (4, 2, 2), P2 (3, 3, 2), P3 (2, 2, 4). প্রথা: একাধিক যোগ্য হলে সবচেয়ে ছোট index আগে, প্রতিবার শুরু থেকে খোঁজা। — ১০ নম্বর (কঠিন)
সংজ্ঞা: একটি অবস্থা safe, যদি এমন একটি ক্রম <P1, …, Pn> থাকে যেখানে প্রতিটি Pi-এর বাকি চাহিদা Needi ≤ Available + Σj<i Allocationj — অর্থাৎ আগের সবাই শেষ করে সম্পদ ফেরত দিলে Pi নিজের সর্বোচ্চ চাহিদা পায়।
প্রমাণ — safe ⇒ deadlock নেই: ধরুন সবচেয়ে খারাপ ক্ষেত্র — প্রত্যেকে এখনই নিজের পুরো Max চায়। P1-এর Need ≤ Available, তাই সে সব পায়, শেষ করে, Allocation ফেরত দেয়। এখন Available বেড়ে Available + Allocation1, যা সংজ্ঞা অনুযায়ী P2-এর জন্য যথেষ্ট। Induction-এ প্রত্যেক Pi একসময় শেষ করে, তাই কোনো দল চিরকাল অপেক্ষায় থাকতে পারে না। ∎ উল্টোটা সত্য নয়: unsafe মানে শুধু নিশ্চয়তা নেই — প্রসেস Max না চাইলে deadlock না-ও হতে পারে। Banker's algorithm প্রতিটি অনুরোধ “দিয়েছি ধরে নিয়ে” safety চালায়, safe থাকলে তবেই দেয় — তাই সিস্টেম সবসময় safe থাকে।
Need = Max − Allocation: P0 (5, 2, 3), P1 (1, 2, 0), P2 (2, 2, 1), P3 (2, 0, 3). মোট Allocation (6, 4, 4), তাই Available = (9, 5, 7) − (6, 4, 4) = (3, 1, 3).
| Work | |
| Finish P0–P3 | |
| Safe sequence | |
| রায় |
- শুরু। Need = Max − Allocation, Available = মোট − মোট Allocation = (৩, ১, ৩)। Work = Available, কেউ শেষ হয়নি।
- প্রথম যোগ্য P3. P0-এর A, P1 আর P2-এর B আটকায়। P3-এর (২, ০, ৩) ≤ (৩, ১, ৩) — সে শেষ করে নিজের Allocation (০, ২, ১) ফেরত দেয়: Work = (৩, ৩, ৪)।
- আবার শুরু থেকে — P1. P0-এর A = ৫ > ৩, বাদ; P1-এর (১, ২, ০) ≤ (৩, ৩, ৪), ফেরত (৩, ০, ২): Work = (৬, ৩, ৬)।
- এবার P0. (৫, ২, ৩) ≤ (৬, ৩, ৬); ফেরত (২, ১, ০): Work = (৮, ৪, ৬)।
- শেষে P2 — SAFE. (২, ২, ১) ≤ (৮, ৪, ৬); Work = (৯, ৫, ৭), ঠিক মোট resource — একটি ভালো যাচাই। Safe sequence <P3, P1, P0, P2>.
- P2-এর অনুরোধ (১, ০, ১)। Need আর Available-এর পরীক্ষা পাস; কিন্তু দিয়েছি ধরে নিলে Available (২, ১, ২)-এ কারও Need পূরণ হয় না — unsafe. তাই resource থাকা সত্ত্বেও নাকচ, অবস্থা ফেরত, P2 অপেক্ষা করে। (P3-এর (০, ০, ২) অনুরোধ হলে safe থাকত, মঞ্জুর হতো।)
খরচ ও বাস্তবতা: safety algorithm O(m·n²), n = প্রসেস, m = resource type. সাধারণ OS Banker's চালায় না — Max আগে জানা যায় না, প্রসেসের সংখ্যা বদলায়; তবে database-এর deadlock detection আর ক্লাস্টারের admission control-এ একই চিন্তা আছে।
নম্বর কোথায়: safe-এর সংজ্ঞা (১), প্রমাণ আর “unsafe ≠ deadlock” (২), Need ও Available (১), প্রতিটি ধাপের Work-সহ safety (৩), অনুরোধের চার ধাপ আর রায় (৩)। পর্ব ২৮
৫ · অংশ ঘ — মেমরি ম্যানেজমেন্ট (মডিউল ৫)
রিভিশন: পর্ব ৩২ (paging), পর্ব ৩৩ (TLB, EAT), পর্ব ৩৪ (segmentation), পর্ব ৩৫ (page fault), পর্ব ৩৬ (replacement) আর পর্ব ৩৭ (thrashing).
ঘ-০১Paging আর segmentation-এর তুলনা করুন। আধুনিক x86-64 Linux কোনটি ব্যবহার করে? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: Paging logical address space-কে সমান মাপের page-এ আর RAM-কে একই মাপের frame-এ ভাগ করে; যেকোনো page যেকোনো খালি frame-এ বসে, অনুবাদ করে page table. Segmentation প্রোগ্রামারের চোখের ছবি — code, data, stack, heap আলাদা segment; logical address = ⟨s, d⟩, segment table-এ প্রতিটির base আর limit; d < limit হলে physical = base + d, না হলে trap.
| মাপকাঠি | Paging | Segmentation |
|---|---|---|
| একক | সমান মাপের page (৪ KiB সাধারণ) | ভিন্ন মাপের, যুক্তিসঙ্গত segment |
| প্রোগ্রামারের কাছে | অদৃশ্য | দৃশ্যমান |
| Fragmentation | শুধু internal (গড়ে আধা page) | external — compaction লাগতে পারে |
| সুরক্ষা ও ভাগাভাগি | page ধরে (PTE-র R/W/X বিট) | segment ধরে — যুক্তির সাথে মেলে, সহজ |
| টেবিল | বড় — বহুস্তর লাগে | ছোট — segment-প্রতি একটি entry |
মিশ্রণ আর আজকের বাস্তবতা: MULTICS আর Intel 80386 segmentation-এর ওপর paging বসিয়েছিল (selector → descriptor → linear → page table → physical). আধুনিক OS সব segment-এর base 0 রেখে flat model চালায়, সুরক্ষা দেয় paging; x86-64 long mode-এ শুধু FS আর GS-এর base কাজ করে — Linux-এ user thread-local storage (%fs) আর kernel-এর per-CPU ডেটা (%gs). ARM-এ segmentation নেই।
নম্বর কোথায়: দুটির সংজ্ঞা ও অনুবাদ (৩), টেবিল (৩), মিশ্রণ ও বাস্তবতা (২)। পর্ব ৩২ · পর্ব ৩৪
ঘ-০২TLB-সহ paging hardware ছবি এঁকে ব্যাখ্যা করুন। Effective access time-এর সূত্র বের করুন: m = 100 ns, TLB lookup t = 20 ns, hit ratio 80% আর 98%, এক স্তর ও বহুস্তর page table. — ১০ নম্বর (মাঝারি, ছবিসহ)
সংজ্ঞা: TLB সাম্প্রতিক page → frame অনুবাদের ছোট, দ্রুত, associative cache. TLB ছাড়া প্রতিটি মেমরি-ছোঁয়ায় দুবার মেমরি পড়তে হয় — একবার page table entry, একবার ডেটা।
CPU ──logical──▶ [ p | d ]
│ └──────────────────────────────┐
▼ │
┌───────────┐ hit: f ▼
│ TLB │ ─────────────────────▶ [ f | d ] ──▶ RAM
└───────────┘ ▲
│ miss │ f
▼ │
PTBR ──▶ page table[p] ── valid? ── yes ──────────┘ (and fill TLB)
└── no ──▶ page fault (trap to OS)
উদাহরণ — page ১০২৪ বাইট: নিচে তিনটি ঠিকানা একে একে। Page table: 0 → 3, 1 → 7, 2 → 5, 3 → 1, 4 → 9, আর page 9 invalid. শুরুতে TLB-তে আছে {2 → 5, 0 → 3}.
| logical address | |
| p , d | |
| TLB | |
| page table | |
| physical address | |
| সময় |
- ঠিকানা ভাগ। ৫০০০ ÷ ১০২৪ = ৪, ভাগশেষ ৯০৪ — p = ৪, d = ৯০৪; হার্ডওয়্যারে শুধু বিট আলাদা করা।
- TLB-তে খোঁজা — miss. TLB-র সব entry একসাথে মেলানো হয় (associative); p = ৪ নেই। খরচ এ পর্যন্ত t.
- Page table walk. PTBR (x86-এ CR3) থেকে টেবিল, entry ৪-এ frame ৯, valid. এটি একটি মেমরি-পড়া: মোট t + m.
- Physical address আর TLB ভরা। ৯ × ১০২৪ + ৯০৪ = ১০১২০; অনুবাদটি TLB-তে রাখা হলো, তারপর আসল ডেটা পড়া — miss-এর মোট খরচ t + ২m.
- একই page-এ আরেকটি ঠিকানা — hit. ৫১০০ → p = ৪, d = ১০০৪; TLB সরাসরি frame ৯ দেয়: ১০২২০. খরচ t + m — locality-র কারণে বেশিরভাগ ছোঁয়া এমনই।
- Invalid page — page fault. ৯৩০০ → p = ৯, d = ৮৪; TLB miss, PTE invalid, তাই হার্ডওয়্যার OS-কে trap দেয়। ঠিকানা বৈধ এলাকায় হলে OS page আনে আর একই instruction আবার চালায়; অবৈধ হলে প্রসেস segmentation fault পায়।
EAT-এর সূত্র: hit হলে খরচ t + m; L স্তরের page table-এ miss হলে t + (L + 1)m (L বার টেবিল, একবার ডেটা)। hit ratio h হলে
- এক স্তর, h = ০.৮: ০.৮ × ১২০ + ০.২ × ২২০ = ৯৬ + ৪৪ = ১৪০ ns.
- এক স্তর, h = ০.৯৮: ০.৯৮ × ১২০ + ০.০২ × ২২০ = ১২২ ns.
- দুই স্তর, h = ০.৯৮: ০.৯৮ × ১২০ + ০.০২ × ৩২০ = ১২৪ ns; চার স্তরে (x86-64) ১২৮ ns.
- TLB-সময় নগণ্য ধরার প্রথায় এক স্তর, h = ০.৮: ০.৮ × ১০০ + ০.২ × ২০০ = ১২০ ns — কোন প্রথা, তা উত্তরে লিখুন।
শিক্ষা: hit ratio বেশি হলে বহুস্তর টেবিলের দাম প্রায় চোখে পড়ে না। Context switch-এ TLB-র entry অন্য প্রসেসের হয়ে যায়; ASID/PCID না থাকলে flush লাগে। Huge page (২ MiB) TLB reach বহু গুণ বাড়ায়।
নম্বর কোথায়: নামসহ ছবি (৩), ঠিকানা ভাগ আর hit/miss-এর পথ (২), সূত্র বের করা (২), সংখ্যা বসানো আর প্রথা (৩)। পর্ব ৩২ · পর্ব ৩৩
ঘ-০৩Page fault হলে OS কী কী করে? Memory access 200 ns, page fault service 8 ms হলে গড় ধীরতা ১০%-এর কম রাখতে fault rate p কত হতে হবে? — ৬ নম্বর (মাঝারি)
Page fault-এর ধাপ: (১) MMU invalid PTE দেখে trap দেয়; (২) kernel ঠিকানাটি প্রসেসের বৈধ এলাকায় কি না দেখে — না হলে প্রসেস শেষ (SIGSEGV); (৩) একটি খালি frame নেয় — না থাকলে replacement, victim dirty হলে আগে লেখা; (৪) ডিস্ক থেকে page পড়ার নির্দেশ দেয়, অপেক্ষার সময় অন্য প্রসেস চলে; (৫) পড়া শেষে page table আপডেট, valid বিট ১; (৬) যে instruction fault করেছিল সেটিই আবার চালানো। Demand paging-এ এভাবেই প্রথম ছোঁয়ায় page আসে।
হিসাব: EAT = (1 − p) × 200 + p × 8,000,000 ns. ১০%-এর কম ধীর মানে EAT < 220: 200 + p × 7,999,800 < 220 ⇒ p < 20 / 7,999,800 = 1/399,990 ≈ 2.5 × 10−6 — চার লক্ষ ছোঁয়ায় একটিরও কম fault. তুলনায় p = 1/1000 হলে EAT ≈ ৮২০০ ns, প্রায় ৪১ গুণ ধীর।
বাস্তব: ডিস্ক ছাড়া মেটে এমন fault (zero-fill, copy-on-write, page cache-এ থাকা page) minor, মাইক্রোসেকেন্ডের; ডিস্ক বা swap থেকে পড়া major, মিলিসেকেন্ডের। Linux-এ /usr/bin/time -v দুটি আলাদা গোনে।
নম্বর কোথায়: ছয় ধাপ (৩), সূত্র ও এককের মিল (১), p-এর হিসাব (২)। পর্ব ৩৫
ঘ-০৪Belady's anomaly কী? 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5 reference string-এ FIFO দিয়ে দেখান। Stack algorithm কী, আর LRU-তে কেন কখনো anomaly হয় না — প্রমাণ করুন। — ৮ নম্বর (কঠিন)
সংজ্ঞা: Belady's anomaly — frame বাড়ালে page fault বাড়ার ঘটনা। স্বাভাবিক প্রত্যাশা উল্টো, কিন্তু FIFO-তে এটি ঘটতে পারে।
FIFO-তে প্রদর্শন: ৩টি frame-এ ৯টি fault, ৪টি frame-এ ১০টি। নিচের প্রোগ্রাম তিনটি নীতিতেই গোনে আর প্রতিটি ধাপে মিলিয়ে দেখে, ৩ frame-এর memory সেট ৪ frame-এর সেটের ভেতরে থাকে কি না:
// FIFO, LRU and OPT on the classic string; then the inclusion test behind "stack algorithm".
const S = [1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5];
function run(policy, n) {
let mem = [], faults = 0; const states = [];
S.forEach((x, i) => {
if (mem.includes(x)) {
if (policy === "LRU") mem = mem.filter(y => y !== x).concat(x); // move to most-recent end
} else {
faults++;
if (mem.length === n) {
let victim = mem[0]; // FIFO and LRU: front of list
if (policy === "OPT") {
const nextUse = y => { const k = S.indexOf(y, i + 1); return k < 0 ? Infinity : k; };
victim = mem.reduce((a, b) => nextUse(b) > nextUse(a) ? b : a);
}
mem = mem.filter(y => y !== victim);
}
mem.push(x);
}
states.push(new Set(mem));
});
return { faults, states };
}
for (const p of ["FIFO", "LRU", "OPT"]) {
const a = run(p, 3), b = run(p, 4);
const bad = a.states.findIndex((s, i) => [...s].some(x => !b.states[i].has(x)));
console.log(`${p.padEnd(4)} 3 frames: ${a.faults} faults, 4 frames: ${b.faults} faults; ` +
(bad < 0 ? "M(3) is inside M(4) at every step"
: `inclusion breaks after reference #${bad + 1} (page ${S[bad]})`));
}আসল রানের আউটপুট:
FIFO 3 frames: 9 faults, 4 frames: 10 faults; inclusion breaks after reference #7 (page 5)
LRU 3 frames: 10 faults, 4 frames: 8 faults; M(3) is inside M(4) at every step
OPT 3 frames: 7 faults, 4 frames: 6 faults; M(3) is inside M(4) at every step
সপ্তম reference (page 5)-এর পর FIFO-র ৩ frame-এ আছে {1, 2, 5}, অথচ ৪ frame-এ {2, 3, 4, 5} — page 1 ছোট মেমরিতে আছে, বড়টিতে নেই। এই “সেটের বাইরে চলে যাওয়া” থেকেই anomaly. LRU আর OPT-এ এমন কখনো হয়নি, আর fault কমেছে।
Stack algorithm: M(n, r) = n frame-এ reference r-এর পর মেমরিতে থাকা page-এর সেট। যে algorithm-এ সব n আর r-এর জন্য M(n, r) ⊆ M(n + 1, r) — inclusion property — সেটি stack algorithm (Mattson ও সহকর্মী, ১৯৭০)।
প্রমাণ — LRU stack algorithm, তাই anomaly নেই: LRU-তে n frame-এ সবসময় থাকে সবচেয়ে সাম্প্রতিক n টি আলাদা page — এটি শুধু reference-এর ইতিহাস দিয়ে ঠিক হয়, frame-সংখ্যার ওপর নির্ভর করে না। সাম্প্রতিক n টি সেট সাম্প্রতিক n + 1 টির উপসেট, তাই M(n, r) ⊆ M(n + 1, r). এখন reference r + 1-এ page x চাওয়া হলে, x যদি n frame-এ থাকে (hit) তবে n + 1 frame-এও থাকে (hit). অর্থাৎ বড় মেমরিতে প্রতিটি fault ছোট মেমরিতেও fault, তাই fault(n + 1) ≤ fault(n). ∎ FIFO-তে মেমরির সেট নির্ভর করে কে কখন ঢুকেছে তার ওপর, যা frame-সংখ্যা বদলালে বদলায় — তাই inclusion ভাঙতে পারে।
বাস্তব: পূর্ণ LRU প্রতিটি ছোঁয়ায় হিসাব চায়, তাই OS reference bit দিয়ে কাছাকাছি নীতি চালায় — clock/second chance; Linux-এ active/inactive list আর ৬.১ থেকে MGLRU.
নম্বর কোথায়: সংজ্ঞা (১), FIFO-র ৯ আর ১০-এর হিসাব (২), stack algorithm-এর সংজ্ঞা (১), LRU-র প্রমাণ (৩), বাস্তব (১)। পর্ব ৩৬
ঘ-০৫Thrashing কী, কেন হয়? Working set model দিয়ে কীভাবে thrashing ঠেকানো যায়? Reference string 1, 2, 1, 3, 2, 1, 4, 4, 5, 6, 5, 4 আর Δ = 4 হলে t = 6 আর t = 12-এ working set কী? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: Thrashing — প্রসেসগুলো কাজের চেয়ে বেশি সময় page আনা-নেওয়ায় কাটায়। কারণ: সক্রিয় page-এর মোট চাহিদা frame-সংখ্যার চেয়ে বেশি, সাধারণত বেশি প্রসেস একসাথে রাখার (degree of multiprogramming) ফলে। দুষ্টচক্র: fault বাড়ে → প্রসেসরা ডিস্কের অপেক্ষায় → CPU অলস দেখায় → পুরোনো ধাঁচের নীতি আরও প্রসেস ঢোকায় → আরও fault. প্রসেস-সংখ্যার সাথে CPU utilisation প্রথমে বাড়ে, তারপর হঠাৎ ভেঙে পড়ে।
Working set (Denning, ১৯৬৮): WS(t, Δ) = শেষ Δটি reference-এ ছোঁয়া আলাদা page-এর সেট — locality-র মাপ। উদাহরণে t = ৬-এ শেষ চারটি reference 1, 3, 2, 1 ⇒ WS = {1, 2, 3}, WSS = ৩; t = ১২-এ 5, 6, 5, 4 ⇒ WS = {4, 5, 6}, WSS = ৩ — locality বদলেছে, আকার একই।
নিয়ন্ত্রণ: মোট চাহিদা D = Σ WSSi. D ≤ m (মোট frame) হলে নতুন প্রসেস ঢোকানো যায়; D > m হলে thrashing আসছে — একটি প্রসেস suspend করে তার frame অন্যদের দিতে হয়। বাস্তবে সঠিক WS মাপা দামি, তাই timer আর reference bit দিয়ে আনুমানিক হিসাব; বিকল্প PFF — প্রতিটি প্রসেসের fault rate-এর ওপর-নিচ দুটি সীমা, ওপরে গেলে frame দেওয়া, নিচে নামলে কেড়ে নেওয়া।
বাস্তব: Linux আলাদা working-set scheduler চালায় না; ভরসা reclaim (kswapd), swap, OOM killer, PSI (মেমরির চাপে কাজ কতক্ষণ আটকে থাকে তার মাপ) আর cgroup-এর memory.high. শেষ ওষুধ: বেশি RAM, নয়তো কম প্রসেস।
নম্বর কোথায়: সংজ্ঞা ও কারণ (২), দুষ্টচক্র বা utilisation-এর বক্ররেখা (২), WS-এর সংজ্ঞা আর দুটি সেট (২), D > m-এর নিয়ম বা PFF (২)। পর্ব ৩৭ · পর্ব ৩৮
৬ · অংশ ঙ — I/O, স্টোরেজ আর ফাইল সিস্টেম (মডিউল ৬)
রিভিশন: পর্ব ৩৯ (polling, interrupt, DMA), পর্ব ৪০ (disk scheduling), পর্ব ৪৩ (allocation, inode), পর্ব ৪৪ (journaling) আর পর্ব ৪৫ (RAID).
ঙ-০১Programmed I/O (polling), interrupt-driven I/O আর DMA-র তুলনা করুন। কোনটি কখন ভালো? — ৫ নম্বর (সহজ)
| পদ্ধতি | কীভাবে | CPU-র কাজ | কখন ভালো |
|---|---|---|---|
| Polling | CPU বারবার ডিভাইসের status register পড়ে | অপেক্ষার পুরোটা ব্যস্ত | ডিভাইস খুব দ্রুত বা ঘটনা খুব ঘন (NVMe, NAPI) |
| Interrupt | ডিভাইস প্রস্তুত হলে নিজে CPU-কে সংকেত দেয়, ISR চলে | প্রতি ঘটনায় একটি ISR | ধীর বা অনিয়মিত ডিভাইস (কিবোর্ড) |
| DMA | DMA engine নিজে ডিভাইস আর RAM-এর মধ্যে ব্লক সরায়, শেষে একটি interrupt | শুধু descriptor সাজানো আর শেষের interrupt | বড় ব্লক (ডিস্ক, নেটওয়ার্ক) |
Interrupt-এর ভারী কাজ যায় bottom half-এ (Linux-এ softirq, workqueue; Windows-এ DPC). DMA শক্তিশালী বলে IOMMU ঠিক করে কোন ডিভাইস RAM-এর কোন অংশ ছুঁতে পারবে। নম্বর কোথায়: তিনটির কাজের ধারা (৩), কখন কোনটি (২)। পর্ব ৩৯
ঙ-০২Disk queue: 98, 183, 37, 122, 14, 124, 65, 67; head 53, cylinder 0–199. FCFS, SSTF, SCAN (০-এর দিকে), LOOK (০-এর দিকে), C-SCAN আর C-LOOK (১৯৯-এর দিকে)-এ মোট head movement বের করে তুলনা করুন। — ৬ নম্বর (মাঝারি)
| Algorithm | ক্রম | মোট |
|---|---|---|
| FCFS | 53 → 98 → 183 → 37 → 122 → 14 → 124 → 65 → 67 | ৬৪০ |
| SSTF | 53 → 65 → 67 → 37 → 14 → 98 → 122 → 124 → 183 | ২৩৬ |
| SCAN ↓ | 53 → 37 → 14 → 0 → 65 → … → 183 | ২৩৬ |
| LOOK ↓ | 53 → 37 → 14 → 65 → … → 183 | ২০৮ |
| C-SCAN ↑ | 53 → 65 → … → 183 → 199 ⇒ 0 → 14 → 37 | ৩৮২ (ফেরার লাফ ধরে) / ১৮৩ (না ধরে) |
| C-LOOK ↑ | 53 → 65 → … → 183 ⇒ 14 → 37 | ৩২২ / ১৫৩ |
তুলনা: FCFS ন্যায্য কিন্তু এলোমেলো দৌড়; SSTF ছোট মোট দেয় কিন্তু দূরের অনুরোধ starve করতে পারে আর সর্বোত্তমও নয় (এখানে LOOK কম); SCAN/LOOK লিফটের মতো এক দিকে যায়; C-SCAN/C-LOOK এক দিকে সেবা দিয়ে ফেরে, তাই অপেক্ষা বেশি সমান। প্রথা সবসময় লিখুন — দিক, শেষ সীমা পর্যন্ত যাওয়া কি না, ফেরার লাফ গোনা কি না।
বাস্তব: ডিস্ক নিজে NCQ দিয়ে সাজায়; Linux-এ mq-deadline, bfq, kyber বা none; NVMe SSD-তে seek নেই, তাই সাধারণত none. নম্বর কোথায়: প্রতিটি ক্রম ও যোগফল (৪), তুলনা আর starvation-এর মন্তব্য (২)। পর্ব ৪০
ঙ-০৩Contiguous, linked আর indexed file allocation-এর তুলনা করুন। ৪ KiB block, ৪ byte pointer, ১২টি direct আর single, double, triple indirect pointer-ওয়ালা inode-এ সর্বোচ্চ ফাইল কত? Byte ১,০০,০০,০০০ পড়তে কতটি disk read লাগে (inode মেমরিতে)? — ১০ নম্বর (মাঝারি)
| মাপকাঠি | Contiguous | Linked (ও FAT) | Indexed (inode) |
|---|---|---|---|
| Directory-তে যা থাকে | শুরুর block আর দৈর্ঘ্য | প্রথম (আর শেষ) block | index block বা inode নম্বর |
| Block i পড়া | start + i — একটি access | শিকল ধরে i + ১টি access | index থেকে সরাসরি |
| Fragmentation | external; আকার আগে জানা লাগে | external নেই | external নেই |
| বাড়তি খরচ | প্রায় নেই | প্রতি block-এ pointer; একটি pointer হারালে বাকি ফাইল হারায় | index block-এর জায়গা |
| বাস্তব রূপ | ext4-এর extent, CD-ROM | FAT: সব pointer এক টেবিলে, মেমরিতে cache | Unix inode, NTFS-এর MFT |
হিসাব: এক block-এ pointer n = ৪০৯৬ ÷ ৪ = ১০২৪. সর্বোচ্চ = (১২ + n + n² + n³) × ৪ KiB = ৪৮ KiB + ৪ MiB + ৪ GiB + ৪ TiB = ৪,৪০২,৩৪৫,৭২১,৮৫৬ byte ≈ ৪ TiB.
Byte ১,০০,০০,০০০: block সূচি = ⌊১০০০০০০০ ÷ ৪০৯৬⌋ = ২৪৪১. Direct ঢাকে ০–১১, single indirect ১২–১০৩৫, double indirect ১০৩৬ থেকে ১০,৪৯,৬১১ পর্যন্ত — তাই double indirect. Disk read: double-indirect block (১) → তার ভেতরের single-indirect block (১) → data block (১) = ৩টি। নিয়ম: disk read = স্তর + ১, inode মেমরিতে থাকলে।
নম্বর কোথায়: তিন পদ্ধতির টেবিল (৪), FAT কীভাবে random access দ্রুত করে (১), সর্বোচ্চ আকারের সূত্র ও সংখ্যা (৩), disk read-এর হিসাব (২)। পর্ব ৪৩
ঙ-০৪Crash consistency সমস্যা কী? Journaling কীভাবে কাজ করে — journal-এর বিন্যাস ছবিতে দেখান। ext4-এর তিনটি journaling mode আর copy-on-write file system-এর তুলনা করুন। — ৮ নম্বর (মাঝারি, ছবিসহ)
সমস্যা: ফাইলে একটি block যোগ করতে তিনটি আলাদা লেখা — inode, data bitmap আর data block. মাঝপথে বিদ্যুৎ গেলে কিছু পৌঁছায়, কিছু না: শুধু bitmap পৌঁছালে space leak; inode আর bitmap পৌঁছালে কিন্তু data নয় — ফাইলে জঞ্জাল; inode একা পৌঁছালে metadata পরস্পরবিরোধী। fsck পরে পুরো ডিস্ক ঘেঁটে metadata মেলায় — সময় ডিস্কের আকারের অনুপাতে, আর জঞ্জাল ডেটা চিনতে পারে না।
Journaling — আগে খাতায়, পরে কাজে:
journal (circular log on disk)
┌──────┬────────────┬──────────────┬────────────┬──────┐
│ TxB │ inode (v2) │ bitmap (v2) │ data (v2) │ TxE │
└──────┴────────────┴──────────────┴────────────┴──────┘
1. journal write: TxB + changed blocks → FLUSH (all durable)
2. journal commit: TxE (one sector, atomic) → FLUSH
3. checkpoint: write the blocks to their real locations
4. free: mark the transaction space in the journal reusable
crash recovery: replay only transactions that have a TxE
TxE আলাদা করে পরে লেখা হয়, কারণ ডিস্ক লেখার ক্রম বদলাতে পারে; TxE আগে বসে crash হলে recovery জঞ্জাল replay করত। Replay idempotent — একই transaction দুবার চালালেও ফল একই।
| পদ্ধতি | কী journal হয় | নিশ্চয়তা ও দাম |
|---|---|---|
| data=journal | data + metadata | সবচেয়ে নিরাপদ; data দুবার লেখা, ধীর |
| data=ordered (ext4-এর ডিফল্ট) | শুধু metadata; কিন্তু data আসল জায়গায় লেখার পরে metadata commit | নতুন block-এ জঞ্জাল দেখা যায় না; সাধারণ কাজে ভালো আপস |
| data=writeback | শুধু metadata, ক্রমের নিয়ম নেই | দ্রুত; crash-এর পর ফাইলে পুরোনো জঞ্জাল সম্ভব |
| Copy-on-write (ZFS, Btrfs, APFS) | journal নেই — কখনো পুরোনো জায়গায় লেখে না, শেষে root pointer বদলায় | snapshot সস্তা, checksum সহজ; fragmentation বাড়তে পারে |
অ্যাপের দায়: file system যা-ই হোক, নিজের ডেটা টেকসই করতে temp ফাইল → fsync → rename → ফোল্ডারের fsync. নম্বর কোথায়: সমস্যা ও fsck-এর সীমা (২), ছবি আর চার ধাপ (৩), তিন mode (২), COW (১)। পর্ব ৪৪
ঙ-০৫RAID 0, 1, 5, 6 আর 10 তুলনা করুন। ছয়টি ৪ TB ডিস্কে প্রতিটিতে ব্যবহারযোগ্য জায়গা কত? RAID 5-এর small-write penalty কী? RAID কি backup? — ৮ নম্বর (মাঝারি)
তিন কৌশল: striping (ডেটা ভাগ করে বহু ডিস্কে — গতি), mirroring (হুবহু কপি) আর parity (XOR — হারানো ব্লক = বাকিদের XOR). RAID-এর নাম আসে Patterson, Gibson ও Katz-এর ১৯৮৮ সালের গবেষণাপত্র থেকে।
| লেভেল | কৌশল | জায়গা (N টি S) | ৬ × ৪ TB | কয়টি ডিস্ক হারানো সয় | ছোট লেখায় I/O |
|---|---|---|---|---|---|
| 0 | striping | N × S | ২৪ TB | ০ | ১ |
| 1 | mirroring | S (জোড়ায় N/2 × S) | ১২ TB (তিন জোড়া; ছয়টিতেই একই কপি হলে ৪ TB) | জোড়ায় একটি | ২ |
| 5 | striping + ঘোরানো parity | (N − ১) × S | ২০ TB | ১ | ৪ |
| 6 | দুটি parity | (N − ২) × S | ১৬ TB | যেকোনো ২ | ৬ |
| 10 | mirror-এর ওপর stripe | N/2 × S | ১২ TB | প্রতি mirror-জোড়ায় ১ | ২ |
Small-write penalty: RAID 5-এ একটি ছোট ব্লক বদলাতে পুরোনো ডেটা আর পুরোনো parity পড়া, নতুন ডেটা আর নতুন parity লেখা — ৪টি I/O, কারণ P′ = P ⊕ Dপুরোনো ⊕ Dনতুন. Rebuild-এর সময় বাকি সব ডিস্ক পুরো পড়তে হয়; বড় ডিস্কে সময় আর URE-এর (unrecoverable read error — কোনো সেক্টর পড়তে না পারা) ঝুঁকি বড় — তাই বড় অ্যারেতে RAID 6.
RAID backup নয়: ডিস্ক নষ্ট হওয়া সামলায়, কিন্তু ভুল করে মোছা, ransomware বা ভুল কমান্ড সাথে সাথে সব ডিস্কে লেখা হয়। দরকার ৩-২-১ নিয়ম — তিন কপি, দুই মাধ্যম, একটি অন্য জায়গায় (অফলাইন বা বদলানো-যায়-না এমন)। নম্বর কোথায়: তিন কৌশল (১), টেবিল আর জায়গার হিসাব (৪), small-write penalty (২), backup-এর প্রশ্ন (১)। পর্ব ৪৫
৭ · অংশ চ — সুরক্ষা, ভার্চুয়ালাইজেশন, distributed আর বাস্তব OS (মডিউল ৭–৯)
রিভিশন: পর্ব ৪৬ (access matrix), পর্ব ৪৭ (permission), পর্ব ৪৯ (MAC), পর্ব ৫০ (hypervisor), পর্ব ৫১ (container), পর্ব ৫৩ (clock), পর্ব ৫৫ আর পর্ব ৫৬ (বাস্তব kernel).
চ-০১Access matrix কী? এটি ACL আর capability list হিসেবে কীভাবে বাস্তবায়ন হয়? দুটির সুবিধা-অসুবিধা তুলনা করুন। — ৮ নম্বর (মাঝারি)
সংজ্ঞা: Access matrix-এর সারি = domain (যেমন একজন user বা প্রসেস), কলাম = object (ফাইল, প্রিন্টার, অন্য domain), ঘর = অধিকারের সেট। ঘরটি বেশিরভাগ ফাঁকা, তাই পুরো টেবিল রাখা হয় না — কাটা হয় দুইভাবে:
F1 F2 printer
D1 read — —
D2 — read print
D3 read,write — —
column of F1 → ACL: F1: {D1: read, D3: read+write}
row of D2 → capability list: D2: {F2: read, printer: print}
| মাপকাঠি | ACL (কলাম) | Capability (সারি) |
|---|---|---|
| কোথায় থাকে | object-এর সাথে | domain-এর হাতে — জাল-করা-যায়-না এমন টোকেন |
| “এই ফাইল কে পড়তে পারে?” | সহজ | কঠিন — সব domain খুঁজতে হয় |
| Revocation | সহজ — তালিকা থেকে মুছলেই হলো | কঠিন — ছড়ানো টোকেন ফেরত আনতে হয় |
| Least privilege ও হস্তান্তর | কঠিন | সহজ — শুধু দরকারি টোকেন দেওয়া |
| Confused deputy | প্রবণ | সমাধান হয় (Hardy, ১৯৮৮) |
| উদাহরণ | Unix-এর rwx, POSIX ACL, Windows DACL | খোলা file descriptor; seL4-এর capability |
লক্ষ করুন: fd একটি capability — অনুমতি যাচাই হয় open-এর সময়, তাই পরে chmod করলেও পুরোনো fd পড়তে পারে। Linux-এর “capabilities” (যেমন CAP_NET_BIND_SERVICE) আসলে root-এর ক্ষমতার টুকরো — নামের মিল, ধারণা আলাদা।
নম্বর কোথায়: matrix-এর সংজ্ঞা ও ছোট উদাহরণ (২), কলাম ও সারি ধরে কাটা (২), তুলনার টেবিল (৩), fd বা বাস্তব উদাহরণ (১)। পর্ব ৪৬
চ-০২Linux-এ rwx permission, umask আর setuid ব্যাখ্যা করুন। umask 027 হলে নতুন ফাইল আর directory-র mode কত? — ৫ নম্বর (সহজ)
Permission: owner, group, other — প্রত্যেকের জন্য r = ৪, w = ২, x = ১. যাচাই হয় একটিমাত্র শ্রেণিতে: আপনি owner হলে শুধু owner-বিট দেখা হয়। Directory-তে x মানে ভেতর দিয়ে যাওয়া, w মানে নাম যোগ-মোছা। 755 = rwxr-xr-x, 644 = rw-r--r--.
umask: নতুন mode = চাওয়া mode AND (NOT umask) — বিয়োগ নয়, বিট মোছা। ফাইল: 0666 & ~027 = 640; directory: 0777 & ~027 = 750.
Setuid: exec-এর সময় effective UID ফাইলের owner হয়ে যায়। passwd এভাবে root-এর ফাইল /etc/shadow বদলায়, আর real UID দেখে বোঝে কার পাসওয়ার্ড। Sticky bit (১৭৭৭, যেমন /tmp) অন্যের ফাইল মোছা আটকায়। নিয়ম least privilege — chmod 777 কখনো সমাধান নয়; setuid ফাইলের তালিকা নিয়মিত নিরীক্ষা করুন।
নম্বর কোথায়: rwx আর শ্রেণির নিয়ম (২), umask-এর হিসাব (২), setuid (১)। পর্ব ৪৭
চ-০৩Popek–Goldberg-এর virtualization শর্ত আর উপপাদ্য লিখুন। পুরোনো x86 কেন শর্ত ভাঙত, আর কোন তিন উপায়ে সমস্যার সমাধান হয়েছে? Type 1 আর type 2 hypervisor-এর পার্থক্য কী? — ১০ নম্বর (কঠিন)
তিন শর্ত (Popek ও Goldberg, ১৯৭৪): একটি ভালো VMM-এর — (১) equivalence: VM-এর ভেতরে প্রোগ্রামের আচরণ আসল যন্ত্রের মতো, শুধু সময় আর সম্পদের পরিমাণ আলাদা হতে পারে; (২) resource control: সব আসল সম্পদের নিয়ন্ত্রণ VMM-এর হাতে; (৩) efficiency: বেশিরভাগ instruction VMM-এর হস্তক্ষেপ ছাড়া সরাসরি CPU-তে চলে।
দুই শব্দ: privileged instruction — user mode-এ চালালে trap হয়; sensitive instruction — যা নিয়ন্ত্রণ-অবস্থা (mode, page table, interrupt) বদলায় বা তার ওপর ফল নির্ভর করে। উপপাদ্য: প্রচলিত CPU-র জন্য VMM বানানো যায় যদি sensitive ⊆ privileged. যুক্তির খসড়া: VMM guest kernel-কে কম ক্ষমতায় চালায়। Sensitive নয় এমন instruction সরাসরি চললেও ফল একই (equivalence ও efficiency). প্রতিটি sensitive instruction privileged হলে তা trap করে VMM-এ আসে, VMM আসল অবস্থা না ছুঁয়ে guest-এর নকল অবস্থায় অনুকরণ করে (resource control) — এটিই trap-and-emulate.
x86-এর সমস্যা: কিছু instruction sensitive কিন্তু privileged নয় — যেমন POPF কম ক্ষমতায় interrupt flag বদলানোর অংশটি চুপচাপ উপেক্ষা করে, trap দেয় না; SGDT/SIDT trap ছাড়াই আসল টেবিলের ঠিকানা দেখায়। তাই VT-x-এর আগে বিশুদ্ধ trap-and-emulate অসম্ভব ছিল।
তিন সমাধান: (১) binary translation (VMware, ১৯৯০-এর দশকের শেষে) — guest kernel-এর কোড চালানোর আগে সমস্যাজনক instruction বদলে নিরাপদ কোড; guest অপরিবর্তিত। (২) paravirtualization (Xen, ২০০৩) — guest kernel বদলে সমস্যাজনক কাজে সরাসরি hypercall; দ্রুত, কিন্তু guest বদলাতে হয়। (৩) হার্ডওয়্যার সহায়তা (Intel VT-x ২০০৫, AMD-V ২০০৬) — guest চলে non-root mode-এ, sensitive কিছু করলে VM exit, অবস্থা VMCS-এ, hypervisor অনুকরণ করে VM entry দেয়; মেমরিতে EPT/NPT.
Type 1 বনাম type 2: type 1 সরাসরি হার্ডওয়্যারে চলে (ESXi, Xen, Hyper-V) — ডেটা সেন্টারে; type 2 একটি host OS-এর ওপর অ্যাপ হিসেবে (VirtualBox, VMware Workstation) — ডেস্কটপে। Linux-এর KVM kernel-কেই hypervisor বানায়, তাই দুই দলেই ফেলার যুক্তি আছে।
নম্বর কোথায়: তিন শর্ত (২), দুই সংজ্ঞা আর উপপাদ্য ও যুক্তি (৩), x86-এর উদাহরণ (১), তিন সমাধান (৩), type 1/2 (১)। পর্ব ৫০
চ-০৪Container আর virtual machine-এর পার্থক্য লিখুন। Container কোন kernel-বৈশিষ্ট্যের ওপর দাঁড়িয়ে? কখন কোনটি বাছবেন? — ৮ নম্বর (মাঝারি)
সংজ্ঞা: VM হলো hypervisor-এর ওপর নকল হার্ডওয়্যারে নিজের kernel-সহ পূর্ণ OS. Container কোনো ছোট VM নয় — host-এর kernel-এ চলা সাধারণ প্রসেস, যাকে namespace দিয়ে আলাদা দৃশ্য (PID, mount, network, user…) আর cgroup দিয়ে সীমিত সম্পদ (CPU, মেমরি, pids, I/O) দেওয়া হয়েছে; নিজের root আসে image-এর স্তর আর overlayfs থেকে।
| মাপকাঠি | Virtual machine | Container |
|---|---|---|
| Kernel | প্রতিটির নিজের guest kernel | host-এর kernel সবার এক |
| চালু হতে | OS বুট — সাধারণত সেকেন্ড বা বেশি | একটি প্রসেস চালু — সাধারণত অনেক দ্রুত |
| বাড়তি মেমরি | পুরো OS-এর জন্য | প্রায় শুধু অ্যাপের |
| সীমানা | শক্ত — হার্ডওয়্যার-সহায়তায় আলাদা | দুর্বল — kernel-এর একটি বাগ সবার ঝুঁকি |
| ভিন্ন OS | চালানো যায় (Linux-এ Windows) | একই kernel-এর জন্য তৈরি প্রোগ্রাম |
কখন কোনটি: নিজেদের অনেকগুলো সার্ভিস ঘন করে চালাতে container; ভিন্ন OS বা অচেনা গ্রাহকের কোড আলাদা রাখতে VM. মাঝামাঝি পথ microVM (Firecracker) আর gVisor বা Kata; public cloud প্রায়ই container-কে VM বা microVM-এর ভেতরে রাখে। Container-এর সুরক্ষা বাড়ায় seccomp, ছাঁটা capability, AppArmor/SELinux আর rootless — যেখানে user namespace-এ ভেতরের root বাইরে সাধারণ ব্যবহারকারী।
নম্বর কোথায়: দুটির সংজ্ঞা (২), namespace আর cgroup-এর ভূমিকা (২), টেবিল (৩), বাছাই বা সুরক্ষার মন্তব্য (১)। পর্ব ৫১ · পর্ব ৫২
চ-০৫Lamport-এর logical clock-এর নিয়ম লিখুন আর একটি সময়রেখার ছবিতে প্রয়োগ করুন। এর সীমাবদ্ধতা কী, আর vector clock তা কীভাবে মেটায়? — ৬ নম্বর (মাঝারি, ছবিসহ)
প্রেক্ষাপট: distributed system-এ সবার এক ঘড়ি নেই, ঘড়ি সরে যায়। কিন্তু অনেক কাজে দরকার শুধু ক্রম — happened-before (a → b): একই প্রসেসে a আগে; অথবা a একটি বার্তা পাঠানো আর b সেটি পাওয়া; অথবা এদের শিকল।
Lamport clock-এর নিয়ম: (১) প্রতিটি ঘটনার আগে L = L + ১; (২) বার্তায় পাঠানোর মুহূর্তের L যায়; (৩) পেলে L = max(নিজের L, বার্তার L) + ১.
P1: a(1) -------- b(2)
\ m1 carries 1
P2: c(1) -- d(2) -- e(3)
\ m2 carries 3
P3: f(1) ------------ g(4)
d = max(1, 1) + 1 = 2 g = max(1, 3) + 1 = 4
chain a -> d -> e -> g : 1 < 2 < 3 < 4
নিশ্চয়তা আর সীমা: a → b হলে L(a) < L(b) — প্রতিটি ধাপে মান বাড়ে। কিন্তু উল্টোটি সত্য নয়: L(c) = ১ < L(b) = ২, অথচ c আর b-এর মধ্যে কোনো বার্তা-শিকল নেই — দুটি concurrent. Lamport সংখ্যা দেখে কারণ-সম্পর্ক বলা যায় না। (সমান মানে tie ভাঙতে প্রসেস id জুড়ে মোট ক্রম বানানো হয় — distributed mutual exclusion-এ কাজে লাগে।)
Vector clock: প্রতিটি প্রসেস সবার জন্য একটি করে গণনা রাখে; নিজের ঘটনায় নিজের ঘর +১, পেলে ঘরে ঘরে max, তারপর নিজের ঘর +১. এখানে b = (2, 0, 0), d = (1, 2, 0) — কোনোটি অন্যটির ≤ নয়, তাই concurrent; আর a = (1, 0, 0) ≤ g = (1, 3, 2), তাই a → g. নিয়ম: a → b ⇔ V(a) ≤ V(b) এবং V(a) ≠ V(b). দাম — প্রতিটি বার্তায় n টি সংখ্যা।
নম্বর কোথায়: happened-before (১), তিন নিয়ম (১), ছবিতে সঠিক মান (২), সীমাবদ্ধতা আর vector clock (২)। পর্ব ৫৩
চ-০৬সংক্ষিপ্ত টীকা লিখুন (৫টি শব্দ): (ক) priority inversion (খ) spooling (গ) convoy effect (ঘ) RCU (ঙ) context switch. — ১০ নম্বর, প্রতিটি ২ (মাঝারি)
(ক) Priority inversion: উচ্চ-অগ্রাধিকারের task H একটি lock-এর অপেক্ষায়, যা ধরে আছে নিম্ন task L; মাঝারি task M এসে L-কে সরিয়ে রাখে, ফলে H অনির্দিষ্টকাল আটকে থাকে। ১৯৯৭ সালে Mars Pathfinder-এর বারবার রিসেটের পেছনে এটিই ছিল বলে জানা যায়। প্রতিকার priority inheritance (L সাময়িকভাবে H-এর priority পায়) বা priority ceiling.
(খ) Spooling: প্রিন্টারের মতো ভাগ-অযোগ্য ধীর ডিভাইসের কাজ আগে ডিস্কের সারিতে লেখা, তারপর একটি spooler একে একে ছাপে — কেউ প্রিন্টার ধরে অপেক্ষা করে না, তাই deadlock-ও কমে।
(গ) Convoy effect: FCFS-এ একটি লম্বা CPU-bound কাজের পেছনে অনেক ছোট কাজ আটকে থাকা — গড় অপেক্ষা বাড়ে, I/O যন্ত্রও অলস থাকে। Burst ২৪, ৩, ৩-এ লম্বাটি আগে গেলে গড় অপেক্ষা ১৭, শেষে গেলে ৩.
(ঘ) RCU (read-copy-update): পড়া বেশি, লেখা কম এমন ডেটায় পাঠক lock ছাড়াই পড়ে; লেখক কপি বদলে pointer দিয়ে নতুন সংস্করণ প্রকাশ করে, আর পুরোনোটি মোছে grace period-এর পরে, যখন আগের সব পাঠক শেষ। Linux kernel-এ ব্যাপক।
(ঙ) Context switch: চলমান প্রসেস বা থ্রেডের CPU-অবস্থা (register, PC, SP, flags, page table-এর ঠিকানা) PCB/TCB-তে রেখে আরেকটির অবস্থা ফিরিয়ে আনা। এ সময় কোনো user কাজ হয় না — খাঁটি overhead; পুরো quantum q ব্যবহার হলে আর প্রতি switch-এ s গেলে efficiency = q/(q + s), যেমন q = ৪ ms, s = ১ ms-এ ৮০%.
নম্বর কোথায়: প্রতিটিতে সংজ্ঞা (১) আর কারণ, উদাহরণ বা প্রতিকার (১)। পর্ব ২৯ · পর্ব ২৭ · পর্ব ১৭ · পর্ব ০৯
চ-০৭সংক্ষিপ্ত টীকা লিখুন (বাস্তব সিস্টেম): (ক) eBPF (খ) Android-এর Zygote (গ) OOM killer (ঘ) Windows-এর IRQL (ঙ) xv6. — ১০ নম্বর, প্রতিটি ২ (মাঝারি)
(ক) eBPF: Linux kernel-এর ভেতরে নিরাপদে চালানো ছোট প্রোগ্রাম। লোডের আগে verifier প্রতিটি পথ যাচাই করে (সীমার ভেতরে মেমরি, শেষ হওয়া লুপ, শুধু অনুমোদিত helper), তারপর JIT আর একটি hook-এ বসানো; ফল জমে map-এ। Tracing, নেটওয়ার্ক আর নিরাপত্তায় ব্যবহৃত।
(খ) Zygote: Android-এ বুটের সময় runtime আর সাধারণ class আগেই লোড করে রাখা একটি প্রসেস; প্রতিটি অ্যাপ তার fork থেকে জন্মায়। ফলে অ্যাপ দ্রুত চালু হয়, আর copy-on-write-এ page ভাগ থাকায় মেমরি বাঁচে।
(গ) OOM killer: Linux ডিফল্টভাবে প্রয়োজনের চেয়ে বেশি মেমরির প্রতিশ্রুতি দেয় (overcommit); সত্যিই ফুরোলে kernel RSS, swap, page table আর oom_score_adj মিলিয়ে সবচেয়ে বেশি points-এর প্রসেসকে SIGKILL দেয় (adj −1000 হলে কখনো নয়)। Container-এ memory.max পেরোলে একই ঘটনা, exit code ১৩৭ = ১২৮ + ৯.
(ঘ) IRQL: Windows-এ CPU-র অগ্রাধিকার-স্তর — PASSIVE (০), APC (১), DISPATCH (২), তার ওপরে ডিভাইসের DIRQL. DISPATCH বা তার ওপরে thread switch হয় না, তাই wait বা page fault নিষেধ; ভাঙলে bugcheck (IRQL_NOT_LESS_OR_EQUAL).
(ঙ) xv6: MIT-র শিক্ষণ-OS, Unix V6-এর আধুনিক পুনর্লিখন, RISC-V-এ চলে; kernel কয়েক হাজার লাইন, তাই পুরোটা পড়া যায়। PCB মানে struct proc, মেমরি Sv39-এর তিন স্তরের page table, সর্বোচ্চ ফাইল (১২ + ২৫৬) × ১০২৪ = ২৭৪,৪৩২ byte.
নম্বর কোথায়: প্রতিটিতে কী আর কেন (১), একটি নির্দিষ্ট খুঁটিনাটি (১)। পর্ব ৫৫ · পর্ব ৫৪ · পর্ব ৩৮ · পর্ব ৫৬ · পর্ব ৫৮
চ-০৮DAC আর MAC-এর পার্থক্য লিখুন। Bell–LaPadula আর Biba মডেলের নিয়ম কী? Linux-এ sandbox বানাতে কোন কোন হাতিয়ার আছে? — ৫ নম্বর (মাঝারি)
DAC: ফাইলের মালিক অনুমতি ঠিক করেন (Unix rwx, ACL). MAC: কেন্দ্রীয় নীতি ঠিক করে; মালিক বা root-ও তা বদলাতে পারেন না (SELinux — label ও type enforcement; AppArmor — path-ভিত্তিক profile).
Bell–LaPadula (গোপনীয়তা): no read up — নিজের স্তরের ওপরের ডেটা পড়া নিষেধ; no write down — নিচের স্তরে লেখা নিষেধ (গোপন তথ্য যেন নিচে না গড়ায়)। Biba (অখণ্ডতা): উল্টো — no read down, no write up (অবিশ্বস্ত ডেটা যেন ওপরের ডেটা নষ্ট না করে)।
Linux-এর হাতিয়ার: seccomp (syscall-এর ছাঁকনি; filter mode-এ BPF প্রোগ্রাম রায় দেয়), no_new_privs, capability ছাঁটা, namespace, Landlock. chroot নিরাপত্তার সীমানা নয় — শুধু path-এর মূল বদলায়। Denial এলে log পড়ে নীতি ঠিক করাই সমাধান, পুরো ব্যবস্থা বন্ধ করা নয়। নম্বর কোথায়: DAC/MAC (২), দুই মডেল (২), হাতিয়ার (১)। পর্ব ৪৯
৮ · ভাইভা — মুখে উত্তরের কৌশল, follow-up আর মডিউলভিত্তিক দ্রুত প্রশ্ন
ভাইভায় পরীক্ষক আপনার প্রথম উত্তর শুনেই পরের প্রশ্ন বানান (follow-up প্রশ্ন) — “fork কী?” থেকে তিন ধাপে “fork-এর আগে fflush কেন?”. তাই প্রথম উত্তরটি এমনভাবে দিন, যাতে পরের প্রশ্ন আপনার চেনা পথে আসে।
তিন বাক্যের কাঠামো
প্রশ্ন: “TLB কী?” উত্তর: “সাম্প্রতিক page-অনুবাদের ছোট, দ্রুত associative cache (কী)। না থাকলে প্রতিটি ছোঁয়ায় page table পড়তে বাড়তি মেমরি-পড়া লাগত (কেন)। Context switch-এ ASID/PCID না থাকলে flush লাগে (সীমা)।” তৃতীয় বাক্যটিই পরের প্রশ্নের দরজা খোলে।
চারটি অভ্যাস যা নম্বর এনে দেয়
- জোরে ভাবুন: সংখ্যার প্রশ্নে পথটি মুখে বলুন — “t = ১-এ P2 এল, বাকি ৪ < ৭, তাই SRTF-এ P1 থামবে”। পথ ঠিক থাকলে ছোট ভুলেও নম্বর থাকে।
- ছবি আঁকুন: পাঁচ অবস্থার ছবি বা দুই থ্রেডের সময়রেখা দশ বাক্যের কাজ করে।
- OS নির্দিষ্ট করুন: “Linux-এ…”, “Windows-এ…”, “POSIX অনুযায়ী…” — যেখানে আচরণ OS-ভেদে আলাদা, সেখানে এই শব্দগুলোই আপনাকে নির্ভুল রাখে।
- প্রশ্ন নিশ্চিত করুন: “RR-এ একই মুহূর্তে আগমন আর সময় শেষ হলে কোন প্রথা ধরব?” — প্রথা জিজ্ঞেস করা দুর্বলতা নয়, পেশাদারি।
যে প্রশ্নের উত্তর জানেন না — সৎভাবে সামলানো
- স্বীকার করুন: “পুরো নিশ্চিত নই” বলা দুর্বলতা নয়; ভুল কথা জোর দিয়ে বললে বাকি উত্তর নিয়েও সন্দেহ জাগে।
- যা জানেন সেখান থেকে যুক্তি দিন: “EEVDF-এর খুঁটিনাটি মনে নেই, তবে CFS-এ সবচেয়ে কম vruntime-এর task চলে; নতুন নীতিও ন্যায্য ভাগের ওপর দাঁড়ানো, শুধু বাছাইয়ে deadline যোগ হয়েছে বলে জানি।”
- যাচাইয়ের পথ বলুন: “Linux-এ man page আর kernel-এর ডকুমেন্টেশনে দেখতাম, আর একটি ছোট প্রোগ্রাম চালিয়ে মিলিয়ে নিতাম।” — বাস্তব কাজে এটিই আসল দক্ষতা।
- বানাবেন না: সংখ্যা, বছর বা kernel version মনে না থাকলে তা স্পষ্ট বলুন, আনুমানিক হলে “যতদূর মনে পড়ে” যোগ করুন।
Follow-up প্রশ্নের শিকল
| শুরুর প্রশ্ন | প্রায়ই আসা follow-up | উত্তরের সূত্র |
|---|---|---|
| প্রসেস কী? | PCB-তে কী? → Linux-এ তার নাম? → থ্রেডে কী আলাদা? | PCB-র ছয় ঘর; task_struct; থ্রেডের নিজের শুধু PC, register, stack |
| fork কী? | মেমরি কি তখনই কপি হয়? → exec ব্যর্থ হলে? → fork-এর আগে fflush কেন? | copy-on-write; child-এ _exit; stdio buffer-ও কপি হয় |
| Deadlock-এর চার শর্ত? | কোনটি ভাঙা সবচেয়ে বাস্তব? → lock ordering কেন কাজ করে? → Banker's বাস্তবে নেই কেন? | circular wait; rank-এর যুক্তি; Max আগে জানা যায় না |
| Paging কী? | TLB কেন? → context switch-এ TLB-র কী হয়? → huge page কেন? | দুবার মেমরি-পড়া; flush বা ASID/PCID; TLB reach |
| Semaphore কী? | Mutex থাকতে semaphore কেন? → condition variable থেকে পার্থক্য? → futex কী? | মালিকানা; স্মৃতি থাকে বনাম থাকে না; প্রতিযোগিতা ছাড়া syscall নেই |
| Container কী? | VM থেকে কম নিরাপদ কেন? → rootless কীভাবে? → PID 1 কেন বিশেষ? | kernel এক; user namespace-এ UID map; orphan reap আর signal |
ভাইভা কুইকফায়ার — দ্রুত প্রশ্ন, ছোট উত্তর
জোরে উত্তর বলুন, তারপর প্রশ্নে চেপে মেলান — প্রতিটিতে ২০–৩০ সেকেন্ডের বেশি নয়। উত্তরগুলো ইচ্ছা করে এক–তিন বাক্যে রাখা।
ভিত্তি (পর্ব ০১–০৭)
ভ-০১Kernel আর shell-এর পার্থক্য কী? (সহজ)
Kernel পূর্ণ ক্ষমতায় চলা OS-এর কেন্দ্র, সম্পদের আসল মালিক। Shell user mode-এর একটি সাধারণ প্রোগ্রাম, যা কমান্ড পড়ে system call দিয়ে kernel-কে কাজ করায় — একই kernel-এ bash, zsh বা GUI বসতে পারে। পর্ব ০১
ভ-০২Interrupt আর trap-এর পার্থক্য কী? (মাঝারি)
Interrupt asynchronous — বাইরের ডিভাইস থেকে, যেকোনো মুহূর্তে। Trap বা exception synchronous — চলমান instruction থেকেই (system call, শূন্য দিয়ে ভাগ, page fault). দুটিতেই CPU kernel-এর নির্দিষ্ট handler-এ যায়। পর্ব ০৪
ভ-০৩printf কি system call? (সহজ)
না; এটি C library-র ফাংশন, লেখা buffer-এ জমিয়ে পরে write system call ডাকে। তাই printf আর write মেশালে আউটপুটের ক্রম উল্টে যেতে পারে। পর্ব ০৫
ভ-০৪Policy আর mechanism-এর একটি উদাহরণ দিন। (মাঝারি)
Timer interrupt দিয়ে প্রসেস থামানোর ক্ষমতা mechanism; time slice কত আর কে আগে পাবে, সেটি policy. দুটি আলাদা রাখলে kernel না বদলেই নীতি বদলানো যায়। পর্ব ০৬
ভ-০৫Linux-এ প্রথম user-space প্রসেস কোনটি? সেটি মারা গেলে কী হয়? (সহজ)
init — আজ বেশিরভাগ distribution-এ systemd, PID 1. এটি orphan প্রসেসের অভিভাবক; মারা গেলে kernel panic. পর্ব ০৭
ভ-০৬Multiprogramming আর multitasking-এর পার্থক্য? (সহজ)
Multiprogramming মেমরিতে অনেক কাজ রেখে I/O-র অপেক্ষার ফাঁকে CPU ব্যস্ত রাখে; multitasking তার সাথে timer দিয়ে নিয়মিত পালা বদলে response time কমায়। পর্ব ০২
প্রসেস ও থ্রেড (পর্ব ০৮–১৫)
ভ-০৭Program আর process-এর পার্থক্য? (সহজ)
Program ডিস্কের নিষ্ক্রিয় ফাইল; process তার চলমান রূপ — নিজের মেমরি, PC, register, খোলা ফাইল আর PID সহ। এক program থেকে অনেক process হতে পারে। পর্ব ০৮
ভ-০৮Context switch-এ কী সংরক্ষিত হয়, আর একে overhead কেন বলে? (মাঝারি)
Register, PC, SP, flags, FPU/SIMD অবস্থা, page table-এর ঠিকানা (x86-এ CR3) আর kernel stack. এ সময় কোনো user কাজ হয় না, আর প্রসেস বদলালে TLB ও cache ঠান্ডা হওয়ার পরোক্ষ খরচও আছে। পর্ব ০৯
ভ-০৯fork-এর ফেরত মান কী কী? (সহজ)
Child-এ 0, parent-এ child-এর PID, ব্যর্থ হলে parent-এ −1 আর কোনো child হয় না। পর্ব ১০
ভ-১০exec সফল হলে কী থাকে, কী বদলায়? (মাঝারি)
PID, parent আর খোলা fd থাকে (FD_CLOEXEC না থাকলে); কোড, ডেটা, heap, stack আর stdio buffer সব নতুন। সফল exec কখনো ফেরে না। পর্ব ১০
ভ-১১Zombie আর orphan-এর পার্থক্য? (সহজ)
Zombie শেষ হয়েছে কিন্তু parent wait করেনি — exit status আটকে আছে। Orphan এখনো চলছে কিন্তু parent আগে শেষ — তাকে PID 1 বা subreaper দত্তক নেয়। পর্ব ১০
ভ-১২Pipe-এর read কখন 0 ফেরত দেয়? (মাঝারি)
যখন buffer খালি এবং সব প্রসেসে লেখার সব মুখ বন্ধ। তাই fork-এর পর অব্যবহৃত মুখ বন্ধ না করলে পাঠক কখনো EOF পায় না। পর্ব ১২
ভ-১৩SIGTERM আর SIGKILL-এর পার্থক্য? (সহজ)
SIGTERM (১৫) ধরা যায় — প্রোগ্রাম গুছিয়ে বের হতে পারে; SIGKILL (৯) ধরা বা উপেক্ষা করা যায় না, kernel সাথে সাথে শেষ করে। ভদ্র নিয়ম: আগে SIGTERM, সময় পেরোলে SIGKILL. পর্ব ১৩
ভ-১৪একই প্রসেসের দুই থ্রেডের switch কেন প্রসেস switch-এর চেয়ে সস্তা? (মাঝারি)
CPU scheduling (পর্ব ১৬–২১)
ভ-১৫Convoy effect কী? (সহজ)
FCFS-এ একটি লম্বা কাজের পেছনে ছোট কাজগুলোর আটকে থাকা — গড় অপেক্ষা বাড়ে, I/O যন্ত্র অলস থাকে। পর্ব ১৭
ভ-১৬Round Robin-এ quantum খুব বড় বা খুব ছোট হলে কী হয়? (সহজ)
খুব বড় হলে FCFS-এর মতো; খুব ছোট হলে context switch-এর খরচেই CPU যায়। মোটা দাগের নিয়ম: প্রায় ৮০% burst যেন q-এর চেয়ে ছোট হয়। পর্ব ১৮
ভ-১৭Starvation কী, aging কীভাবে প্রতিকার করে? (সহজ)
উঁচু অগ্রাধিকারের কাজ আসতে থাকায় নিচেরটি কখনো CPU না পাওয়া। Aging অপেক্ষার সাথে অগ্রাধিকার বাড়ায়, তাই অপেক্ষার একটি ঊর্ধ্বসীমা তৈরি হয়। পর্ব ১৮
ভ-১৮MLFQ burst না জেনে কীভাবে ছোট কাজকে আগে রাখে? (মাঝারি)
নতুন কাজ ওপরের queue-তে ঢোকে; পুরো allotment খেলে নিচে নামে — স্তরই “এ পর্যন্ত কত চলেছে”-র মাপ। Starvation ঠেকাতে নির্দিষ্ট সময় পরপর boost. পর্ব ১৯
ভ-১৯EDF কেন এক CPU-তে optimal? (কঠিন)
যেকোনো সফল schedule-এ যদি পরের deadline-এর কাজ আগে চলে, দুটি অংশ অদলবদল করলে কোনো deadline ভাঙে না (exchange argument); বারবার করলে EDF পাওয়া যায়। তাই কোনো নীতি পারলে EDF-ও পারে — এক CPU-তে U ≤ ১ হলেই। পর্ব ২০
ভ-২০Linux-এর CFS পরের task কীভাবে বাছে? (মাঝারি)
প্রতিটি task-এর vruntime = চলার সময় × (nice 0-এর weight ÷ নিজের weight) — বেশি weight মানে vruntime ধীরে বাড়ে; red-black tree-তে সাজানো, সবচেয়ে বাঁয়ের (সবচেয়ে কম vruntime) চলে। Linux ৬.৬ থেকে EEVDF: eligible task-দের মধ্যে সবচেয়ে আগের virtual deadline. পর্ব ২১
কনকারেন্সি ও deadlock (পর্ব ২২–২৯)
ভ-২১count = 5-এ একসাথে একটি count++ আর একটি count-- চললে ফল কত হতে পারে? (সহজ)
৪, ৫ বা ৬ — কারণ প্রতিটি load, বদল আর store-এ ভাঙে, আর দুই ধারার ধাপ মিশে একজনের লেখা আরেকজন মুছে দিতে পারে। পর্ব ২২
ভ-২২Mutex আর binary semaphore কি একই? (মাঝারি)
না। Mutex-এর মালিক আছে — যে নেয় সে-ই ছাড়ে, তাই priority inheritance আর ভুল-ধরা সম্ভব; semaphore-এর মালিক নেই, যেকোনো থ্রেড signal দিতে পারে — সংকেতের জন্য উপযুক্ত। পর্ব ২৪
ভ-২৩Condition variable-এ wait কেন while লুপে? (মাঝারি)
Mesa semantics-এ জাগার আগে অন্য থ্রেড শর্ত বদলে দিতে পারে, আর spurious wakeup-ও সম্ভব; তাই জেগে আবার শর্ত দেখতে হয়। পর্ব ২৫
ভ-২৪Spinlock কখন mutex-এর চেয়ে ভালো? (মাঝারি)
Multicore-এ, lock খুব অল্প সময় ধরা থাকলে, আর যেখানে ঘুমানো নিষেধ (interrupt handler). এক CPU-তে প্রায় কখনো না — spinner CPU ধরে রাখলে holder চলতেই পারে না। পর্ব ২৩
ভ-২৫Deadlock, livelock আর starvation-এর পার্থক্য? (মাঝারি)
Deadlock-এ দলের কেউই এগোয় না, সবাই অপেক্ষায়; livelock-এ সবাই ব্যস্ত, অবস্থা বদলাচ্ছে, কিন্তু কাজ এগোয় না; starvation-এ সিস্টেম চলে, শুধু একজন বারবার বঞ্চিত। পর্ব ২৭
ভ-২৬Resource-allocation graph-এ চক্র মানেই কি deadlock? (মাঝারি)
প্রতিটি resource-এর একটি instance হলে হ্যাঁ; একাধিক instance হলে না-ও হতে পারে — detection algorithm চালিয়ে দেখতে হয়। চক্র না থাকলে deadlock নেই, নিশ্চিত। পর্ব ২৭
ভ-২৭৪টি প্রসেসের প্রত্যেকের সর্বোচ্চ ৩টি একক লাগে — deadlock-মুক্ত থাকতে অন্তত কতটি একক দরকার? (মাঝারি)
n(k − ১) + ১ = ৪ × ২ + ১ = ৯. ৮টি হলে চারজনই দুটি করে নিয়ে তৃতীয়টির জন্য আটকে যেতে পারে; ৯টিতে অন্তত একজন শেষ করে ছেড়ে দেয়। পর্ব ২৭
ভ-২৮Lock-free আর wait-free-এর পার্থক্য? (কঠিন)
Lock-free: সবসময় কেউ না কেউ এগোয়, যদিও একজন বারবার হারতে পারে; wait-free: প্রত্যেকে সসীম ধাপে শেষ করে। CAS-ভিত্তিক Treiber stack lock-free; তার বড় ফাঁদ ABA সমস্যা। পর্ব ২৯
মেমরি (পর্ব ৩০–৩৮)
ভ-২৯Logical আর physical address-এর পার্থক্য? (সহজ)
CPU যা তৈরি করে তা logical; MMU অনুবাদ করে RAM-এ যা পাঠায় তা physical. Compile আর load-time binding-এ দুটি এক, execution-time binding-এ আলাদা। পর্ব ৩০
ভ-৩০৩২-বিট ঠিকানা, ৪ KiB page, ৪ বাইটের entry — সমতল page table কত বড়? (সহজ)
ভ-৩১Inverted page table-এর সুবিধা আর অসুবিধা? (মাঝারি)
প্রতিটি physical frame-এর জন্য একটি entry, পুরো সিস্টেমে একটি টেবিল — আকার RAM-এর সমানুপাতিক। কিন্তু খোঁজা ধীর (⟨pid, vpn⟩ hash লাগে) আর shared page কঠিন। পর্ব ৩৩
ভ-৩২Minor আর major page fault-এর পার্থক্য? (মাঝারি)
Minor ডিস্ক ছাড়াই মেটে (zero-fill, copy-on-write, page cache-এ থাকা page) — মাইক্রোসেকেন্ড; major-এ ডিস্ক বা swap থেকে পড়তে হয় — মিলিসেকেন্ড, হাজার গুণ ধীর। পর্ব ৩৫
ভ-৩৩Dirty bit কেন লাগে? (সহজ)
Page বদলেছে কি না জানায়। পরিষ্কার victim ডিস্কে না লিখেই ফেলে দেওয়া যায়, তাই সেই replacement-এ I/O অর্ধেক — শুধু নতুন page পড়া, পুরোনোটি লেখা নেই। পর্ব ৩৬
ভ-৩৪OPT কেন বাস্তবায়ন করা যায় না, তবু শেখানো হয় কেন? (মাঝারি)
ভবিষ্যতের reference জানতে হয়। তবে সম্ভাব্য সেরা ফল দেয় বলে অন্য algorithm মাপার মাপকাঠি — বহুল প্রচলিত string 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1-এ ৩ frame-এ FIFO ১৫, LRU ১২, OPT ৯টি fault. পর্ব ৩৬
ভ-৩৫VSZ আর RSS-এর পার্থক্য? Container-এর exit code ১৩৭ মানে কী? (মাঝারি)
VSZ সব virtual এলাকার মোট আকার (প্রতিশ্রুতি), RSS এই মুহূর্তে RAM-এ থাকা অংশ। ১৩৭ = ১২৮ + ৯, অর্থাৎ SIGKILL — প্রায়ই cgroup-এর memory.max পেরিয়ে OOM kill. পর্ব ৩৮
I/O, স্টোরেজ ও ফাইল সিস্টেম (পর্ব ৩৯–৪৫)
ভ-৩৬Hard link আর symbolic link-এর পার্থক্য? (সহজ)
Hard link একই inode-এর আরেকটি নাম — link count বাড়ে, একই file system-এ, আসল নাম মুছলেও ফাইল থাকে। Symlink নিজের inode-এ একটি path রাখে — অন্য file system বা directory-কে দেখাতে পারে, লক্ষ্য মুছলে ঝুলে যায়। পর্ব ৪২
ভ-৩৭Directory-র hard link কেন নিষেধ? (মাঝারি)
Cycle তৈরি হতো — গাছ-ঘোরা অসীম লুপে পড়ত, reference count শূন্য না হওয়ায় জায়গা ফেরত আসত না, আর ..-র মানে অস্পষ্ট হতো। পর্ব ৪২
ভ-৩৮write() ফিরলেই কি ডেটা ডিস্কে? (মাঝারি)
না। পথ stdio buffer → kernel-এর page cache → ডিস্ক; fflush প্রথম ধাপ পার করে, fsync শেষ ধাপ — আর তার ফেরত মানও দেখতে হয়। পর্ব ৪১
ভ-৩৯SSTF-এর সমস্যা কী? (সহজ)
দূরের অনুরোধ অনির্দিষ্টকাল অপেক্ষা করতে পারে (starvation), আর এটি সর্বোত্তমও নয় — ক্লাসিক সারিতে LOOK-এর মোট (২০৮) SSTF-এর (২৩৬) চেয়ে কম। পর্ব ৪০
ভ-৪০SSD-তে write amplification কেন হয়? (মাঝারি)
Flash-এ জায়গায় বসে overwrite হয় না — লেখা হয় page-এ, মোছা হয় বড় block-এ; garbage collection বৈধ page সরিয়ে কপি করে, তাই host যা লেখে তার চেয়ে বেশি NAND-এ লেখা হয়। TRIM আর over-provisioning তা কমায়। পর্ব ৪০
ভ-৪১RAID কি backup? (সহজ)
না। RAID ডিস্ক নষ্ট হওয়া সামলায়; ভুল করে মোছা বা ransomware সাথে সাথে সব ডিস্কে যায়। দরকার ৩-২-১ নিয়মের backup আর নিয়মিত restore-মহড়া। পর্ব ৪৫
সুরক্ষা ও নিরাপত্তা (পর্ব ৪৬–৪৯)
ভ-৪২Protection আর security-র পার্থক্য? (সহজ)
Protection ভেতরের mechanism — কে কোন object-এ কী করতে পারে, আর প্রতিটি চেষ্টায় যাচাই। Security বাইরের হুমকিসহ পুরো সিস্টেমের সুরক্ষা — authentication, encryption, patch সব মিলিয়ে। পর্ব ৪৬
ভ-৪৩পাসওয়ার্ডে salt কেন, আর SHA-256 কেন যথেষ্ট নয়? (মাঝারি)
Salt একই পাসওয়ার্ডকে আলাদা hash দেয় আর আগে-বানানো টেবিল অকেজো করে। SHA-256 দ্রুত, তাই চুরি হওয়া hash-এ অফলাইন অনুমান সস্তা — দরকার ইচ্ছাকৃত ধীর Argon2, bcrypt বা scrypt. পর্ব ৪৮
ভ-৪৪NX, ASLR আর stack canary — কোনটি কী থামায়? (মাঝারি)
NX ডেটাকে কোড হিসেবে চালানো আটকায়; ASLR ঠিকানা আগে জানা কঠিন করে; canary stack উপচে ফেরার ঠিকানা বদলানো ধরে। কোনোটি একা যথেষ্ট নয়। পর্ব ৪৮
ভ-৪৫chroot কি sandbox? (মাঝারি)
না; শুধু path-এর মূল বদলায় — UID, capability, syscall, PID বা নেটওয়ার্ক আলাদা করে না। Sandbox-এর জন্য seccomp, namespace, capability ছাঁটা আর MAC মিলিয়ে লাগে। পর্ব ৪৯
ভার্চুয়ালাইজেশন ও আধুনিক OS (পর্ব ৫০–৫৪)
ভ-৪৬Full virtualization আর paravirtualization-এর পার্থক্য? (সহজ)
Full-এ guest OS অপরিবর্তিত — binary translation বা VT-x সামলায়; para-তে guest kernel বদলানো, সে hypercall দিয়ে hypervisor-কে সরাসরি ডাকে। পর্ব ৫০
ভ-৪৭Namespace আর cgroup-এর পার্থক্য? (মাঝারি)
Namespace ঠিক করে কী দেখা যাবে (PID, mount, network…); cgroup ঠিক করে কতটা ব্যবহার করা যাবে (CPU, মেমরি, pids, I/O) আর হিসাব রাখে। পর্ব ৫১
ভ-৪৮Serverless-এ cold start কী? (সহজ)
কাজ না থাকায় instance শূন্যে নামার পর নতুন অনুরোধে sandbox, runtime আর কোড চালু করার দেরি। ছোট প্যাকেজ, হালকা init, provisioned concurrency বা snapshot তা কমায়। পর্ব ৫২
ভ-৪৯RTOS আর সাধারণ OS-এর মূল পার্থক্য? (মাঝারি)
RTOS সবচেয়ে খারাপ সময়ের সীমা (determinism) দেয় — fixed-priority preemptive scheduler, ছোট footprint, ছোট ISR; সাধারণ OS গড় throughput আর ন্যায্যতা খোঁজে। পর্ব ৫৪
বাস্তব OS (পর্ব ৫৫–৫৯)
ভ-৫০Kernel-এর কোডে spinlock ধরে বা interrupt handler-এ কেন ঘুমানো যায় না? (কঠিন)
Interrupt context-এ পেছনে ঘুমাতে-পারা কোনো task নেই; আর spinlock-ধারী ঘুমালে অন্য CPU ঘুরতেই থাকবে — deadlock বা দীর্ঘ আটকে থাকা। তাই সেখানে মেমরি চাইতে GFP_ATOMIC, ঘুমাতে-পারা জায়গায় GFP_KERNEL. পর্ব ৫৫
ভ-৫১Windows handle আর Unix file descriptor-এর মিল ও অমিল? (মাঝারি)
দুটিই প্রসেস-নিজস্ব সূচক, অধিকার যাচাই হয় খোলার সময়। Handle শুধু ফাইল নয় — প্রসেস, thread, event, registry key, যেকোনো kernel object-এর জন্য। পর্ব ৫৬
ভ-৫২“সার্ভার ধীর” — প্রথম কী করবেন? (মাঝারি)
আন্দাজে সেটিং বদল নয়: আগে লক্ষণ মাপা (rate, error, latency-র percentile), baseline-এর সাথে তুলনা, তারপর USE পদ্ধতি — প্রতিটি সম্পদের utilization, saturation, errors — আর vmstat, iostat-এর মতো চেকলিস্ট। পর্ব ৫৭
৯ · AI-কে কড়া পরীক্ষক বানান — আর তার উত্তর যাচাই করুন
AI-কে উত্তরদাতা না বানিয়ে পরীক্ষক বানান: নিজে উত্তর লিখে নম্বর দিতে বলুন, আর তার follow-up-এর উত্তর মুখে দিন। তবে OS-এ AI-এর আত্মবিশ্বাসী ভুল সাধারণ — প্রথা গুলিয়ে ফেলা Gantt chart, ভুল OS-এর কমান্ড, পুরোনো kernel-তথ্য আর chmod 777-এর মতো বিপজ্জনক পরামর্শ।
একটি prompt, যা AI-কে পরীক্ষক বানায় আর নিজের হিসাব দেখাতে বাধ্য করে:
OS নিয়ে AI-এর উত্তরে যেসব ভুল প্রায়ই থাকে
| ভুল | ফল | কীভাবে ধরবেন |
|---|---|---|
| RR-এ নতুন আগমন আর preempted-এর ক্রম উল্টো | Gantt chart আর গড় WT ভুল (খ-০২) | প্রথা লিখে দিন; এই পাতার simulator-এ চালান |
| EAT-এ TLB-সময় hit-এ গোনা, miss-এ বাদ | সংখ্যা কাছাকাছি কিন্তু ভুল (ঘ-০২) | hit আর miss-এর খরচ আলাদা করে লিখতে বলুন |
| Banker's-এ Work-এ Allocation-এর বদলে Need যোগ | ভুল safe sequence (গ-০৫) | শেষে Work = মোট resource কি না দেখুন |
| Linux-এর আচরণকে সব OS-এর বলা | যেমন overcommit বা fork — Windows-এ আলাদা | প্রশ্ন করুন: কোন OS, কোন version; ডকুমেন্টেশন মেলান |
chmod 777 বা অকারণ sudo-র পরামর্শ | নিরাপত্তার ফাঁক (চ-০২) | least privilege: ঠিক কার, কোন অধিকার লাগে তা বের করুন |
AI-এর উত্তর মেনে নেওয়ার আগে — চেকলিস্ট
নিজেকে যাচাই করুন
প্রথমে একটি ক্রম সাজানোর প্রশ্ন, তারপর লিখিত আর ভাইভার মূল তথ্য নিয়ে MCQ. ভুল হলে কারণসহ ব্যাখ্যা পাবেন।
ক্রমএকটি ১০ নম্বরের OS উত্তরের অংশগুলো পরীক্ষকের নম্বর-ভাগের ক্রমে সাজান (▲▼ চেপে সরান)
- নির্ভুল সংজ্ঞা, শর্তসহ
- নামসহ ছবি — state diagram, টেবিল বা Gantt chart
- নির্দিষ্ট সংখ্যার একটি ছোট উদাহরণ
- সুবিধা, অসুবিধা আর দাম
- বাস্তব সিস্টেমে কোথায় — যেমন Linux বা Windows-এর নাম
C-তে for (int i = 0; i < 3; i++) fork(); চালালে মূল প্রসেসসহ মোট কতটি প্রসেস হয় (কোনো fork ব্যর্থ হয় না)?
- ৮
- ৪
- ৬
- ৭
এক স্তরের page table; memory access ১০০ ns, TLB lookup ২০ ns (hit আর miss দুই ক্ষেত্রেই গোনা), TLB hit ratio ৯০%. Effective access time কত?
- ১২০ ns
- ১৩০ ns
- ১৪০ ns
- ২২০ ns
Banker's algorithm-এর প্রসঙ্গে unsafe অবস্থা সম্পর্কে কোনটি সঠিক?
- Unsafe মানে deadlock ইতিমধ্যে ঘটে গেছে
- Unsafe অবস্থায় deadlock অসম্ভব, কারণ কোনো অনুরোধ মঞ্জুর হয় না
- Deadlock সম্ভব, কিন্তু নিশ্চিত নয়
- একাধিক safe sequence থাকলে অবস্থাটি unsafe
কোন page replacement নীতিতে frame-সংখ্যা বাড়ালে page fault বাড়তে পারে (Belady's anomaly)?
- LRU
- OPT
- LRU আর OPT দুটিই
- FIFO
Popek–Goldberg অনুযায়ী একটি CPU-তে শুধু trap-and-emulate দিয়ে VMM বানানো যায় কখন?
- প্রতিটি sensitive instruction privileged হলে
- প্রতিটি privileged instruction sensitive হলে
- CPU-তে অন্তত চারটি privilege ring থাকলে
- Hardware-এ দুই স্তরের page table থাকলে
Peterson-এর সমাধানে দুজনই flag true করল; তারপর P0 লিখল turn = 1, তারপর P1 লিখল turn = 0. কে আগে critical section-এ ঢুকবে?
- P1
- P0
- দুজনই একসাথে
- কেউ না — deadlock
ছয়টি ৪ TB ডিস্কে RAID 6 বানালে ব্যবহারযোগ্য জায়গা কত?
- ২৪ TB
- ২০ TB
- ১৬ TB
- ১২ TB
Lamport logical clock-এ দুটি ঘটনার জন্য L(a) < L(b). নিশ্চিতভাবে কী বলা যায়?
- a → b (a, b-এর আগে ঘটেছে)
- a আর b অবশ্যই concurrent
- b → a হতে পারে
- b → a নয়; a → b অথবা দুটি concurrent
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বে ব্যবহৃত সব শব্দ এখানে একসাথে:
মনে রাখুন
- কাঠামোয় নম্বর: সংজ্ঞা → ছবি → উদাহরণ → সুবিধা ও অসুবিধা → বাস্তব সিস্টেম; ২ নম্বরে দুই–তিন বাক্য, ৫ নম্বরে একটি ছবি বা টেবিল, ১০ নম্বরে দুটি আর একটি উদাহরণ বা প্রমাণ।
- ছবির প্রশ্নে: প্রতিটি অবস্থা আর তীরের নাম; waiting → running আর ready → waiting অসম্ভব; Banker's-এ প্রতিটি Work, শেষে Work = মোট resource.
- প্রমাণের প্রশ্নে: অনুমান লিখুন, তারপর বিপরীত ধরে বিরোধ (Peterson), exchange argument (SJF, EDF), induction (safe state) বা inclusion property (LRU) — শেষে ∎.
- সংখ্যার প্রশ্নে: প্রথা আগে — tie-নিয়ম, RR-এর আগমন, TLB-সময়, C-SCAN-এর ফেরার লাফ; তারপর টেবিল, সূত্র, একক আর চূড়ান্ত উত্তর আলাদা করে।
- ভাইভায়: তিন বাক্য — কী, কেন, সীমা; জোরে ভাবা, ছবি আঁকা, OS নির্দিষ্ট করা; না জানলে সৎভাবে বলা আর যাচাইয়ের পথ জানানো।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৬৩ · OS ইন্টারভিউর প্রশ্ন — ধারণা থেকে বাস্তব সিস্টেমপরবর্তী পর্বইন্টারভিউর ধাঁচে OS-এর প্রশ্ন।
- পর্ব ৬০ · Numerical সমস্যা — scheduling, page replacement, Banker's আর diskএকই মডিউলসংখ্যার প্রশ্নের অনুশীলন।
- পর্ব ৬১ · MCQ প্রশ্নব্যাংক — অপারেটিং সিস্টেমএকই মডিউলপুরো কোর্সের MCQ.
- পর্ব ২৮ · Deadlock avoidance আর detection — Banker's algorithmফিরে দেখুনsafety আর request algorithm-এর পূর্ণ ব্যাখ্যা।
- অপারেটিং সিস্টেম · কোর্স হোম৬৪টি পর্বপুরো কোর্সের রোডম্যাপ — ১০টি মডিউল।
- DBMS ও SQL · লিখিত ও ভাইভা প্রশ্নসম্পর্কিত কোর্সtransaction, concurrency আর recovery-র মডেল উত্তর।
- DSA · লিখিত ও ভাইভা প্রশ্নসম্পর্কিত কোর্সheap, hashing আর graph-এর প্রমাণ ও মডেল উত্তর।