এই পর্বে যা শিখবেন
- হার্ড ডিস্কের গঠন — platter, track, sector, cylinder, head আর arm; zoned bit recording, 512 B বনাম 4 KiB sector, আর LBA
- Access time-এর সূত্র আর পরীক্ষার ধাঁচের সংখ্যাভিত্তিক সমস্যা — rotational latency, transfer time, random বনাম sequential I/O
- FCFS, SSTF, SCAN, C-SCAN, LOOK আর C-LOOK-এর পূর্ণ trace, কোন নিয়মে কোন উত্তর, SSTF-এর starvation আর একটি সর্বনিম্ন-সীমার প্রমাণ
- বাস্তব সিস্টেম — NCQ, Linux-এর I/O scheduler, NVMe-তে কেন none
- SSD-র ভেতর — NAND cell, page আর erase block, FTL, garbage collection, write amplification-এর হিসাব, wear leveling, TRIM; সঙ্গে formatting, partition, bad block আর DAS/NAS/SAN
১ · হার্ড ডিস্কের ভেতরে — platter থেকে LBA
পর্ব ৩৯-এ দেখেছেন, OS একটি ডিভাইসের সাথে কথা বলে device driver আর device controller-এর মাধ্যমে, আর বড় ডেটা সরায় DMA দিয়ে। এই পর্বে সেই ডিভাইসগুলোর মধ্যে সবচেয়ে গুরুত্বপূর্ণটি — স্থায়ী স্টোরেজ। আপনার ফাইল, ডেটাবেস, swap, এমনকি OS নিজেই থাকে এখানে। আর এখানেই একটি কম্পিউটারের সবচেয়ে বড় গতির ফারাক: RAM-এ একটি পড়া ১০০ ns-এর কাছাকাছি, ঘোরা ডিস্কে কয়েক ms — প্রায় এক লাখ গুণ বেশি।
একটি HDD খুললে দেখবেন এক বা একাধিক চকচকে গোল চাকতি, একটি অক্ষে গাঁথা — এগুলো platter. প্রতিটির দুই পিঠে চৌম্বক আবরণ, যেখানে বিট লেখা থাকে। Platter-গুলো একসাথে মিনিটে কয়েক হাজার পাক ঘোরে — ল্যাপটপে প্রায়ই 5400, ডেস্কটপে 7200, কিছু সার্ভার-ডিস্কে 10000 বা 15000 RPM. প্রতিটি পিঠের ওপর ভাসে একটি read-write head; সব head বসানো একটি arm-এর মাথায়, আর arm-গুলো একসাথে ভেতরে-বাইরে সরে। ঘোরার সময় head পিঠ থেকে মাত্র কয়েক ন্যানোমিটার উঁচুতে বাতাসের স্তরে ভাসে — তাই ধাক্কা লাগলে head পিঠে আঘাত করতে পারে (head crash).
পাশ থেকে দেখা ওপর থেকে একটি platter
arm ──┬── head 0 ▶ ═══ platter 0 (ওপর পিঠ) .-~~~~~-.
├── head 1 ▶ ═══ platter 0 (নিচ পিঠ) / .---. \ ← track (গোল রেখা)
├── head 2 ▶ ═══ platter 1 (ওপর পিঠ) | ( ● ) | ● = অক্ষ (spindle)
└── head 3 ▶ ═══ platter 1 (নিচ পিঠ) \ '---' / track-এর একটি টুকরো
'-~~~~~-' = sector
cylinder = সব পিঠের একই ব্যাসার্ধের track-গুলো একসাথে
- Track: একটি পিঠে একটি নির্দিষ্ট ব্যাসার্ধের গোল রেখা। একটি পিঠে লাখখানেকেরও বেশি track থাকতে পারে।
- Sector: track-এর একটি টুকরো — পড়া-লেখার সবচেয়ে ছোট একক। প্রতিটি sector-এ ডেটার সাথে থাকে চেনার তথ্য আর ভুল ধরার ও শোধরানোর কোড (ECC).
- Cylinder: সব পিঠের একই ব্যাসার্ধের track মিলে একটি কাল্পনিক চোঙ। Arm না সরিয়েই পুরো cylinder পড়া যায়। Disk scheduling-এর অঙ্কে “cylinder 0–199” বলতে এটাই বোঝায়।
একটি পুরোনো রেকর্ড-প্লেয়ারের কথা ভাবুন, কিন্তু অনেকগুলো রেকর্ড একটির ওপর আরেকটি সাজানো, আর প্রতিটির জন্য আলাদা সুঁই — সব সুঁই একটি দণ্ডে বাঁধা। কোনো গান শুনতে হলে আগে দণ্ডটি সঠিক দাগে সরাতে হয় (seek), তারপর রেকর্ড ঘুরে গানের শুরু সুঁইয়ের নিচে আসা পর্যন্ত অপেক্ষা (rotational latency), তারপর গান বাজা (transfer). প্রথম দুটি কাজই সময় খায়; আসল বাজানো প্রায়ই সবচেয়ে ছোট অংশ।
Zoned bit recording — বাইরের track-এ বেশি sector
বাইরের দিকের track ভেতরের track-এর চেয়ে লম্বা। পুরোনো ডিস্কে প্রতিটি track-এ সমান sector থাকত, ফলে বাইরের track-এ বিটগুলো অযথা ছড়ানো থাকত। আধুনিক ডিস্ক zoned bit recording ব্যবহার করে: track-গুলো কয়েকটি zone-এ ভাগ, আর বাইরের zone-এর প্রতিটি track-এ বেশি sector. Platter একই গতিতে ঘোরে, তাই এক পাকে বাইরের track-এর নিচ দিয়ে বেশি sector যায় — বাইরের দিকে transfer rate বেশি, প্রায়ই ভেতরের দিকের প্রায় দ্বিগুণের কাছাকাছি (ডিস্কভেদে আলাদা)। তাই একটি HDD-র শুরুর LBA-গুলো (বাইরের দিকে) শেষের দিকের চেয়ে দ্রুত পড়ে।
512 byte বনাম 4 KiB — Advanced Format
বহু দশক ধরে sector-এর আকার ছিল 512 byte. ডিস্ক বড় হওয়ায় এত ছোট sector-এ প্রতিটির সাথে আলাদা ফাঁক আর ECC-র খরচ বেশি পড়ছিল, তাই প্রায় ২০১০ সাল থেকে নির্মাতারা 4096 byte-এর physical sector চালু করেন — একে Advanced Format বলে। পুরোনো সফটওয়্যার যাতে না ভাঙে, অনেক ডিস্ক বাইরে 512 byte-এর logical sector দেখায় কিন্তু ভেতরে 4 KiB-তে লেখে (512e, “512 emulation”); কিছু ডিস্ক বাইরেও 4 KiB দেখায় (4Kn, “4K native”).
Alignment-এর ফাঁদ: 512e ডিস্কে একটি partition যদি 4 KiB-এর সীমানায় শুরু না হয় (যেমন পুরোনো নিয়মে LBA 63-এ), তবে file system-এর প্রতিটি 4 KiB block দুটি physical sector-এ ছড়িয়ে পড়ে। তখন একটি block লিখতে ডিস্ককে দুটি sector পড়ে, বদলে, আবার লিখতে হয় (read-modify-write) — লেখা লক্ষণীয়ভাবে ধীর হয়। আধুনিক partition টুল ডিফল্টে প্রথম partition 1 MiB (LBA 2048) থেকে শুরু করে, যা সব সাধারণ সীমানায় মেলে। Linux-এ lsblk -t logical আর physical sector-এর আকার দেখায়।
CHS থেকে LBA
পুরোনো দিনে OS-কে একটি sector চাইতে হতো তিনটি সংখ্যায়: cylinder, head, sector — CHS. কিন্তু zone-এ zone-এ sector-সংখ্যা বদলালে, আর ডিস্ক নিজেই খারাপ sector সরিয়ে রাখলে, এই তিন সংখ্যা আর আসল জ্যামিতির সাথে মেলে না। তাই আধুনিক ডিস্ক বাইরে দেখায় শুধু একটি ক্রমিক নম্বর — LBA 0, 1, 2, … শেষ পর্যন্ত। কোন LBA আসলে কোন platter-এর কোন track-এ, তা জানে কেবল ডিস্কের firmware.
তবু একটি মোটামুটি নিয়ম সত্য থাকে, আর disk scheduling-এর পুরো তত্ত্ব তার ওপর দাঁড়ানো: কাছাকাছি LBA সাধারণত কাছাকাছি physical জায়গায়, তাই OS LBA-র দূরত্বকে head-এর দূরত্বের আনুমানিক মাপ ধরে; অঙ্কের “cylinder নম্বর” সেই সরল মডেল।
১৯৫৬ সালে IBM বাজারে আনে প্রথম বাণিজ্যিক হার্ড ডিস্ক — IBM 350, যা RAMAC 305 কম্পিউটারের অংশ। তাতে ছিল ২৪ ইঞ্চির ৫০টি platter, আর ধারণক্ষমতা প্রায় ৫০ লাখ অক্ষর (আজকের হিসাবে মোটামুটি ৩.৭৫ MB). আকার ছিল প্রায় দুটি বড় আলমারির সমান। আজ একটি ৩.৫ ইঞ্চির ডিস্কে কয়েক কোটি গুণ বেশি ডেটা ধরে — অথচ seek আর ঘোরার মূল যান্ত্রিক নীতি প্রায় একই রয়ে গেছে। এজন্যই ঘোরা ডিস্কের গতি ধারণক্ষমতার তুলনায় সামান্যই বেড়েছে।
২ · Access time — seek, rotational latency আর transfer
একটি sector পড়তে ডিস্ককে তিনটি কাজ পরপর করতে হয়:
- Seek time: arm সরিয়ে head-কে ঠিক cylinder-এ নেওয়া, আর সেখানে স্থির হওয়া (settle). পাশের track-এ যেতে ১ ms-এর কম, পুরো ডিস্ক পেরোতে ১০ ms-এর বেশিও লাগতে পারে; ডেস্কটপ ডিস্কের গড় seek প্রায়ই কয়েক ms থেকে ১০ ms-এর আশপাশে বলা হয় (নির্মাতার datasheet দেখুন)।
- Rotational latency: চাওয়া sector ঘুরে head-এর নিচে আসা পর্যন্ত অপেক্ষা। সবচেয়ে ভালো ক্ষেত্রে ০, সবচেয়ে খারাপ ক্ষেত্রে পুরো এক পাক; এলোমেলো অবস্থানে গড়ে অর্ধেক পাক.
- Transfer time: sector-গুলো head-এর নিচ দিয়ে যাওয়ার সময় আসল পড়া। সময় = ডেটার আকার ÷ transfer rate.
গড় rotational latency = ½ × (60 ÷ RPM) সেকেন্ড
উদাহরণ ১ (পরীক্ষার সবচেয়ে পরিচিত অঙ্ক): 7200 RPM ডিস্কের গড় rotational latency কত? এক মিনিটে ৭২০০ পাক, তাই এক পাক = ৬০,০০০ ms ÷ ৭২০০ = ৮.৩৩৩ ms. গড় latency = অর্ধেক পাক = ৪.১৬৭ ms (প্রায় ৪.১৭ ms).
উদাহরণ ২: একই ডিস্ক, গড় seek ৯ ms, transfer rate ১৫০ MB/s (১ MB = ১০৬ byte ধরে)। একটি এলোমেলো 4 KiB (৪০৯৬ byte) block পড়তে কত সময়? Transfer = ৪০৯৬ ÷ ১৫০,০০,০০,০০০ সেকেন্ড ≈ ০.০২৭ ms. মোট = ৯ + ৪.১৬৭ + ০.০২৭ ≈ ১৩.১৯৪ ms. অর্থাৎ সেকেন্ডে মোটামুটি ১,০০০ ÷ ১৩.১৯৪ ≈ ৭৬টি এলোমেলো পড়া — এই মাপকে বলে IOPS. আসল ডেটা পড়ায় গেল মাত্র ০.০২৭ ms.
উদাহরণ ৩ — random বনাম sequential: ১,০০০টি 4 KiB block পড়তে হবে। এলোমেলো জায়গায় থাকলে প্রতিটির জন্য আলাদা seek আর latency: ১,০০০ × ১৩.১৯৪ ≈ ১৩.২ সেকেন্ড। পাশাপাশি থাকলে একবার seek, একবার latency, তারপর একটানা ৪০,৯৬,০০০ byte transfer: ৯ + ৪.১৬৭ + ২৭.৩০৭ ≈ ৪০.৫ ms — প্রায় ৩২৬ গুণ দ্রুত. তাই file system ফাইলের block পাশাপাশি রাখতে চায় (পর্ব ৪৩), আর OS অনুরোধগুলো সাজিয়ে পাঠায়।
নিচের calculator এই তিনটি উদাহরণ নিজে হিসাব করে। সংখ্যাগুলো (seek, rate) বদলে নিজের বইয়ের অঙ্ক যাচাই করতে পারেন — তবে আগে হাতে করুন।
// HDD access time = seek + rotational latency + transfer (all in ms).
function hdd(rpm, seekMs, mbPerS, bytes) {
const rotMs = 60000 / rpm; // one full revolution
const latMs = rotMs / 2; // on average, wait half a revolution
const xferMs = bytes / (mbPerS * 1e6) * 1000; // bytes / (bytes per ms)
return { rotMs, latMs, xferMs, total: seekMs + latMs + xferMs };
}
const f = (x) => x.toFixed(3);
console.log("RPM one rotation avg rotational latency");
for (const rpm of [5400, 7200, 10000, 15000]) {
const r = hdd(rpm, 0, 1, 0);
console.log(String(rpm).padEnd(8) + (f(r.rotMs) + " ms").padEnd(15) + f(r.latMs) + " ms");
}
// Example drive: 7200 RPM, 9 ms average seek, 150 MB/s sustained transfer.
const SEEK = 9, RATE = 150, BLOCK = 4096, N = 1000;
const r = hdd(7200, SEEK, RATE, BLOCK);
console.log("\nOne random 4 KiB read: seek " + SEEK + " + latency " + f(r.latMs) +
" + transfer " + f(r.xferMs) + " = " + f(r.total) + " ms");
console.log("=> about " + Math.round(1000 / r.total) + " random reads per second (IOPS)");
const random = N * r.total; // every block pays seek + latency
const seq = hdd(7200, SEEK, RATE, N * BLOCK).total; // one seek, then stream
console.log(N + " random 4 KiB reads: " + f(random) + " ms");
console.log(N + " blocks read sequentially: " + f(seq) + " ms");
console.log("sequential is " + (random / seq).toFixed(1) + "x faster");
console.log("effective rate, random: " + (N * BLOCK / random / 1000).toFixed(3) + " MB/s");আউটপুট (নির্ধারিত, প্রতিবার একই):
RPM one rotation avg rotational latency
5400 11.111 ms 5.556 ms
7200 8.333 ms 4.167 ms
10000 6.000 ms 3.000 ms
15000 4.000 ms 2.000 ms
One random 4 KiB read: seek 9 + latency 4.167 + transfer 0.027 = 13.194 ms
=> about 76 random reads per second (IOPS)
1000 random 4 KiB reads: 13193.973 ms
1000 blocks read sequentially: 40.473 ms
sequential is 326.0x faster
effective rate, random: 0.310 MB/s
প্রথম টেবিলে প্রতিটি RPM-এর এক পাক আর গড় latency: 7200 RPM-এ ৮.৩৩৩ আর ৪.১৬৭ ms, 15000 RPM-এ ৪ আর ২ ms. দামি দ্রুত ডিস্কও latency অর্ধেকের বেশি কমাতে পারে না। তারপর একটি এলোমেলো 4 KiB পড়া: ১৩.১৯৪ ms, অর্থাৎ প্রায় ৭৬ IOPS. শেষ চার লাইনে random আর sequential-এর তুলনা — ১৩.২ সেকেন্ড বনাম ৪০.৫ ms, ৩২৬ গুণ ফারাক। “১৫০ MB/s-এর ডিস্ক” এলোমেলো 4 KiB পড়ায় বাস্তবে দেয় মাত্র ০.৩১০ MB/s. hdd() ফাংশনটি সূত্রটি হুবহু লেখা; sequential-এর বেলায় একই ফাংশনকে পুরো ৪০,৯৬,০০০ byte একবারে দেওয়া হয়েছে — একটি seek, একটি latency.
এককের সতর্কতা: পরীক্ষার প্রশ্নে transfer rate “MB/s” লেখা থাকলে ১ MB = ১০৬ byte না ২২০ byte, তা প্রশ্নেই দেখে নিন; ডিস্ক-নির্মাতারা সাধারণত দশমিক (১০৬) ব্যবহার করেন। আরেকটি পরিচিত রূপ: “প্রতি track-এ ৪০০টি 512-byte sector, 7200 RPM” — তখন একটি sector পড়ার সময় = এক পাক ÷ ৪০০ = ৮.৩৩৩ ÷ ৪০০ ≈ ০.০২০৮ ms, আর transfer rate = ৪০০ × ৫১২ byte ÷ ৮.৩৩৩ ms ≈ ২৪.৬ MB/s.
৩ · Disk scheduling — FCFS আর SSTF
একটি ব্যস্ত সার্ভারে একসাথে বহু প্রসেস ডিস্কে অনুরোধ পাঠায়। OS-এর কাছে তখন একটি অপেক্ষমাণ সারি — কোনটি আগে ডিস্কে পাঠাবে? Seek-ই সবচেয়ে বড় খরচ, তাই disk scheduling-এর লক্ষ্য: মোট head movement (কত cylinder পেরোল) কমানো, কিন্তু কোনো অনুরোধকে অনির্দিষ্টকাল বসিয়ে না রেখে। অর্থাৎ throughput বাড়ানো, আর গড় ও সবচেয়ে খারাপ response time সামলানো।
একটি বহুতল অফিসের লিফটের কথা ভাবুন। ১২ তলা, ৩ তলা, ৯ তলা, ১ তলা থেকে লোক ডাকছে। লিফট যদি ডাকার ক্রমে ছোটে (১২ → ৩ → ৯ → ১), সারাদিন ওঠানামাতেই যাবে। যদি সবসময় সবচেয়ে কাছের তলায় যায়, তবে মাঝের তলার লোকেরা খুশি, কিন্তু ছাদের কাছের কেউ হয়তো অনেকক্ষণ অপেক্ষা করবেন। আর একদিকে উঠতে উঠতে সবাইকে তুলে, তারপর নামতে নামতে নামালে — দক্ষও, ন্যায্যও। Disk scheduling-এর তিনটি মূল ধারণা ঠিক এই তিনটি।
এই পর্বের ক্লাসিক অঙ্ক (Silberschatz-এর পাঠ্যবইয়ের পরিচিত উদাহরণ): ডিস্কে cylinder 0 থেকে 199. Head এখন cylinder 53-এ। অপেক্ষমাণ অনুরোধ, আসার ক্রমে: 98, 183, 37, 122, 14, 124, 65, 67. প্রতিটি algorithm-এর জন্য বের করতে হবে কোন ক্রমে সেবা হবে আর মোট head movement কত cylinder.
FCFS — যে আগে এসেছে
FCFS (first-come, first-served) অনুরোধগুলো আসার ক্রমেই পাঠায়। ন্যায্য, সহজ, কোনো starvation নেই — কিন্তু head এদিক-ওদিক ছোটে:
53 → 98 → 183 → 37 → 122 → 14 → 124 → 65 → 67
45 + 85 + 146 + 85 + 108 + 110 + 59 + 2 = 640 cylinder
দেখুন 122 থেকে 14, তারপর 14 থেকে 124 — প্রায় পুরো ডিস্ক দুবার পেরোনো, অথচ 122 আর 124 পাশাপাশি। 37 আর 14-র কাছে যাওয়ার সময় যদি একসাথে সেরে নেওয়া যেত, অনেক বাঁচত।
SSTF — সবচেয়ে কাছেরটি আগে
SSTF (shortest seek time first) প্রতিবার head-এর বর্তমান অবস্থান থেকে সবচেয়ে কাছের অনুরোধটি বাছে। এটি CPU scheduling-এর SJF-এর মতো একটি লোভী (greedy) কৌশল। নিচের stepper প্রতিটি ধাপে বাকি অনুরোধগুলোর দূরত্ব দেখায় — কেন ওই অনুরোধ জিতল, তা সরাসরি চোখে পড়বে।
1 start head = 532 serve 653 serve 674 serve 375 serve 146 serve 987 serve 1228 serve 1249 serve 183
| head | |
| এই ধাপের সরা | |
| মোট movement | |
| অপেক্ষমাণ |
- শুরু। Head 53-এ, আটটি অনুরোধ অপেক্ষায়। দূরত্বের তালিকায় সবচেয়ে ছোট 65 (১২ cylinder), তারপর 67 (১৪) আর 37 (১৬)।
- 53 → 65, সরল ১২, মোট ১২। এখন সবচেয়ে কাছে 67 — মাত্র ২ cylinder দূরে।
- 65 → 67, সরল ২, মোট ১৪। পরের প্রতিযোগিতা খুব কাছাকাছি: 37 আছে ৩০ দূরে, 98 আছে ৩১ দূরে। মাত্র ১ cylinder-এর ব্যবধানে 37 জেতে — আর এই সিদ্ধান্তই head-কে নিচের দিকে টেনে নেয়।
- 67 → 37, সরল ৩০, মোট ৪৪। এবার 14 সবচেয়ে কাছে (২৩)।
- 37 → 14, সরল ২৩, মোট ৬৭। নিচে আর কেউ নেই; বাকি সব অনুরোধ ওপরে, সবচেয়ে কাছে 98 (৮৪)।
- 14 → 98, সরল ৮৪, মোট ১৫১। পুরো trace-এর সবচেয়ে বড় লাফ — নিচে নামার দাম এখন দিতে হলো।
- 98 → 122, সরল ২৪, মোট ১৭৫।
- 122 → 124, সরল ২, মোট ১৭৭।
- 124 → 183, সরল ৫৯, মোট ২৩৬। সারি খালি। SSTF-এর মোট head movement ২৩৬ cylinder — FCFS-এর ৬৪০-এর তিন ভাগের এক ভাগের কিছু বেশি।
SSTF সর্বোত্তম নয় — একটি ছোট প্রমাণ
২৩৬ কি সম্ভাব্য সবচেয়ে কম? না। একটি সহজ যুক্তি দিয়ে এই সারির সর্বনিম্ন সীমা বের করা যায়। সবচেয়ে নিচের অনুরোধ 14, সবচেয়ে ওপরেরটি 183, আর head শুরু করে 53 থেকে। যেকোনো ক্রমেই head-কে 14 আর 183 দুটিই ছুঁতে হবে, তাই [14, 183] পুরো অংশটি অন্তত একবার পেরোতে হবে — ১৬৯ cylinder. তার ওপর 53 থেকে প্রথমে যেদিকের প্রান্তে যাওয়া হবে, সেখান থেকে ফিরে আসার পথের কিছু অংশ দুবার পেরোতে হবে: আগে নিচে গেলে ৫৩ − ১৪ = ৩৯, আগে ওপরে গেলে ১৮৩ − ৫৩ = ১৩০. তাই যেকোনো ক্রমের মোট ≥ ১৬৯ + min(৩৯, ১৩০) = ২০৮. আর “আগে নিচে সবগুলো, তারপর ওপরে সবগুলো” ক্রমটি ঠিক ২০৮ দেয় — অর্থাৎ এই সারির সর্বনিম্ন ২০৮, আর সেটি পরের অংশের LOOK (0-এর দিকে) পায়। SSTF ধাপ ৩-এ লোভী সিদ্ধান্তে নিচে গিয়েছিল, কিন্তু 67-এর কাছ থেকে নামায় ফেরার পথ লম্বা হয়েছে। লোভী কৌশল প্রতিটি ধাপে সেরা, পুরো পথে নয়।
SSTF-এর starvation
বড় সমস্যাটি অবশ্য সংখ্যায় নয়, ন্যায্যতায়। বাস্তবে অনুরোধ একবারে আসে না, ক্রমাগত আসে। ধরুন head 50-এর আশপাশে, আর একটি ডেটাবেস 40 থেকে 60-এর মধ্যে একটানা অনুরোধ পাঠাচ্ছে। এর মধ্যে cylinder 190-এ একটি backup প্রোগ্রামের অনুরোধ এলো। SSTF প্রতিবার কাছের নতুন অনুরোধটিই বাছবে — 190-এর অনুরোধ যতক্ষণ কাছে নতুন অনুরোধ আসছে, ততক্ষণ সেবা পাবে না। এটি starvation — CPU scheduling-এর SJF-এর মতোই। ফল: দীর্ঘ tail latency. প্রতিকার দুই রকম: অপেক্ষার সময় অনুযায়ী অগ্রাধিকার বাড়ানো (aging, বা Linux-এর mq-deadline-এর মতো প্রতিটি অনুরোধে একটি সময়সীমা), অথবা head-কে একদিকে চলতে বাধ্য করা — পরের অংশের SCAN পরিবার।
৪ · SCAN, C-SCAN, LOOK আর C-LOOK — লিফটের নিয়ম
SCAN algorithm-এ head একদিকে চলতে চলতে পথের সব অনুরোধ সেরে ডিস্কের প্রান্ত পর্যন্ত যায়, তারপর দিক উল্টে ফেরার পথে বাকিগুলো সারে। লিফটের সাথে মিলের জন্য একে elevator algorithm-ও বলে। কোনো অনুরোধ সর্বোচ্চ প্রায় দুটি পূর্ণ যাত্রার বেশি অপেক্ষা করে না — starvation নেই।
উত্তর নির্ভর করে নিয়মের ওপর — আগে লিখে নিন:
- দিক: head এখন কোন দিকে চলছে? প্রশ্নে না থাকলে নিজের ধরে নেওয়া দিকটি উত্তরে স্পষ্ট লিখুন। Silberschatz-এর SCAN উদাহরণে head 0-এর দিকে চলে; তার C-SCAN উদাহরণে 199-এর দিকে।
- প্রান্ত ছোঁয়া: SCAN আর C-SCAN প্রান্ত (0 বা 199) পর্যন্ত যায়, সেখানে অনুরোধ না থাকলেও; LOOK আর C-LOOK শেষ অনুরোধেই ঘোরে।
- ফেরার লাফ: C-SCAN আর C-LOOK এক প্রান্ত থেকে আরেক প্রান্তে ফেরার সময় কোনো অনুরোধ সারে না। এই লাফ মোট movement-এ গোনা হবে কি না, বই ও প্রশ্নভেদে আলাদা — দুটি সংখ্যাই জানুন, আর কোনটি দিচ্ছেন তা লিখুন।
- সমান দূরত্ব (SSTF): দুটি অনুরোধ head থেকে সমান দূরে হলে এই পর্বের simulator ছোট cylinder নম্বরটি আগে নেয়; প্রশ্নে অন্য নিয়ম (যেমন চলার দিকেরটি আগে) দেওয়া থাকলে সেটিই মানুন, আর উত্তরে লিখুন। ক্লাসিক সারিতে অবশ্য কোনো সমতা আসে না।
চারটির পূর্ণ trace (ক্লাসিক queue, head 53)
| Algorithm ও নিয়ম | সেবার ক্রম আর প্রতিটি ধাপের সরা | মোট |
|---|---|---|
| SCAN, 0-এর দিকে | 53 → 37 → 14 → 0 → 65 → 67 → 98 → 122 → 124 → 183 16 + 23 + 14 + 65 + 2 + 31 + 24 + 2 + 59 | ২৩৬ |
| LOOK, 0-এর দিকে | 53 → 37 → 14 → 65 → 67 → 98 → 122 → 124 → 183 16 + 23 + 51 + 2 + 31 + 24 + 2 + 59 | ২০৮ |
| C-SCAN, 199-এর দিকে | 53 → 65 → 67 → 98 → 122 → 124 → 183 → 199 ⇢ 0 → 14 → 37 12 + 2 + 31 + 24 + 2 + 59 + 16 + [199 ফেরা] + 14 + 23 | ৩৮২ (ফেরা ধরে) ১৮৩ (ফেরা বাদে) |
| C-LOOK, 199-এর দিকে | 53 → 65 → 67 → 98 → 122 → 124 → 183 ⇢ 14 → 37 12 + 2 + 31 + 24 + 2 + 59 + [169 ফেরা] + 23 | ৩২২ (ফেরা ধরে) ১৫৩ (ফেরা বাদে) |
SCAN-এর হিসাবের একটি শর্টকাট: 0-এর দিকে গেলে মোট = (৫৩ − ০) + (১৮৩ − ০) = ৫৩ + ১৮৩ = ২৩৬ — নিচে প্রান্ত পর্যন্ত, তারপর প্রান্ত থেকে সবচেয়ে ওপরের অনুরোধ পর্যন্ত। LOOK একই পথ, কিন্তু 14-এ ঘোরে: (৫৩ − ১৪) + (১৮৩ − ১৪) = ৩৯ + ১৬৯ = ২০৮ — অংশ ৩-এর সর্বনিম্ন সীমা। C-SCAN (ওপরে): (১৯৯ − ৫৩) + ১৯৯ + ৩৭ = ১৪৬ + ১৯৯ + ৩৭ = ৩৮২; লাফ বাদে ১৪৬ + ৩৭ = ১৮৩.
SCAN বনাম C-SCAN — head-এর পথ পাশাপাশি
তুলনা ন্যায্য রাখতে নিচের stepper-এ দুটিই শুরুতে ওপরে (199-এর দিকে) চলছে। দুই রেখায় H হলো head, o হলো এখনো অপেক্ষমাণ অনুরোধ (৪০ ঘরের রেখায় আনুমানিক অবস্থান, তাই 65/67 আর 122/124 এক ঘরে পড়ে)।
| SCAN | |
| C-SCAN |
- শুরু। Head 53-এ, দুটিই ওপরের দিকে চলছে। নিচে অপেক্ষায় 14 আর 37; ওপরে 65, 67, 98, 122, 124, 183.
- 65-এ (+১২), মোট ১২। দুই algorithm-এর পথ এখনো হুবহু এক।
- 67-এ (+২), মোট ১৪।
- 98-এ (+৩১), মোট ৪৫।
- 122-এ (+২৪), মোট ৬৯।
- 124-এ (+২), মোট ৭১।
- 183-এ (+৫৯), মোট ১৩০। ওপরের শেষ অনুরোধ সারা হলো। LOOK বা C-LOOK হলে এখানেই ঘুরত।
- 199-এ (+১৬), মোট ১৪৬। 199-এ কোনো অনুরোধ নেই, তবু SCAN আর C-SCAN প্রান্ত পর্যন্ত যায় — এটিই তাদের সংজ্ঞা।
- পথ আলাদা হলো। SCAN দিক উল্টে নামতে নামতে প্রথমে 37 সারে (+১৬২, মোট ৩০৮)। C-SCAN কিছু না সেরে সোজা 0-এ ফেরে (১৯৯ cylinder, ধরলে মোট ৩৪৫) — আবার একই দিকে, নিচ থেকে ওপরে চলার জন্য।
- 14. SCAN 37 থেকে 14-এ (+২৩), মোট ৩৩১ — SCAN-এর কাজ শেষ। C-SCAN 0 থেকে 14-এ (+১৪), মোট ৩৫৯.
- C-SCAN শেষ করে। 14 থেকে 37 (+২৩): মোট ৩৮২, ফেরার লাফ বাদে ১৮৩. SCAN (ওপরের দিকে) ৩৩১. এই স্থির সারিতে C-SCAN বেশি পথ চলল — তার লাভ অন্য জায়গায়, নিচে দেখুন।
তাহলে C-SCAN কেন?
বাস্তবে অনুরোধ ক্রমাগত আসে, আর ডিস্কজুড়ে মোটামুটি সমানভাবে ছড়ানো থাকে। SCAN একটি প্রান্তে পৌঁছে দিক উল্টালে তার ঠিক পেছনের অংশ মাত্রই সেরে এসেছে — সেখানে নতুন অনুরোধ কম জমেছে। সবচেয়ে বেশি অনুরোধ জমে আছে অন্য প্রান্তে, যারা সবচেয়ে দীর্ঘ সময় অপেক্ষা করছে। C-SCAN (circular SCAN) ডিস্ককে একটি বৃত্তের মতো দেখে: সবসময় একদিকে সেবা, শেষে দ্রুত ফেরা। প্রতিটি cylinder প্রতি চক্রে ঠিক একবার সুযোগ পায় — অপেক্ষার সময় বেশি সমান, বিনিময়ে মোট পথ কিছুটা বেশি।
LOOK আর C-LOOK একই ধারণার ব্যবহারিক রূপ — শেষ অনুরোধ পেরিয়ে খালি প্রান্ত পর্যন্ত যাওয়ার কোনো কারণ নেই। বাস্তবে “SCAN” বা “elevator” বলে যা চালানো হয়, তা প্রায় সবসময় LOOK-এর মতো।
সব নিয়মে সব সংখ্যা — simulator
নিচের simulator ছয়টি algorithm চালায়। DIR ঠিক করে SCAN-পরিবার প্রথমে কোন দিকে যাবে, COUNT_RETURN ঠিক করে C-SCAN/C-LOOK-এর ফেরার লাফ গোনা হবে কি না। প্রথমে নির্বাচিত নিয়মে পুরো trace ছাপে, তারপর চার রকম নিয়মে সব মোটের একটি টেবিল।
// Disk-scheduling simulator: FCFS, SSTF, SCAN, C-SCAN, LOOK, C-LOOK.
const queue = [98, 183, 37, 122, 14, 124, 65, 67];
const head = 53, MAX = 199; // cylinders 0..199
const DIR = "down"; // "down" = move toward 0 first, "up" = toward 199
const COUNT_RETURN = true; // count the C-SCAN / C-LOOK return jump?
const ALGS = ["FCFS", "SSTF", "SCAN", "C-SCAN", "LOOK", "C-LOOK"];
function order(alg, dir) {
const lo = queue.filter(c => c < head).sort((a, b) => b - a); // nearest first
const hi = queue.filter(c => c >= head).sort((a, b) => a - b);
const [first, second] = dir === "down" ? [lo, hi] : [hi, lo];
const edge = dir === "down" ? 0 : MAX, far = MAX - edge;
if (alg === "FCFS") return [...queue];
if (alg === "SSTF") { const left = [...queue], out = []; let h = head;
while (left.length) { // nearest first; a tie goes to the smaller cylinder
left.sort((a, b) => Math.abs(a - h) - Math.abs(b - h) || a - b);
h = left.shift(); out.push(h); }
return out; }
if (alg === "SCAN") return [...first, edge, ...second];
if (alg === "LOOK") return [...first, ...second];
if (alg === "C-SCAN") return [...first, edge, "jump", far, ...second.reverse()];
return [...first, "jump", ...second.reverse()]; // C-LOOK
}
function run(alg, dir, countReturn, show) {
let h = head, total = 0, jump = false; const parts = [], seq = [];
for (const c of order(alg, dir)) {
if (c === "jump") { jump = true; continue; }
const d = Math.abs(c - h);
if (jump && !countReturn) parts.push("[" + d + " not counted]");
else { total += d; parts.push(jump ? "[" + d + " return]" : d); }
jump = false; h = c; seq.push(c);
}
if (show) console.log(alg.padEnd(6) + " order: " + seq.join(" ") +
"\n moves: " + parts.join(" + ") + "\n total = " + total);
return total;
}
for (const a of ALGS) run(a, DIR, COUNT_RETURN, true);
console.log("\nTotals up+return up,no-return down+return down,no-return");
for (const a of ALGS) console.log(a.padEnd(7) + [["up", true], ["up", false], ["down", true],
["down", false]].map(([d, r]) => String(run(a, d, r, false)).padStart(10)).join(" "));আউটপুট (নির্ধারিত, প্রতিবার একই):
FCFS order: 98 183 37 122 14 124 65 67
moves: 45 + 85 + 146 + 85 + 108 + 110 + 59 + 2
total = 640
SSTF order: 65 67 37 14 98 122 124 183
moves: 12 + 2 + 30 + 23 + 84 + 24 + 2 + 59
total = 236
SCAN order: 37 14 0 65 67 98 122 124 183
moves: 16 + 23 + 14 + 65 + 2 + 31 + 24 + 2 + 59
total = 236
C-SCAN order: 37 14 0 199 183 124 122 98 67 65
moves: 16 + 23 + 14 + [199 return] + 16 + 59 + 2 + 24 + 31 + 2
total = 386
LOOK order: 37 14 65 67 98 122 124 183
moves: 16 + 23 + 51 + 2 + 31 + 24 + 2 + 59
total = 208
C-LOOK order: 37 14 183 124 122 98 67 65
moves: 16 + 23 + [169 return] + 59 + 2 + 24 + 31 + 2
total = 326
Totals up+return up,no-return down+return down,no-return
FCFS 640 640 640 640
SSTF 236 236 236 236
SCAN 331 331 236 236
C-SCAN 382 183 386 187
LOOK 299 299 208 208
C-LOOK 322 153 326 157
প্রথম অংশ DIR = "down"-এ পুরো trace: FCFS ৬৪০, SSTF ২৩৬, SCAN ২৩৬, LOOK ২০৮ — উপরের টেবিলের সাথে হুবহু এক। 0-এর দিকে C-SCAN 0 থেকে 199-এ লাফ দিয়ে নামতে নামতে সারে, তাই ৩৮৬ (ফেরা বাদে ১৮৭); পাঠ্যবইয়ের ৩৮২ পেতে DIR = "up" লাগে — শেষ টেবিলের প্রথম কলাম। টেবিলটিই এই পর্বের “উত্তরপত্র”: FCFS আর SSTF দিকের ওপর নির্ভর করে না; SCAN ৩৩১ বা ২৩৬; LOOK ২৯৯ বা ২০৮; C-SCAN ৩৮২/১৮৩ (ওপরে) বা ৩৮৬/১৮৭ (নিচে); C-LOOK ৩২২/১৫৩ বা ৩২৬/১৫৭. order() শুধু সেবার ক্রম বানায়; "jump" চিহ্ন ফেরার লাফ বোঝায়, আর run() সেখানে countReturn দেখে দূরত্ব যোগ করে বা বাদ দেয়।
তুলনা এক নজরে
| Algorithm | ক্লাসিক queue-তে | সুবিধা | অসুবিধা |
|---|---|---|---|
| FCFS | ৬৪০ | সহজ, ন্যায্য, starvation নেই | সবচেয়ে বেশি seek; হালকা লোডেই চলে |
| SSTF | ২৩৬ | গড় seek অনেক কম | starvation; সর্বোত্তমও নয়; মাঝের cylinder সুবিধা পায় |
| SCAN | ২৩৬ (নিচে) / ৩৩১ (ওপরে) | starvation নেই, অপেক্ষার সীমা আছে | অকারণে প্রান্ত ছোঁয়; প্রান্তের অনুরোধের অপেক্ষা বেশি |
| C-SCAN | ৩৮২ বা ১৮৩ (ওপরে) | সবচেয়ে সমান অপেক্ষা | ফেরার লাফ; মোট পথ বেশি |
| LOOK | ২০৮ (নিচে) / ২৯৯ (ওপরে) | SCAN-এর চেয়ে কম পথ | প্রান্তের অসমতা থেকেই যায় |
| C-LOOK | ৩২২ বা ১৫৩ (ওপরে) | সমান অপেক্ষা, খালি প্রান্ত বাদ | ফেরার লাফ থাকে |
লোড কম হলে (সারিতে ০–১টি অনুরোধ) সব algorithm একই; ভারী লোডে LOOK/C-LOOK ভালো ভারসাম্য দেয়।
৫ · বাস্তব সিস্টেমে — NCQ, Linux-এর I/O scheduler আর NVMe
ডিস্ক নিজেই সাজায় — NCQ
OS ডিস্কের আসল জ্যামিতি জানে না, আর platter এই মুহূর্তে কোন কোণে আছে, তা তো নয়ই। ডিস্কের firmware দুটিই জানে। তাই SATA ডিস্কে NCQ (Native Command Queuing) আছে: OS একসাথে সর্বোচ্চ ৩২টি অনুরোধ ডিস্কে পাঠাতে পারে, আর ডিস্ক নিজে ঠিক করে কোনটি আগে — seek আর rotational latency দুটিই হিসাব করে। SCSI/SAS ডিস্কে একই ধারণা আগে থেকেই ছিল (tagged command queuing). ফলে আধুনিক সিস্টেমে disk scheduling দুই স্তরে হয়: OS মোটামুটি সাজায় আর ন্যায্যতা দেখে, ডিস্ক শেষ মুহূর্তের সূক্ষ্ম সাজানোটা করে।
Linux-এর I/O scheduler
Linux-এর block layer (blk-mq, multi-queue) প্রতিটি ডিভাইসের জন্য একটি I/O scheduler বেছে নিতে দেয়। Linux 5.0 (২০১৯) থেকে পুরোনো single-queue পথ আর তার CFQ, deadline, noop scheduler সরিয়ে দেওয়া হয়েছে; এখন বিকল্প চারটি:
none
কোনো সাজানো নেই, শুধু পাশাপাশি অনুরোধ জোড়া লাগানো (merge). দ্রুত SSD আর NVMe-র জন্য, যেখানে seek নেই আর ডিভাইস নিজে সমান্তরালে কাজ করে।
NVMe-তে সাধারণত ডিফল্টmq-deadline
অনুরোধ sector অনুযায়ী সাজানো (elevator-এর মতো), কিন্তু প্রতিটির একটি সময়সীমা — ডিফল্টে পড়া ৫০০ ms, লেখা ৫ সেকেন্ড। সীমা পেরোলে আগে সেবা — SSTF/SCAN-এর starvation-এর প্রতিকার।
SATA ডিস্কে প্রায়ই ডিফল্টbfq
Budget Fair Queueing: প্রতিটি প্রসেসকে ডিস্ক-সময়ের ন্যায্য ভাগ দেয়, interactive কাজকে অগ্রাধিকার — বড় কপি চলার সময়ও ডেস্কটপ সাড়া দেয়। CPU খরচ বেশি।
ডেস্কটপ, ধীর ডিস্কkyber
হালকা, token-ভিত্তিক: পড়া আর synchronous লেখার জন্য একটি লক্ষ্য latency রাখে, আর ডিভাইসে কতগুলো অনুরোধ একসাথে যাবে তা মানিয়ে নেয়। দ্রুত ডিভাইসের জন্য নকশা।
দ্রুত SSDBFQ (Paolo Valente ও সহকর্মীরা) আর Kyber (Facebook-এর Omar Sandoval) দুটিই Linux 4.12-এ (২০১৭) kernel-এ আসে। কোন ডিভাইসে কোনটি ডিফল্ট, তা kernel version আর distro-র udev নিয়মের ওপর নির্ভর করে — নিজের মেশিনে দেখে নিন। নিচের bash প্রোগ্রাম ডিস্কগুলোর তালিকা, ঘোরা ডিস্ক কি না (ROTA = 1 মানে HDD), আর বর্তমান scheduler দেখায়। Container-এ চালালে ডিস্কের তথ্য লুকানো থাকতে পারে — প্রোগ্রাম সেটিও সামলায়।
echo "== lsblk =="
if command -v lsblk >/dev/null 2>&1; then
lsblk -o NAME,ROTA,SIZE,SCHED 2>/dev/null | head -n 12 || echo "lsblk: no output here"
else
echo "lsblk not installed"
fi
echo "== /sys/block =="
found=0
for d in /sys/block/*; do
[ -e "$d" ] || continue
found=1
n=$(basename "$d")
rot=$(cat "$d/queue/rotational" 2>/dev/null || echo "?")
sch=$(cat "$d/queue/scheduler" 2>/dev/null || echo "?")
echo "$n rotational=$rot scheduler=$sch"
done | head -n 12
[ -d /sys/block ] && [ -n "$(ls /sys/block 2>/dev/null)" ] || echo "/sys/block is empty or hidden here"একটি আসল রানের আউটপুট (container ও সময়ভেদে আলাদা হতে পারে):
== lsblk ==
== /sys/block ==
loop0 rotational=1 scheduler=[none] mq-deadline
loop1 rotational=1 scheduler=[none] mq-deadline
loop2 rotational=1 scheduler=[none] mq-deadline
loop3 rotational=1 scheduler=[none] mq-deadline
loop4 rotational=1 scheduler=[none] mq-deadline
loop5 rotational=1 scheduler=[none] mq-deadline
loop6 rotational=1 scheduler=[none] mq-deadline
loop7 rotational=1 scheduler=[none] mq-deadline
loop8 rotational=1 scheduler=[none] mq-deadline
loop9 rotational=1 scheduler=[none] mq-deadline
sr0 rotational=1 scheduler=none [mq-deadline]
vda rotational=1 scheduler=[none] mq-deadline
এই container-এ lsblk কিছুই ছাপেনি — ডিভাইসের তালিকা তার কাছে লুকানো; তাই একই তথ্য সরাসরি /sys/block থেকে পড়া হয়েছে। loop0–loop9 হলো loop device, sr0 একটি CD/DVD ড্রাইভ, আর vda হলো virtual machine-এর virtio ডিস্ক। প্রতিটি লাইনে বন্ধনীর ভেতরের নামটি চলমান scheduler: বেশিরভাগে [none], sr0-তে [mq-deadline]. খেয়াল করুন, vda নিজেকে rotational=1 বলছে — virtual ডিস্ক প্রায়ই এমন দেখায়, কারণ নিচে আসলে HDD, SSD না নেটওয়ার্ক storage, তা guest OS জানে না।
নিজের Linux মেশিনে (container নয়) সাধারণত এমন কিছু দেখবেন — নমুনা, আপনার মেশিনে নাম ও সংখ্যা আলাদা হবে:
$ lsblk -o NAME,ROTA,SIZE,SCHED
NAME ROTA SIZE SCHED
sda 1 1.8T mq-deadline
nvme0n1 0 476.9G none
$ cat /sys/block/sda/queue/scheduler
[mq-deadline] kyber bfq none
$ echo bfq | sudo tee /sys/block/sda/queue/scheduler # reboot হলে আগের অবস্থায় ফেরে
bfqবন্ধনীর ভেতরেরটি এখন চলছে। স্থায়ীভাবে বদলাতে udev নিয়ম লাগে (অনুশীলন ৪)। Windows আর macOS-এ Linux-এর মতো ব্যবহারকারীর বাছাই করার scheduler-তালিকা নেই; সেখানে অনুরোধ সাজানো মূলত storage driver স্তর আর ডিস্কের firmware-এর কাজ, আর OS I/O priority-র মতো সুবিধা দেয়।
NVMe-তে কেন “none”
SSD-তে কোনো arm নেই — LBA 5 আর LBA 5,000,000 পড়ার খরচ প্রায় সমান, তাই “কাছের অনুরোধ আগে” কথাটির মানেই নেই। তার ওপর NVMe ডিভাইসে অনেকগুলো hardware queue থাকে, আর Linux সাধারণত প্রতিটি CPU core-কে নিজের queue দেয় — core-গুলো lock ছাড়াই সমান্তরালে অনুরোধ পাঠায়। Scheduler বসালে প্রতিটি অনুরোধে বাড়তি CPU খরচ আর lock-এর প্রতিযোগিতা যোগ হয়, যা কয়েক দশ µs-এর ডিভাইসে চোখে পড়ে। তাই ডিফল্ট none; তবে একই NVMe-তে কয়েকটি কাজের মধ্যে ন্যায্যতা বা latency-লক্ষ্য দরকার হলে kyber বা mq-deadline, আর cgroup-এর I/O নিয়ন্ত্রণ কাজে লাগে।
আরও গভীরে: “head movement” আসলে seek time-এর একটি সরল প্রতিনিধি। বাস্তবে seek time দূরত্বের সাথে সরলরেখায় বাড়ে না: ছোট seek-এ arm-এর ত্বরণ আর থিতু হওয়াই প্রধান, তাই সময় মোটামুটি দূরত্বের বর্গমূলের মতো বাড়ে, আর লম্বা seek-এ প্রায় সরলরৈখিক। তাই ডিস্কের firmware “shortest positioning time first” (SPTF বা SATF) ধরনের নীতি চালায় — seek আর ঘোরা মিলিয়ে কোন অনুরোধে সবচেয়ে কম সময় লাগবে, তা হিসাব করে। এমন নীতি OS চালাতে পারে না, কারণ platter-এর বর্তমান কোণ শুধু ডিস্ক জানে।
৬ · SSD-র ভেতরে — NAND flash, FTL আর garbage collection
একটি SSD-তে কোনো ঘোরা অংশ নেই। ডেটা থাকে NAND flash চিপে — কোটি কোটি ছোট cell, প্রতিটি একটি বিশেষ transistor, যার ভেতরে আটকে রাখা বৈদ্যুতিক চার্জের পরিমাণই ডেটা। বিদ্যুৎ চলে গেলেও চার্জ থেকে যায়, তাই ডেটা হারায় না।
প্রতি cell-এ কত বিট — SLC থেকে QLC
একটি cell-এ চার্জের কয়টি স্তর আলাদা করে চেনা যায়, তার ওপর নির্ভর করে সে কত বিট রাখে। বেশি বিট মানে একই চিপে বেশি ধারণক্ষমতা আর কম দাম — কিন্তু স্তরগুলো কাছাকাছি হয়ে যায়, তাই পড়া-লেখা ধীর, ভুল বেশি, আর cell কম বার লেখা সহ্য করে।
| ধরন | বিট / cell | চার্জের স্তর | সহ্যক্ষমতা (মোটামুটি মাত্রা, পণ্যভেদে আলাদা) |
|---|---|---|---|
| SLC | ১ | ২ | সবচেয়ে বেশি — কয়েক দশ হাজার P/E cycle বা তারও বেশি |
| MLC | ২ | ৪ | কয়েক হাজার |
| TLC | ৩ | ৮ | প্রায় এক থেকে কয়েক হাজার; আজকের বেশিরভাগ ভোক্তা-SSD |
| QLC | ৪ | ১৬ | কয়েকশো থেকে প্রায় এক হাজারের কাছাকাছি; সস্তা, বড়, পড়া-প্রধান কাজে |
এখানে P/E cycle মানে একবার লেখা (program) আর একবার মোছা (erase). প্রতিটি cycle cell-এর অন্তরক স্তরকে একটু ক্ষয় করে; একসময় cell আর নির্ভরযোগ্যভাবে চার্জ ধরে রাখতে পারে না।
তিনটি নিয়ম, যা সব বদলে দেয়
- পড়া আর লেখা হয় page ধরে — একটি page সাধারণত কয়েক KiB থেকে ১৬ KiB.
- মোছা হয় শুধু erase block ধরে — একটি block-এ শত শত page, আকার কয়েক MiB পর্যন্ত। মোছা ধীর (ms-মাত্রার), পড়া মাইক্রোসেকেন্ড-মাত্রার।
- একটি page আবার লেখার আগে তার পুরো block মুছতে হয়। অর্থাৎ জায়গায় বসে overwrite হয় না।
ভাবুন, OS বলল “LBA 1 বদলে নতুন ডেটা লেখো।” HDD হলে head সেই sector-এ গিয়ে লিখে দেয়। SSD-তে LBA 1 যে page-এ আছে, সেটি সরাসরি আবার লেখা যায় না; পুরো block মুছতে হলে সেই block-এর বাকি শত page-এর ডেটা আগে সরাতে হবে — একটি 4 KiB লেখার জন্য কয়েক MiB নড়াচড়া! সমাধান: নতুন ডেটা অন্য একটি ফাঁকা page-এ লেখা, আর পুরোনো page-কে “বাতিল” (invalid) চিহ্ন দেওয়া। কিন্তু তাহলে LBA 1 এখন কোথায়, সেই হিসাব কেউ রাখতে হবে।
Flash Translation Layer — SSD-র নিজের “page table”
সেই হিসাব রাখে FTL (flash translation layer) — SSD-র controller-এ চলা firmware. এটি প্রতিটি LBA-র জন্য লিখে রাখে, ডেটা এখন কোন physical page-এ। পর্ব ৩২-এর page table-এর সাথে মিলটি লক্ষ করুন: সেখানে virtual page → physical frame, এখানে LBA → flash page. OS ভাবে সে একটি সাধারণ ব্লক-ডিভাইসে নির্দিষ্ট ঠিকানায় লিখছে; ভেতরে প্রতিটি লেখা নতুন জায়গায় যায়।
নতুন জায়গায় লিখতে লিখতে একসময় ফাঁকা page ফুরোয়, আর অনেক block-এ জমে বাতিল page. তখন চলে garbage collection (GC): একটি block বাছা (সাধারণত যেটিতে সবচেয়ে কম valid page), তার valid page-গুলো অন্য ফাঁকা জায়গায় কপি করা, তারপর পুরো block মুছে ফাঁকা তালিকায় ফেরত দেওয়া। কপি করা page-গুলো হলো বাড়তি লেখা — host চায়নি, তবু NAND-এ লেখা হলো। এটিই write amplification.
একটি অফিসের রেজিস্টার খাতার কথা ভাবুন, যেখানে কালিতে লেখা হয় আর কাটাকুটি নিষেধ। কোনো এন্ট্রি বদলাতে হলে পুরোনোটিতে “বাতিল” দাগ দিয়ে খাতার পরের ফাঁকা লাইনে নতুনটি লেখা হয়, আর সামনের সূচিপত্রে লেখা থাকে কোন এন্ট্রি এখন কোন পাতায় (FTL). খাতা ভরে এলে একজন কেরানি একটি পুরোনো পাতা বাছেন যেখানে বেশিরভাগই বাতিল, তার অল্প কয়টি বৈধ এন্ট্রি নতুন পাতায় তুলে নেন, তারপর পুরোনো পাতাটি ছিঁড়ে নতুন সাদা পাতা লাগান (erase). বৈধ এন্ট্রি তুলে নেওয়ার পরিশ্রমটাই বাড়তি খরচ।
নিচের stepper একটি খেলনা SSD দেখায়: ৩টি erase block (A, B, C), প্রতিটিতে ৪টি page. ঘরে সংখ্যা মানে সেই LBA-র বৈধ ডেটা, x মানে বাতিল page, . মানে ফাঁকা। FTL একটি block সবসময় GC-র জন্য খালি রাখে (বাস্তব SSD-ও এমন সংরক্ষিত জায়গা রাখে)।
| Block A | |
| Block B | |
| Block C | |
| host / NAND লেখা |
- নতুন SSD. তিনটি block-ই ফাঁকা, FTL map খালি। host লিখেছে ০, NAND-এ লেখা হয়েছে ০।
- LBA 0–3 লেখা। চারটিই block A-তে পরপর বসল; map-এ 0→A0 … 3→A3. host ৪, NAND ৪।
- LBA 1 আবার লেখা (overwrite). A1-এ বসে লেখা যায় না। নতুন ডেটা গেল B0-তে, map-এ 1→B0, আর A1 এখন বাতিল (x). host ৫, NAND ৫।
- LBA 2 আবার লেখা। একইভাবে B1-এ, A2 বাতিল। Block A-তে এখন ২টি বৈধ (0, 3) আর ২টি বাতিল page. host ৬, NAND ৬।
- LBA 4, 5 লেখা। B2, B3-এ বসল; B ভরে গেল। ফাঁকা আছে শুধু C — যা GC-র জন্য সংরক্ষিত। পরের লেখার আগে জায়গা বানাতে হবে। host ৮, NAND ৮।
- Garbage collection: কপি। সবচেয়ে কম বৈধ page-এর ভরা block হলো A (২টি)। FTL তার বৈধ LBA 0 আর 3 কপি করল C0 আর C1-এ, map হালনাগাদ করল। এই দুটি লেখা host চায়নি — host এখনো ৮, NAND ১০।
- Block A মোছা। A-তে এখন সব বাতিল, তাই পুরো block একবারে erase — A আবার ফাঁকা (এবং এখন সেটিই সংরক্ষিত block). A-র P/E গণনায় একটি cycle যোগ হলো।
- LBA 6, 7 লেখা। C2, C3-এ বসল। মোট host লেখা ১০, NAND লেখা ১২ — write amplification = ১২ ÷ ১০ = ১.২০.
Write amplification-এর সূত্র
WA = ১ মানে কোনো বাড়তি লেখা নেই; WA = ৩ মানে host-এর প্রতি ১ GB লেখায় flash-এ ৩ GB লেখা হচ্ছে, অর্থাৎ SSD-র আয়ু তিন গুণ দ্রুত খরচ হচ্ছে, আর GC-র কাজে host-এর লেখাও ধীর হচ্ছে।
একটি সরল মডেল: ধরুন প্রতিবার GC যে block বাছে, তার page-গুলোর u অংশ বৈধ (০ ≤ u < ১)। P page-এর block থেকে u·P page কপি করলে (P − u·P) page নতুন লেখার জন্য ফাঁকা হয়। অর্থাৎ (১ − u)·P page host-লেখার জন্য NAND-এ মোট P page লিখতে হয়:
উদাহরণ: ৬৪ page-এর একটি block-এ GC-র সময় ১৬টি বৈধ (u = ০.২৫)। ১৬টি কপি করে ৪৮টি ফাঁকা পাওয়া গেল, তাতে ৪৮টি host-লেখা — মোট NAND লেখা ৪৮ + ১৬ = ৬৪. WA = ৬৪ ÷ ৪৮ = ১ ÷ (১ − ০.২৫) ≈ ১.৩৩. Victim যদি ৭৫% বৈধ হয়, WA = ৪; ৯০% হলে ১০. Drive প্রায় ভরা থাকলে GC ভালো victim পায় না — WA লাফিয়ে বাড়ে। (বাস্তব FTL আরও জটিল; এটি শুধু প্রবণতা বোঝার মডেল।)
নিচের প্রোগ্রাম stepper-এর খেলনা SSD-টিই চালায় — page-level FTL আর “সবচেয়ে কম বৈধ page” নীতির GC — আর শেষে সূত্রের কয়েকটি মান ছাপে।
// Toy SSD: 3 erase blocks x 4 pages, page-level FTL, greedy garbage collection.
const PAGES = 4, nand = [[], [], []]; // each block: list of {lba, valid}
const map = {}; // FTL map: LBA -> [block, page]
let host = 0, flash = 0, active = 0;
const free = () => nand.filter(b => b.length === 0).length;
function program(lba) { // NAND pages are written once: append only
if (nand[active].length === PAGES) active = nand.findIndex(b => b.length === 0);
if (map[lba]) { const [b, p] = map[lba]; nand[b][p].valid = false; } // old copy dies
nand[active].push({ lba, valid: true });
map[lba] = [active, nand[active].length - 1]; flash++;
}
function gc() { // victim = full block with fewest valid pages
let v = -1;
nand.forEach((b, i) => { if (b.length === PAGES && i !== active &&
(v < 0 || b.filter(x => x.valid).length < nand[v].filter(x => x.valid).length)) v = i; });
const live = nand[v].filter(x => x.valid).map(x => x.lba);
active = nand.findIndex(b => b.length === 0); // the reserved free block
for (const lba of live) program(lba); // copy valid pages: extra NAND writes
nand[v] = []; // erase the whole block
console.log(" GC: block " + "ABC"[v] + " had " + live.length + " valid pages (LBA " +
live.join(",") + ") -> copied, block erased");
}
function write(lba) { // keep one free block in reserve for GC
host++;
if (nand[active].length === PAGES && free() <= 1) gc();
program(lba);
}
const show = (t) => console.log(t.padEnd(22) + nand.map((b, i) => "ABC"[i] + "[" +
[0, 1, 2, 3].map(p => b[p] ? (b[p].valid ? b[p].lba : "x") : ".").join(" ") + "]").join(" ") +
" host=" + host + " nand=" + flash);
for (const l of [0, 1, 2, 3]) write(l); show("write LBA 0-3");
for (const l of [1, 2]) write(l); show("overwrite LBA 1,2");
for (const l of [4, 5]) write(l); show("write LBA 4,5");
for (const l of [6, 7]) write(l); show("write LBA 6,7");
console.log("WA = NAND writes / host writes = " + flash + "/" + host + " = " + (flash / host).toFixed(2));
for (const u of [0.25, 0.5, 0.75, 0.9]) console.log("victim " + u * 100 + "% valid -> WA = 1/(1-u) = " + (1 / (1 - u)).toFixed(2));আউটপুট (নির্ধারিত, প্রতিবার একই):
write LBA 0-3 A[0 1 2 3] B[. . . .] C[. . . .] host=4 nand=4
overwrite LBA 1,2 A[0 x x 3] B[1 2 . .] C[. . . .] host=6 nand=6
write LBA 4,5 A[0 x x 3] B[1 2 4 5] C[. . . .] host=8 nand=8
GC: block A had 2 valid pages (LBA 0,3) -> copied, block erased
write LBA 6,7 A[. . . .] B[1 2 4 5] C[0 3 6 7] host=10 nand=12
WA = NAND writes / host writes = 12/10 = 1.20
victim 25% valid -> WA = 1/(1-u) = 1.33
victim 50% valid -> WA = 1/(1-u) = 2.00
victim 75% valid -> WA = 1/(1-u) = 4.00
victim 90% valid -> WA = 1/(1-u) = 10.00
প্রতিটি লাইন stepper-এর একটি ধাপের সাথে মেলে: overwrite-এর পর A-তে দুটি x, LBA 6 লেখার আগে GC A-র দুটি বৈধ page (0, 3) C-তে কপি করে A মুছে দেয়, আর শেষে host ১০, NAND ১২ — WA ১.২০. program()-এ দুটি লাইনই FTL-এর সারকথা: পুরোনো কপিকে valid = false করা (overwrite নয়), আর নতুন জায়গার ঠিকানা map-এ লেখা। gc() GC-র সময় নিজেও program() ডাকে — তাই flash বাড়ে, host বাড়ে না। শেষ চার লাইন সূত্রের মান: ২৫% বৈধ হলে ১.৩৩, ৯০% হলে ১০.
Wear leveling, TRIM আর over-provisioning
- Wear leveling: কিছু LBA বারবার লেখা হয় (log, metadata), কিছু বছরের পর বছর বদলায় না (সিনেমা, OS-এর ফাইল)। FTL লেখাগুলো সব block-এ ছড়িয়ে দেয়, আর মাঝে মাঝে “ঠান্ডা” ডেটাকেও বেশি-ক্ষয় হওয়া block থেকে সরিয়ে কম-ক্ষয় হওয়া block-এ রাখে (static wear leveling), যাতে সব block মোটামুটি সমানভাবে বুড়ো হয়। এর দামও বাড়তি লেখা।
- TRIM / discard: আপনি একটি ফাইল মুছলে file system শুধু নিজের হিসাবে block-গুলো “ফাঁকা” লেখে; SSD জানে না। FTL-এর চোখে সেই page-গুলো এখনো বৈধ — GC সেগুলো বারবার কপি করবে! TRIM হলো OS-এর পক্ষ থেকে SSD-কে জানানো “এই LBA-গুলোর ডেটা আর লাগবে না।” ATA-তে TRIM, SCSI-তে UNMAP, NVMe-তে Deallocate নামে। Linux-এ
fstrim(অনেক distro-তে সাপ্তাহিকfstrim.timer) বা mount-এরdiscardবিকল্প; Windows-এ “Optimize Drives” TRIM পাঠায়, আরfsutil behavior query DisableDeleteNotify-এর ফল 0 মানে TRIM চালু। - Over-provisioning: SSD-তে বিক্রির ধারণক্ষমতার চেয়ে বেশি flash থাকে — বাড়তি অংশ ব্যবহারকারী দেখেন না, FTL GC আর খারাপ block বদলানোর জন্য রাখে। যত বেশি ফাঁকা জায়গা, GC তত বেশি বাতিল-ভরা victim পায় (u কম), WA তত কম। Enterprise SSD প্রায়ই বেশি over-provisioning রাখে; ভোক্তা হিসেবে আপনিও ড্রাইভ পুরো ভরে না রেখে একই সুবিধা পান।
৭ · NVMe আর গতির মাত্রা — HDD, SATA SSD, NVMe
প্রথম দিকের SSD-গুলো SATA সংযোগে বসানো হতো — যে interface ঘোরা ডিস্কের জন্য বানানো। SATA-র AHCI নিয়মে একটি মাত্র command queue, তাতে সর্বোচ্চ ৩২টি অনুরোধ; আর SATA III-এর তারের গতি ৬ Gb/s, বাস্তবে প্রায় ৫৫০ MB/s-এর কাছাকাছিতে আটকে যায়।
২০১১ সালে NVMe (Non-Volatile Memory Express) স্পেসিফিকেশনের প্রথম সংস্করণ আসে, সরাসরি PCIe-র ওপর flash-এর জন্য নকশা করা। এর কেন্দ্রে জোড়া queue: একটি submission queue, যেখানে host অনুরোধ রাখে, আর একটি completion queue, যেখানে ডিভাইস ফল জানায় — দুটিই RAM-এ রাখা ring, ঠিক পর্ব ৫-এ দেখা io_uring-এর ধাঁচে। স্পেসিফিকেশন অনুযায়ী সর্বোচ্চ প্রায় ৬৪ হাজার I/O queue, প্রতিটিতে প্রায় ৬৪ হাজার অনুরোধ রাখা যায়; বাস্তব ডিভাইস এর অনেক কম queue দেয়, আর Linux সাধারণত প্রতিটি CPU core-কে একটি করে দেয়। কোনো core-কে অন্য core-এর সাথে lock ভাগ করতে হয় না।
নিচের টেবিল মাত্রা বোঝানোর জন্য — নির্দিষ্ট মডেল, queue depth আর workload অনুযায়ী আসল সংখ্যা অনেক বদলায়।
| মাপ | HDD (7200 RPM) | SATA SSD | NVMe SSD |
|---|---|---|---|
| একটি এলোমেলো 4 KiB পড়ার latency | কয়েক ms থেকে ১০+ ms | কয়েক দশ থেকে ~১০০ µs | প্রায় ১০ থেকে কয়েক দশ µs |
| এলোমেলো পড়া, IOPS | কয়েকশো পর্যন্ত (প্রায়ই ১০০–২০০) | কয়েক দশ হাজার | কয়েক লাখ থেকে দশ লাখ ছাড়িয়ে |
| ক্রমানুসারে পড়া | ~১০০–২৫০ MB/s | ~৫০০–৫৫০ MB/s (SATA-র সীমা) | কয়েক GB/s (PCIe প্রজন্মভেদে) |
| Command queue | ১টি, NCQ-তে ৩২ | ১টি, ৩২ | অনেকগুলো, প্রতিটি গভীর |
| Disk scheduling-এর গুরুত্ব | খুব বেশি | কম | প্রায় নেই (সাধারণত none) |
HDD থেকে NVMe-তে latency কমেছে প্রায় হাজার গুণ — এখন OS-এর নিজের সফটওয়্যার-পথই মোট সময়ের লক্ষণীয় অংশ (ভাবনার প্রশ্ন ০৪)।
৮ · ডিস্ক প্রস্তুত করা — formatting, partition, boot block, bad block আর সংযোগ
তিন স্তরের formatting
- Low-level (physical) formatting: platter-এ track আর sector-এর কাঠামো, প্রতিটি sector-এর header আর ECC-র জায়গা বসানো। আধুনিক ডিস্কে এটি কারখানাতেই হয়ে আসে; ব্যবহারকারী আর করেন না।
- Partitioning: ডিস্ককে এক বা একাধিক partition-এ ভাগ করা — হিসাব থাকে MBR বা GPT partition table-এ। প্রতিটি partition OS-এর কাছে আলাদা ডিস্কের মতো।
- Logical formatting: একটি partition-এ file system তৈরি করা — superblock, free-space-এর হিসাব, প্রথম directory (Linux-এ
mkfs.ext4, Windows-এ Format). এর ভেতরের কাঠামো আসবে পর্ব ৪৩-এ। কিছু database file system ছাড়াই সরাসরি partition (raw disk) ব্যবহার করতে পারে।
Boot block
কম্পিউটার চালু হলে firmware-কে জানতে হয় কোথা থেকে OS শুরু করবে। BIOS-এর যুগে ডিস্কের প্রথম sector — boot sector, LBA 0-এর MBR — একটি ছোট boot code রাখত, যা পরের ধাপের bootloader আনত। UEFI-তে বুটের ফাইল থাকে একটি আলাদা FAT partition-এ (ESP). বিস্তারিত পর্ব ৭ · বুট প্রক্রিয়া-য়।
Bad block — খারাপ জায়গা লুকানো
কোনো চৌম্বক স্তর নিখুঁত নয়; কারখানাতেই কিছু খারাপ sector থাকে, ব্যবহারের সময় আরও তৈরি হয়। আধুনিক ডিস্ক নিজেই সামলায়: কারখানায় কিছু অতিরিক্ত (spare) sector রেখে দেওয়া হয়। কোনো sector খারাপ হলে controller তার LBA-কে একটি spare sector-এ পাঠিয়ে দেয় — sector sparing (forwarding). এতে একটি অসুবিধা: OS-এর scheduler যে LBA-কে পাশাপাশি ভাবছে, তার একটি আসলে অন্য cylinder-এ — তাই অনেক ডিস্ক প্রতিটি cylinder-এ কিছু spare রাখে। আরেক কৌশল sector slipping: খারাপ sector-এর পরের সব sector এক ঘর সরিয়ে দেওয়া, যাতে ক্রম অটুট থাকে। SSD-তে একই কাজ FTL করে — খারাপ block বাদ দিয়ে over-provisioning-এর block বসায়।
Reallocated sector-এর সংখ্যা ডিস্কের S.M.A.R.T. তথ্যে দেখা যায় (Linux-এ smartctl -a /dev/sda, root লাগে)। এই সংখ্যা বাড়তে থাকা ডিস্ক বদলানোর একটি সতর্কসংকেত — ব্যাকআপ আগে নিশ্চিত করুন।
ডিস্ক কোথায় লাগানো — DAS, NAS, SAN আর ক্লাউড
DAS
Direct-attached storage: ডিস্ক সরাসরি কম্পিউটারে — SATA, SAS, NVMe বা USB. OS একটি block device দেখে। ল্যাপটপের ভেতরের SSD এটিই।
block স্তরে, একটি hostNAS
Network-attached storage: নেটওয়ার্কে একটি file server, NFS বা SMB দিয়ে ফাইল দেয়। অফিসের শেয়ার্ড ফোল্ডার।
ফাইল স্তরে, অনেক hostSAN
Storage area network: আলাদা storage নেটওয়ার্ক (Fibre Channel বা iSCSI), যা সার্ভারকে নেটওয়ার্কের ওপারের block device দেয় — সার্ভার ভাবে ডিস্কটি তারই।
block স্তরে, নেটওয়ার্কেক্লাউড block storage
Cloud block storage: AWS EBS, Azure Managed Disk, Google Persistent Disk — VM-এর কাছে সাধারণ ডিস্ক, কিন্তু আসলে নেটওয়ার্কের ওপারে কপি রাখা storage; IOPS আর throughput প্রায়ই প্ল্যান অনুযায়ী সীমিত।
block স্তরে, ভাড়ায়চাবি: NAS ফাইল দেয়, তাই file system চলে সার্ভারে; SAN আর ক্লাউড block storage ব্লক দেয়, তাই file system চলে আপনার মেশিনে। একাধিক ডিস্ক মিলিয়ে নির্ভরযোগ্যতা — RAID — পর্ব ৪৫-এ।
৯ · AI-এর যুগে ডিস্ক আর SSD
Disk scheduling-এর অঙ্ক আর storage-এর পরামর্শ — দুটিতেই AI দ্রুত উত্তর দেয়, আর দুটিতেই নিয়মিত ভুল করে:
| AI-এর ভুল | কেন ভুল | কীভাবে যাচাই করবেন |
|---|---|---|
| C-SCAN-এ ফেরার লাফ নিঃশব্দে যোগ বা বাদ; দিক না বলেই SCAN-এর উত্তর | একই প্রশ্নের একাধিক সঠিক উত্তর আছে নিয়মভেদে | নিয়ম আগে লিখে দিন; simulator-এর টেবিলে চারটি কলাম মিলিয়ে দেখুন |
| লম্বা trace-এ যোগফলে ছোট ভুল (৬৪০-এর জায়গায় ৬৩০) | ভাষা-মডেল ধাপে ধাপে হিসাব রাখে না | প্রতিটি ধাপের দূরত্ব আলাদা করে লিখিয়ে নিজে যোগ করুন |
| “SCAN সবসময় সর্বোত্তম” বা “SSTF সর্বোত্তম” | দুটিই নয়; এই queue-তে সর্বনিম্ন ২০৮ (LOOK নিচের দিকে) | অংশ ৩-এর সর্বনিম্ন-সীমার যুক্তি |
| Rotational latency = পুরো এক পাক | গড় অর্ধেক পাক; পূর্ণ পাক হলো সবচেয়ে খারাপ | 60 ÷ RPM ÷ 2 হাতে হিসাব |
NVMe-তে “bfq দিন, দ্রুত হবে” বা elevator= boot প্যারামিটার | NVMe-তে সাধারণত none ভালো; blk-mq-র পর পুরোনো elevator প্যারামিটার কাজ করে না | cat /sys/block/*/queue/scheduler দেখুন; fio দিয়ে আগে-পরে মাপুন |
| “SSD-তে ফাইল overwrite করলেই নিরাপদে মুছে যায়” | FTL নতুন জায়গায় লেখে, পুরোনো page থেকে যেতে পারে | নির্মাতার secure erase / sanitize ডকুমেন্টেশন দেখুন |
সন্দেহজনক ডিস্কে প্রথমেই sudo fsck -y বা dd চালানোর পরামর্শ | মরতে থাকা ডিস্কে বাড়তি লেখা ক্ষতি বাড়াতে পারে; dd-এ ভুল ডিভাইস নাম মানে পুরো ডেটা মুছে যাওয়া | আগে ব্যাকআপ/ইমেজ, lsblk দিয়ে ডিভাইস নাম দুবার মেলান, SMART দেখুন |
অঙ্কে নিয়ম স্পষ্ট লিখে দিন, আর যাচাইযোগ্য ধাপ চান:
AI-এর উত্তর মানার আগে — চেকলিস্ট
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- Access time-এর তিনটি অংশ কী, আর কোনটি সবচেয়ে বড়? — seek + rotational latency + transfer; এলোমেলো ছোট I/O-তে seek আর latency প্রায় পুরোটা, transfer নগণ্য।
- 7200 RPM-এ গড় rotational latency? — ½ × ৬০,০০০ ÷ ৭২০০ ≈ ৪.১৭ ms.
- SSTF-এর সমস্যা কী? — starvation (দূরের অনুরোধ অনির্দিষ্টকাল অপেক্ষা করতে পারে), আর এটি সর্বোত্তমও নয়।
- SCAN আর C-SCAN-এর পার্থক্য? — SCAN দুই দিকেই সেবা দেয়; C-SCAN এক দিকে সেবা দিয়ে লাফিয়ে শুরুতে ফেরে, তাই অপেক্ষার সময় বেশি সমান।
- SSD-তে write amplification কেন হয়, কীভাবে কমে? — overwrite নেই, GC বৈধ page কপি করে; TRIM, over-provisioning আর ড্রাইভ পুরো না ভরানো WA কমায়।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১SSD এত দ্রুত, তবু ঘোরা হার্ড ডিস্ক কেন আজও ডেটা সেন্টারে বিপুল সংখ্যায় কেনা হয়?
উত্তরটি এক শব্দে — দাম, তবে তার পেছনে প্রকৌশলের একটি গল্প আছে। ১৯৫৬ সালের IBM 350-এর ৫০টি ২৪-ইঞ্চি platter-এ ধরত মোটামুটি ৩.৭৫ MB. তারপর প্রায় সাত দশকে ঘোরা ডিস্কের ধারণক্ষমতা বেড়েছে কল্পনাতীত হারে — head ছোট হয়েছে, বিট আরও ঘন হয়েছে, track-গুলো আরও কাছাকাছি এসেছে। কিন্তু অংশ ২-এর অঙ্কটি মনে করুন: seek আর ঘোরা যান্ত্রিক, তাই এলোমেলো I/O-র গতি এই সময়ে বেড়েছে খুব সামান্য — 7200 RPM ডিস্ক আজও সেকেন্ডে কয়েকশো এলোমেলো পড়ার বেশি দিতে পারে না।
ফলে HDD-র প্রতি TB-এর দাম এখনো সাধারণত SSD-র চেয়ে কম, যদিও ব্যবধান সময়ের সাথে কমছে। যে ডেটা লেখা হয় একবার, পড়া হয় কালেভদ্রে — ব্যাকআপ, পুরোনো ছবি-ভিডিও, log-এর সংরক্ষণাগার, বৈজ্ঞানিক ডেটা — সেখানে এলোমেলো গতির দরকার নেই, ক্রমানুসারে লেখা-পড়াই যথেষ্ট, যেখানে HDD ভালোই চলে। তাই বড় ক্লাউড-প্রতিষ্ঠানগুলোর “ঠান্ডা” (cold) storage-স্তরের বড় অংশ প্রকাশ্য তথ্যমতে এখনো ঘোরা ডিস্কে, আর তার ওপরে একটি দ্রুত flash-স্তর গরম ডেটা রাখে — পর্ব ৪-এর memory hierarchy-র আরেকটি রূপ।
ঘনত্ব বাড়ানোর কৌশলের দামও আছে। Shingled magnetic recording (SMR)-এ track-গুলো ছাদের টালির মতো একটির ওপর আরেকটি আংশিক চাপানো, ফলে একটি track লিখলে পাশেরটি নষ্ট হয় — SSD-র erase block-এর মতোই “জায়গায় বসে overwrite নেই”, আর ডিস্কের ভেতরে একটি translation layer লাগে। ২০২০ সালে একটি বড় নির্মাতার কিছু NAS-ডিস্কে ঘোষণা ছাড়াই drive-managed SMR ব্যবহারের খবর সামনে আসে; RAID পুনর্গঠনের সময় সেগুলো খুব ধীর হয়ে যাওয়ার অভিযোগ ওঠে — ব্যবহারকারীরা শিখলেন, ডিস্কের ভেতরের প্রযুক্তি জানা জরুরি।
মূল উপলব্ধি: storage বাছাই একটি মাপজোখ — প্রতি TB-এর দাম, IOPS আর latency; ডেটা কতটা “গরম”, তা দেখে স্তর ঠিক করাই আসল নকশা, “সবচেয়ে দ্রুত” বাছা নয়।
প্র ০২ডিস্ক নিজেই NCQ দিয়ে সাজায়, SSD-তে seek-ই নেই — তাহলে SCAN, C-SCAN শেখার মূল্য কী?
প্রশ্নটি ন্যায্য, আর Linux-এর ইতিহাসই আংশিক উত্তর দেয়। দীর্ঘদিন Linux-এ I/O scheduler-কে বলা হতো “elevator”, আর পুরোনো kernel-এ boot-এর সময় elevator= প্যারামিটার দিয়ে বাছা যেত। CFQ (Completely Fair Queuing) বহু বছর অনেক distro-র ডিফল্ট ছিল। Linux 5.0 (২০১৯)-এ পুরোনো single-queue block layer সরানোর সাথে CFQ-ও বিদায় নেয়; জায়গা নেয় blk-mq-র mq-deadline, bfq, kyber আর none. অর্থাৎ নির্দিষ্ট algorithm বদলেছে, কিন্তু প্রশ্নগুলো বদলায়নি — কাকে আগে, কতক্ষণ কেউ অপেক্ষা করবে, ন্যায্যতা কীভাবে।
mq-deadline-এর ভেতরে তাকালেই দেখবেন: অনুরোধগুলো sector অনুযায়ী সাজানো একটি তালিকায় রাখা হয় আর এক দিকে চলতে চলতে পাঠানো হয় — SCAN/LOOK-এর ধারণা। পাশাপাশি প্রতিটির সময়সীমা দেখা হয় — SSTF-এর starvation-এর প্রতিকার, যা এই পর্বে দেখেছেন। BFQ-র “budget” আসলে CPU scheduling-এর ন্যায্য ভাগের ধারণা ডিস্কে আনা (পর্ব ১৮–২১)। আর NCQ-র ভেতরে ডিস্কের firmware যা করে, তা SSTF-এরই সম্প্রসারিত রূপ — seek-এর সাথে ঘোরাও হিসাব করে, আর starvation ঠেকাতে পুরোনো অনুরোধকে একসময় জোর করে সেবা দেয়।
দ্বিতীয় মূল্য: এই algorithm-গুলো একটি সাধারণ প্রশ্নের নমুনা — একটি এক-মাত্রিক জায়গায় একটি যন্ত্র চলাচল করে, আর অনুরোধ আসতে থাকে। লিফট নিয়ন্ত্রণ, গুদামে রোবটের পথ, ব্যাংকের টেপ-লাইব্রেরি, এমনকি একটি ছাপাখানার কাগজ-ফিডার — সবখানে “লোভী বনাম ঝাড়ু-চলাচল”-এর একই আপস। আর তৃতীয়ত, পরীক্ষায় এগুলো আসবেই — সংখ্যা-হিসাবের নির্ভুলতা আর নিয়ম স্পষ্ট লেখার অভ্যাস এখান থেকেই তৈরি হয়।
মূল উপলব্ধি: বাস্তব scheduler-এর নাম বদলায়, কিন্তু তার ভেতরে থাকে এই পর্বের দুটি টান — মোট পথ কমানো আর কাউকে অনির্দিষ্টকাল বসিয়ে না রাখা।
প্র ০৩Write amplification SSD-র আয়ু খায় — তাহলে file system আর database কীভাবে নিজেদের বদলেছে?
SSD নির্মাতারা আয়ু জানান TBW (terabytes written — মোট কত TB লেখা সহ্য করবে) বা DWPD (drive writes per day — নির্দিষ্ট বছর ধরে প্রতিদিন পুরো ড্রাইভ কতবার লেখা যাবে) দিয়ে। এই সংখ্যা host-এর লেখার হিসাবে; ভেতরের WA বেশি হলে আসল NAND-ক্ষয় তার চেয়ে দ্রুত। তাই সফটওয়্যারের লেখার ধরন সরাসরি হার্ডওয়্যারের আয়ুতে প্রভাব ফেলে।
প্রথম শিক্ষা এলো log-structured নকশা থেকে। ১৯৯০-এর দশকের শুরুতে Mendel Rosenblum আর John Ousterhout-এর Log-structured File System (LFS) প্রস্তাব করেছিল সব লেখা ডিস্কের শেষে ক্রমানুসারে যোগ করা — তখন উদ্দেশ্য ছিল HDD-র seek এড়ানো। মজার ব্যাপার, SSD-র FTL ভেতরে ঠিক এটিই করে, আর LFS-এর “cleaner” আসলে GC-র পূর্বসূরি। পরে Samsung-এর F2FS (Linux 3.8-এ, ২০১৩ সালের শুরুতে kernel-এ আসে) flash-এর জন্য log-structured ধারণায় নকশা করা। Database-জগতে LSM-tree (RocksDB, Cassandra-র মতো সিস্টেমে) এলোমেলো overwrite-এর বদলে ক্রমানুসারে লেখা ফাইল বানায় আর পরে compaction করে — যদিও compaction নিজেও এক ধরনের write amplification, তাই আপস আছে।
সর্বশেষ ধাপ হলো host আর ডিভাইসের দায়িত্ব নতুন করে ভাগ করা। NVMe-র Zoned Namespaces (ZNS)-এ ডিভাইস নিজেকে কয়েকটি “zone” হিসেবে দেখায়, যেখানে শুধু ক্রমানুসারে লেখা যায় আর পুরো zone একসাথে মুছতে হয় — অর্থাৎ erase block-এর নিয়ম host-এর কাছে খোলাখুলি। তখন GC কোথায় আর কখন হবে, তা file system বা database নিজে ঠিক করে, যে জানে কোন ডেটা একসাথে মরবে। এতে WA কমে আর over-provisioning কম লাগে, বিনিময়ে সফটওয়্যার জটিল হয়। একই চিন্তা প্র ০১-এর SMR ডিস্কেও (host-managed SMR).
মূল উপলব্ধি: যে স্তর জানে কোন ডেটা একসাথে বাতিল হবে, তার হাতে garbage collection থাকলে বাড়তি লেখা কমে — storage নকশার ইতিহাস হলো এই জ্ঞান ঠিক স্তরে পৌঁছে দেওয়ার চেষ্টা।
প্র ০৪NVMe-তে latency ১০ µs-এর ঘরে নেমে এলে OS-এর কাছে কী বদলায়? Interrupt, polling আর kernel এড়ানো নিয়ে ভাবুন।
HDD-র যুগে একটি I/O-তে প্রায় ১০ ms. তার মধ্যে system call, block layer, scheduler, driver, interrupt সামলানো, প্রসেস জাগানো — এসবে মিলিয়ে হয়তো কয়েক দশ µs; মোটের ১%-এরও কম, কেউ খেয়াল করত না। এখন ডিভাইস নিজেই কয়েক দশ µs-এ উত্তর দিলে একই সফটওয়্যার-খরচ মোটের বড় অংশ। Amdahl-এর নিয়ম মনে করুন: যে অংশ দ্রুত হয়নি, সেটিই এখন সীমা।
OS কয়েকটি উপায়ে সাড়া দিয়েছে। প্রথম, block layer-কে বহু-queue করা (blk-mq), যাতে প্রতিটি core নিজের queue-তে lock ছাড়াই অনুরোধ দেয় — NVMe-র নকশার সাথে মিলিয়ে; এজন্য scheduler “none”. দ্বিতীয়, system call-এর সংখ্যা কমানো — io_uring-এ অনুরোধ আর ফল shared memory-র ring-এ যায়, অনেক অনুরোধ একটি syscall-এ বা একটিও ছাড়া। তৃতীয়, interrupt-এর বদলে polling: খুব দ্রুত ডিভাইসে একটি interrupt নেওয়া, context বদলানো আর প্রসেস জাগানোর খরচ অপেক্ষার চেয়ে বেশি হতে পারে, তাই CPU কিছুক্ষণ ঘুরে ঘুরে completion queue দেখে (পর্ব ৩৯-এর polling বনাম interrupt-এর আপস নতুন রূপে)। চতুর্থ, কিছু অতি-দ্রুত সিস্টেম kernel-কেই এড়িয়ে যায় — SPDK-এর মতো কাঠামোয় user-space থেকে সরাসরি ডিভাইস চালানো হয়, বিনিময়ে নিরাপত্তা আর সহজ ভাগাভাগির সুবিধা হারায়।
একটি সতর্ক ইতিহাসও আছে। Intel আর Micron-এর 3D XPoint (Optane) প্রযুক্তি flash-এর চেয়েও কম latency আর byte-স্তরের ব্যবহার দিয়েছিল; OS-গুলো persistent memory-র জন্য নতুন পথ (যেমন DAX) বানিয়েছিল। কিন্তু ২০২২ সালে Intel Optane ব্যবসা গুটিয়ে নেওয়ার ঘোষণা দেয়। প্রযুক্তি ভালো হলেও দাম, বাস্তুতন্ত্র আর সফটওয়্যার-বদলের খরচ টিকে থাকা ঠিক করে।
মূল উপলব্ধি: হার্ডওয়্যার যত দ্রুত হয়, OS-এর “সাধারণ” খরচগুলো তত দৃশ্যমান হয় — তখন queue, syscall আর interrupt-এর নকশাই পারফরম্যান্স ঠিক করে।
প্র ০৫পুরোনো ল্যাপটপ বিক্রির আগে ফাইল মুছে দিলেন — HDD আর SSD-তে ডেটা কি সত্যিই গেল? নিরাপদে মোছার সঠিক উপায় কী?
সাধারণভাবে ফাইল মুছলে (এমনকি Recycle Bin খালি করলেও) file system শুধু নিজের হিসাবে block-গুলো “ফাঁকা” লেখে; ডেটা ডিস্কে থেকে যায়, যতক্ষণ না নতুন কিছু তার ওপর লেখা হয়। HDD-তে তাই recovery টুল দিয়ে মোছা ফাইল প্রায়ই ফেরত পাওয়া যায়। Quick format-ও মূলত file system-এর কাঠামো নতুন করে লেখে, ডেটা নয়। পুরোনো ডিস্ক বিক্রি বা দান করার আগে এটি একটি বাস্তব গোপনীয়তার ঝুঁকি — ছবি, ব্যাংকের কাগজ, ব্রাউজারের সংরক্ষিত তথ্য।
HDD-তে সমাধান তুলনামূলক সরল: পুরো ডিস্ক একবার নতুন ডেটা দিয়ে লিখে দিলে আধুনিক ডিস্কে আগের ডেটা সাধারণ উপায়ে ফেরানো যায় না (বহুবার লেখার পুরোনো পরামর্শ আজকের ঘন ডিস্কে সাধারণত অপ্রয়োজনীয় বলে মনে করা হয়; তবে reallocate হওয়া spare sector-এ পুরোনো ডেটা থেকে যেতে পারে)। SSD-তে ব্যাপারটি আলাদা, আর এই পর্বের FTL-ই কারণ। একটি ফাইলের ওপর overwrite করলে নতুন ডেটা যায় নতুন page-এ; পুরোনো page শুধু বাতিল চিহ্নিত হয়, GC না হওয়া পর্যন্ত flash-এ থাকে। over-provisioning-এর অংশে OS পৌঁছাতেই পারে না। তাই “ফাইলটির ওপর শূন্য লিখে দিন” SSD-তে নির্ভরযোগ্য নয়। TRIM চালু থাকলে মোছা অংশ সাধারণত দ্রুত অপাঠযোগ্য হয়ে যায়, কিন্তু এটি নিরাপত্তার নিশ্চয়তা নয়।
নির্ভরযোগ্য পথ হলো ডিভাইসের নিজের মোছার আদেশ, যা FTL জানে: ATA Secure Erase, NVMe-র Format বা Sanitize — নির্মাতার টুল বা OS-এর ডকুমেন্টেশন অনুযায়ী (ভুল ডিভাইস বাছলে সব ডেটা চলে যাবে, তাই ডিভাইস নাম দুবার মেলান)। আরও ভালো অভ্যাস: শুরু থেকেই পুরো ডিস্ক encryption — Windows-এ BitLocker, macOS-এ FileVault, Linux-এ LUKS. তখন key মুছে ফেললেই (cryptographic erase) সব ডেটা অর্থহীন, আর হারানো বা চুরি যাওয়া ল্যাপটপেও ডেটা সুরক্ষিত। আধুনিক ফোন এই নীতিতেই চলে — factory reset আসলে key মোছা।
মূল উপলব্ধি: SSD-তে “কোথায় লেখা হলো” ঠিক করে FTL, OS নয় — তাই নিরাপদ মোছার দায়িত্বও দিতে হয় ডিভাইসের নিজস্ব আদেশ বা encryption-কে।
অনুশীলন
হাতে হিসাব, আউটপুট অনুমান আর কমান্ড — আগে নিজে চেষ্টা করুন, তারপর উত্তর মেলান।
-
হাতে trace: Cylinder 0–199, head 50-এ, এখন ওপরের দিকে (199-এর দিকে) চলছে। অনুরোধ আসার ক্রমে: 82, 170, 43, 140, 24, 16, 190. FCFS, SSTF, SCAN, C-SCAN, LOOK আর C-LOOK-এর মোট head movement বের করুন (C-SCAN/C-LOOK-এ ফেরার লাফ গুনে আর বাদ দিয়ে)।
উত্তর (simulator-এ queue, head আর
DIR = "up"বদলে যাচাই করা):FCFS 50→82→170→43→140→24→16→190 32+88+127+97+116+8+174 = 642 SSTF 50→43→24→16→82→140→170→190 7+19+8+66+58+30+20 = 208 SCAN 50→82→140→170→190→199→43→24→16 32+58+30+20+9+156+19+8 = 332 C-SCAN 50→…→190→199 ⇢ 0→16→24→43 149 + [199] + 43 = 391 (লাফ বাদে 192) LOOK 50→82→140→170→190→43→24→16 140 + 174 = 314 C-LOOK 50→…→190 ⇢ 16→24→43 140 + [174] + 27 = 341 (লাফ বাদে 167)খেয়াল করুন, এখানে SSTF (২০৮) সবচেয়ে কম। সর্বনিম্ন সীমা: (১৯০ − ১৬) + min(৫০ − ১৬, ১৯০ − ৫০) = ১৭৪ + ৩৪ = ২০৮ — SSTF এই সারিতে সর্বোত্তম পথই পেয়েছে, কারণ নিচের তিনটি অনুরোধ কাছেই। ওপরের দিকে বাধ্যতামূলকভাবে যাওয়া SCAN-পরিবার এখানে বেশি পথ চলে।
-
সংখ্যাভিত্তিক: (ক) একটি 10000 RPM ডিস্কের গড় seek ৪ ms, transfer rate ২০০ MB/s (১ MB = ১০৬ byte). একটি এলোমেলো 64 KiB (৬৫,৫৩৬ byte) পড়ার গড় access time কত? (খ) একটি 7200 RPM ডিস্কের প্রতি track-এ ৪০০টি 512-byte sector. একটি sector পড়ার transfer time আর ডিস্কের সর্বোচ্চ transfer rate কত?
(ক) এক পাক = ৬০,০০০ ÷ ১০,০০০ = ৬ ms, গড় latency = ৩ ms. Transfer = ৬৫,৫৩৬ ÷ (২০০ × ১০৬) সেকেন্ড ≈ ০.৩২৮ ms. মোট ≈ ৪ + ৩ + ০.৩২৮ = ৭.৩২৮ ms. এখানেও transfer মোটের ৫%-এরও কম।
(খ) এক পাক = ৮.৩৩৩ ms, আর এক পাকে ৪০০টি sector head-এর নিচ দিয়ে যায়: একটি sector = ৮.৩৩৩ ÷ ৪০০ ≈ ০.০২০৮ ms. Transfer rate = ৪০০ × ৫১২ = ২,০৪,৮০০ byte প্রতি ৮.৩৩৩ ms ≈ ২৪.৫৮ MB/s. (দুটি হিসাবই access-time calculator-এর
hdd()ফাংশনের সূত্রে করা যায়।) -
আউটপুট অনুমান: Disk-scheduling simulator-এ শুধু
DIR = "up"আরCOUNT_RETURN = falseকরে চালালে প্রথম অংশে C-SCAN আর C-LOOK-এরtotal =লাইনে কী ছাপা হবে, আর C-SCAN-এরmoves:লাইনে ফেরার লাফটি কীভাবে দেখাবে?C-SCAN-এ
total = 183, C-LOOK-এtotal = 153— শেষ টেবিলের “up,no-return” কলামের সাথে এক। C-SCAN-এর moves লাইন:12 + 2 + 31 + 24 + 2 + 59 + 16 + [199 not counted] + 14 + 23— লাফের দূরত্ব দেখানো হয়, কিন্তু মোটে যোগ হয় না (১৪৬ + ১৪ + ২৩ = ১৮৩)। বাকি চারটি algorithm-এ ফেরার লাফ নেই, তাই তাদের সংখ্যাCOUNT_RETURN-এ বদলায় না: FCFS ৬৪০, SSTF ২৩৬, SCAN ৩৩১, LOOK ২৯৯. -
কমান্ড লিখুন: একটি Linux সার্ভারে HDD
sdaআর NVMenvme0n1. (ক) দুটির বর্তমান scheduler আর ঘোরা কি না কীভাবে দেখবেন? (খ) শুধুsda-কে এখনই bfq করুন। (গ) সব ঘোরা SATA ডিস্কে reboot-এর পরেও bfq রাখার udev নিয়ম লিখুন।# (ক) পড়তে root লাগে না lsblk -d -o NAME,ROTA,SCHED cat /sys/block/sda/queue/scheduler /sys/block/nvme0n1/queue/scheduler cat /sys/block/sda/queue/rotational # 1 = HDD # (খ) এখনই বদলানো (root), reboot-এ হারায় echo bfq | sudo tee /sys/block/sda/queue/scheduler # (গ) /etc/udev/rules.d/60-iosched.rules ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"নিয়ম লেখার পর
sudo udevadm control --reloadআরsudo udevadm triggerদিয়ে প্রয়োগ করে আবার (ক) দিয়ে মিলিয়ে নিন।ROTAশর্তের কারণে SATA SSD (rotational = 0) আর NVMe এই নিয়মে বদলাবে না — NVMe none-ই থাকবে। kernel-এ bfq module না থাকলে লেখাটি ব্যর্থ হবে; তখনschedulerফাইলের তালিকায় bfq আছে কি না দেখুন। Production-এ বদলের আগে-পরে fio-র মতো টুলে latency মেপে সিদ্ধান্ত নিন।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমহার্ড ডিস্ক থেকে একটি block পড়ার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- Driver ডিস্কের controller-কে LBA আর আকারসহ পড়ার আদেশ পাঠায়
- Arm সরে head ঠিক cylinder-এ পৌঁছায় (seek)
- চাওয়া sector ঘুরে head-এর নিচে আসা পর্যন্ত অপেক্ষা (rotational latency)
- Sector-গুলো পড়ে ডিস্কের buffer-এ আসে (transfer)
- DMA দিয়ে ডেটা RAM-এ যায়, তারপর CPU একটি interrupt পায়
Cylinder 0–199-এর ডিস্কে head 53-এ। অনুরোধ আসার ক্রমে: 98, 183, 37, 122, 14, 124, 65, 67. FCFS-এ মোট head movement কত?
- ২৩৬
- ৬৩৮
- ৬৪০
- ১৮৩
একই সারিতে (head 53; 98, 183, 37, 122, 14, 124, 65, 67; cylinder 0–199) SSTF-এর সেবার ক্রম আর মোট head movement কী?
- 37, 14, 65, 67, 98, 122, 124, 183 — ২০৮
- 65, 67, 37, 14, 98, 122, 124, 183 — ২৩৬
- 65, 67, 98, 122, 124, 183, 37, 14 — ২৯৯
- 98, 183, 37, 122, 14, 124, 65, 67 — ৬৪০
7200 RPM-এ ঘোরা একটি হার্ড ডিস্কের গড় rotational latency কত?
- প্রায় ৪.১৭ ms
- প্রায় ৮.৩৩ ms
- প্রায় ২ ms
- গড় seek time-এর সমান
SCAN আর C-SCAN disk scheduling-এর মূল পার্থক্য কোনটি?
- SCAN প্রান্ত পর্যন্ত যায়, C-SCAN শেষ অনুরোধে ঘোরে
- C-SCAN-এ starvation হতে পারে, SCAN-এ নয়
- C-SCAN সবসময় কম মোট head movement দেয়
- SCAN দুই দিকেই সেবা দেয়; C-SCAN শুধু এক দিকে সেবা দিয়ে শুরুতে ফেরে, ফলে অপেক্ষা বেশি সমান
একটি SSD-তে garbage collection-এর সময় victim block-এর ৭৫% page বৈধ থাকে। সরল মডেল WA = 1 ÷ (1 − u) অনুযায়ী write amplification কত?
- ১.৩৩
- ৪
- ০.৭৫
- ১০
SSD-তে TRIM (বা discard) আদেশের কাজ কী?
- OS ডিভাইসকে জানায় কোন LBA-র ডেটা আর লাগবে না, যাতে GC সেগুলো কপি না করে
- ফাইলের block পাশাপাশি সাজিয়ে defragment করে
- নির্দিষ্ট LBA-গুলো সঙ্গে সঙ্গে নিরাপদে মুছে ফেলে, ফেরত আনা অসম্ভব করে
- খারাপ block খুঁজে spare block দিয়ে বদলে দেয়
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- HDD-র গঠন: platter, track, sector, cylinder, head, arm; zoned bit recording-এ বাইরের track দ্রুত; 4 KiB Advanced Format আর 1 MiB alignment; OS দেখে শুধু LBA.
- Access time = seek + rotational latency (গড়ে অর্ধেক পাক; 7200 RPM-এ ৪.১৬৭ ms) + transfer. এলোমেলো 4 KiB ≈ ১৩.২ ms (৭৬ IOPS); ক্রমানুসারে পড়া কয়েকশো গুণ দ্রুত।
- ক্লাসিক সারি (head 53): FCFS ৬৪০, SSTF ২৩৬, SCAN ↓ ২৩৬, LOOK ↓ ২০৮ (সর্বনিম্ন), C-SCAN ↑ ৩৮২ / ১৮৩, C-LOOK ↑ ৩২২ / ১৫৩ — দিক আর ফেরার নিয়ম সবসময় লিখুন। SSTF-এ starvation.
- বাস্তবে: NCQ-তে ডিস্ক নিজে সাজায়; Linux-এ mq-deadline, bfq, kyber, none; NVMe-তে seek নেই আর queue অনেক, তাই none.
- SSD: SLC→QLC, page-এ লেখা, block-এ মোছা, overwrite নেই; FTL remap, GC, WA = NAND ÷ host ≈ 1 ÷ (1 − u); wear leveling, TRIM, over-provisioning; formatting, boot block, bad-block sparing, DAS/NAS/SAN/ক্লাউড।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৪১ · ফাইল — file descriptor, open/read/write আর access methodপরবর্তী পর্বব্লকের ওপর ফাইলের ধারণা।
- অপারেটিং সিস্টেম · কোর্স হোম৬৪টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- পর্ব ৩৯ · I/O system — polling, interrupt, DMA আর device driverপেছনে ফিরেডিস্কের অনুরোধ কীভাবে driver আর DMA পেরিয়ে যায়।
- পর্ব ৬০ · Numerical সমস্যা — scheduling, page replacement, Banker's আর diskপরীক্ষার প্রস্তুতিDisk scheduling-সহ আরও অনুশীলনী।
- DBMS · Storage internalsডেটাবেসDatabase কীভাবে page, block আর ডিস্কের গতি মাথায় রেখে ডেটা সাজায়।
- কম্পিউটার ফান্ডামেন্টালস · মেমরি আর স্টোরেজভিত্তিRAM, HDD, SSD — শুরুর পরিচিতি।