এই পর্বে যা শিখবেন
- পাওয়ার বাটন চাপা থেকে login স্ক্রিন পর্যন্ত প্রতিটি ধাপ — কে কাকে চালায়, কোথা থেকে পড়ে
- BIOS + MBR আর UEFI + GPT-এর পার্থক্য, সীমা (২ TiB, ৪টি partition বনাম ১২৮টি) আর MBR-এর বাইট হাতে পড়া
- GRUB 2, systemd-boot আর Windows Boot Manager কী করে; kernel আর initramfs কেন একসাথে আসে
- SysV init থেকে systemd — target, unit আর dependency অনুযায়ী সমান্তরাল চালু; macOS আর Windows-এ একই কাজ কে করে
- বুট কেন ব্যর্থ হয়, recovery-র ধারণা, বুট-সময় মাপা — আর AI-এর বুট-পরামর্শ কীভাবে যাচাই করবেন
১ · পাওয়ার বাটন থেকে login — বুটের বড় ছবি
সকালে অফিসে ল্যাপটপের পাওয়ার বাটন চাপলেন। ২০–৩০ সেকেন্ড পরে login স্ক্রিন এলো। এই অল্প সময়ে কম্পিউটারের ভেতরে একটি অদ্ভুত সমস্যার সমাধান হয়। সমস্যাটি হলো: অপারেটিং সিস্টেম নিজেই একটি প্রোগ্রাম, আর প্রোগ্রাম চালাতে OS লাগে। তাহলে OS-কে মেমরিতে আনবে কে?
উত্তর হলো ধাপে ধাপে ছোট থেকে বড় প্রোগ্রাম চালানো। প্রথমে একটি খুব ছোট প্রোগ্রাম চলে, যেটি মাদারবোর্ডের চিপে স্থায়ীভাবে লেখা থাকে। সে একটু বড় একটি প্রোগ্রামকে ডিস্ক থেকে আনে। সেটি আরও বড়টিকে আনে। শেষে পুরো OS চলে আসে। ইংরেজি প্রবাদ “pulling yourself up by your bootstraps” (জুতার ফিতা ধরে নিজেকে টেনে তোলা) থেকে এর নাম bootstrapping, সংক্ষেপে বুট।
একটি ব্যাংকের শাখা সকালে খোলার কথা ভাবুন। প্রথমে দারোয়ান আসেন — তাঁর কাছে শুধু মূল গেটের চাবি, আর তিনি জানেন লাইট-ফ্যান ঠিক আছে কি না দেখতে হবে। তিনি গেট খুলে দিলে ক্যাশ অফিসার আসেন, ভল্ট খোলেন। তারপর ম্যানেজার আসেন, সব কাউন্টার চালু করেন — টোকেন মেশিন, ক্যাশ কাউন্টার, ঋণ বিভাগ। সবশেষে গ্রাহকের জন্য দরজা খোলে। কেউ একা সব করেন না; প্রত্যেকে পরের জনের কাজের পরিবেশ তৈরি করে দেন। বুটও তাই: firmware = দারোয়ান, bootloader = ক্যাশ অফিসার, kernel = ম্যানেজার, init = কাউন্টারগুলো চালু করা, login = গ্রাহকের জন্য দরজা খোলা।
বুটের রিলে দৌড় — পাঁচটি হাত বদল
Firmware → bootloader → kernel → init → user session
- Firmware
BIOS / UEFIচিপে লেখা, প্রথম চলে - Bootloader
GRUB / bootmgrOS খুঁজে মেমরিতে আনে - Kernel
vmlinuz / ntoskrnlহার্ডওয়্যার নিয়ন্ত্রণ নেয় - init (PID 1)
systemd / launchdসার্ভিস চালু করে - Login
getty / GDMআপনার session
প্রথম মুহূর্তটি আরও একটু কাছ থেকে দেখি। পাওয়ার বাটন চাপলে power supply ভোল্টেজ স্থির করে মাদারবোর্ডকে একটি “Power Good” সংকেত পাঠায়। তখন CPU reset অবস্থা থেকে বেরিয়ে আসে। Reset-এর পর CPU-র register-গুলো নির্দিষ্ট মানে থাকে, আর সে একটি নির্দিষ্ট ঠিকানা থেকে প্রথম নির্দেশ পড়ে — একে বলে reset vector. x86 CPU-তে এই ঠিকানা 0xFFFFFFF0, প্রথম ৪ GiB ঠিকানা-জগতের একদম শেষ প্রান্তের ১৬ বাইট আগে। মাদারবোর্ড এই ঠিকানাটি RAM-এ নয়, firmware-এর flash চিপে জুড়ে রাখে। সেখানে সাধারণত একটি jump নির্দেশ থাকে, যা firmware-এর মূল কোডে লাফ দেয়। ARM চিপে (ফোন, Apple silicon, Raspberry Pi) ঠিকানা ভিন্ন, প্রায়ই চিপের ভেতরের একটি Boot ROM প্রথম চলে — কিন্তু নীতি একই: হার্ডওয়্যারে আগে থেকে ঠিক করা একটি জায়গা থেকে প্রথম নির্দেশ।
বুটের প্রতিটি ধাপকে তিনটি প্রশ্ন দিয়ে চিনুন: (১) এটি কোথায় থাকে (চিপে, ডিস্কের নির্দিষ্ট সেক্টরে, না একটি ফাইলে)? (২) এটি কী জানে (শুধু সেক্টর পড়তে, না file system বুঝতে)? (৩) পরের ধাপকে কোথায় খোঁজে আর কী তথ্য দিয়ে হাত বদল করে? পরীক্ষার প্রশ্ন বা বাস্তবের বুট-সমস্যা — দুটোতেই এই তিন প্রশ্নই পথ দেখায়।
এই পর্বটি পর্ব ৪-এর হার্ডওয়্যার (CPU, memory, interrupt), পর্ব ৫-এর user mode আর kernel mode এবং পর্ব ৬-এর kernel-গঠনের ওপর দাঁড়িয়ে আছে। বুট শেষে যে প্রথম প্রসেসটি জন্মায়, সেখান থেকেই মডিউল ২ শুরু — পর্ব ৮-এ প্রসেস আর পর্ব ১০-এ fork/exec দেখবেন।
২ · Legacy BIOS — POST আর ৫১২ বাইটের MBR
BIOS (Basic Input/Output System) এসেছে ১৯৮১ সালের IBM PC থেকে। প্রায় তিন দশক ধরে PC এভাবেই বুট হয়েছে, আর অনেক পুরোনো কম্পিউটারে এবং কিছু virtual machine-এ আজও হয়। BIOS-এর প্রথম কাজ POST (Power-On Self-Test): CPU, RAM, কীবোর্ড কন্ট্রোলার আর ভিডিও কার্ড ঠিক আছে কি না যাচাই। গুরুতর সমস্যা হলে, স্ক্রিন চালু হওয়ার আগেই, BIOS কয়েকটি “বিপ” শব্দে জানায় — কত বিপ, কী অর্থ, তা নির্মাতাভেদে আলাদা। তারপর BIOS নিজের সেটিং (বুট-ক্রম, তারিখ-সময়) পড়ে — এগুলো থাকে ব্যাটারি-চালিত একটি ছোট মেমরিতে, যাকে ঐতিহাসিক কারণে CMOS বলে। পুরোনো ডেস্কটপে তারিখ বারবার ২০০০ সালে ফিরে গেলে সেজন্যই মেকানিক বলেন “CMOS ব্যাটারি বদলান।”
এরপর BIOS বুট-ক্রমের প্রথম ডিস্কের প্রথম সেক্টরটি — LBA 0 (LBA = Logical Block Address, ডিস্কের সেক্টরের ক্রমিক নম্বর), মাত্র ৫১২ বাইট — মেমরির 0x7C00 ঠিকানায় এনে রাখে। একে বলে MBR (Master Boot Record). BIOS কোনো file system বোঝে না; সে জানে শুধু তিনটি কাজ: সেক্টর ০ পড়া, শেষ দুই বাইট 55 AA কি না দেখা, তারপর সেখানে লাফ দেওয়া। এই দুই বাইটকে বলে boot signature.
| বাইট (দশমিক) | Offset (hex) | আকার | কী থাকে |
|---|---|---|---|
| ০–৪৪৫ | 0x000–0x1BD | ৪৪৬ বাইট | Bootstrap code — প্রথম ধাপের bootloader |
| ৪৪৬–৫০৯ | 0x1BE–0x1FD | ৪ × ১৬ = ৬৪ বাইট | Partition table — সর্বোচ্চ ৪টি primary partition |
| ৫১০–৫১১ | 0x1FE–0x1FF | ২ বাইট | Signature 0x55, 0xAA |
৪৪৬ বাইটে একটি file system পড়ার কোড লেখা প্রায় অসম্ভব। তাই আধুনিক bootloader (যেমন GRUB 2) ভাগ করে কাজ করে: MBR-এর ছোট কোড শুধু ডিস্কের পরের কয়েকটি নির্দিষ্ট সেক্টর থেকে বড় একটি অংশ আনে। নিচের ডায়াগ্রামে পুরো BIOS-শিকলটি ধাপে ধাপে দেখুন:
- Reset
0xFFFFFFF0প্রথম নির্দেশ - POST
BIOSহার্ডওয়্যার যাচাই - MBR
LBA 0 → 0x7C00৫১২ বাইট - core.img
LBA 1…GRUB-এর বড় অংশ - GRUB মেনু
grub.cfgfile system পড়ে - Kernel
vmlinuz + initrdহাত বদল
| কে চলছে | |
| কোড কোথায় ছিল | |
| CPU mode | |
| File system বোঝে? |
- Reset vector. Power Good সংকেতের পর CPU reset থেকে বেরিয়ে
0xFFFFFFF0ঠিকানা থেকে প্রথম নির্দেশ পড়ে। ঠিকানাটি firmware চিপে জোড়া। x86 CPU এ সময় ১৯৭৮ সালের 8086-এর মতো ১৬-bit real mode-এ থাকে — পুরোনো সফটওয়্যারের সাথে মিল রাখার জন্য। - POST আর ডিভাইস প্রস্তুত। BIOS CPU, RAM, ভিডিও যাচাই করে, ডিভাইসগুলো চালু করে, CMOS থেকে বুট-ক্রম পড়ে। সমস্যা হলে বিপ বা স্ক্রিনে বার্তা। কোনো ডিস্কের file system এখনো অজানা।
- MBR লোড। বুট-ক্রমের প্রথম ডিস্কের LBA 0 পড়ে মেমরির
0x7C00-এ রাখা হলো। বাইট ৫১০–৫১১-এ55 AAআছে কি না দেখে BIOS সেখানে লাফ দিল। না থাকলে পরের ডিস্ক, বা “No bootable device” বার্তা। - দ্বিতীয় অংশ আনা। ৪৪৬ বাইটের কোড (GRUB-এর
boot.img) file system বোঝে না — সে শুধু নির্দিষ্ট সেক্টর নম্বর থেকেcore.imgপড়ে। MBR ডিস্কে এটি থাকে MBR আর প্রথম partition-এর মাঝের ফাঁকা জায়গায় (আজকাল প্রথম partition সাধারণত LBA 2048 থেকে শুরু, তাই LBA 1–2047 ফাঁকা)। core.img-এর ভেতরেই ext4-এর মতো file system পড়ার module. - মেনু আর কনফিগ। এখন GRUB ফাইল পড়তে পারে:
/boot/grub/grub.cfgখুলে মেনু দেখায় — Ubuntu, Advanced options, Windows… আপনি না বাছলে কয়েক সেকেন্ড পর ডিফল্টটি চলে। - Kernel-এর হাতে লাঠি। GRUB
vmlinuz(সংকুচিত kernel) আরinitrd.img(initramfs) RAM-এ আনে, kernel command line (যেমনroot=UUID=… ro quiet) জানিয়ে kernel-এ লাফ দেয়। এরপর bootloader-এর আর কোনো ভূমিকা নেই। CPU-কে 64-bit long mode-এ নেওয়া kernel-এর নিজের প্রথম কাজগুলোর একটি।
MBR-এর একটি partition entry হাতে পড়া
প্রতিটি partition entry ১৬ বাইট। এর মধ্যে আজকের কাজে লাগে চারটি জিনিস: বাইট ০ — bootable চিহ্ন (0x80 মানে “এখান থেকে বুট”), বাইট ৪ — partition-এর type (একটি সংখ্যা, যেমন 0x07 = NTFS, 0x83 = Linux), বাইট ৮–১১ — শুরুর LBA, বাইট ১২–১৫ — মোট সেক্টর সংখ্যা। বাইট ১–৩ আর ৫–৭-এ পুরোনো CHS (cylinder-head-sector) ঠিকানা থাকে, যা আজ আর কেউ ব্যবহার করে না। সংখ্যাগুলো little-endian — অর্থাৎ ছোট বাইটটি আগে লেখা। নিচে একটি বাস্তবসম্মত entry ধাপে ধাপে পড়ুন:
| Bootable | |
| Type | |
| শুরুর LBA | |
| সেক্টর সংখ্যা | |
| সেক্টরটি বৈধ MBR? |
- কাঁচা বাইট। সেক্টর ০-এর offset
0x1BE(দশমিকে ৪৪৬) থেকে প্রথম entry-র ১৬টি বাইট, আর একদম শেষে signature. এখনো কিছুই বোঝা হয়নি — সব “?”। - বাইট ০ =
80. এটি “active” বা bootable চিহ্ন। পুরোনো MBR কোড চারটি entry-র মধ্যে যেটিতে0x80, সেই partition-এর প্রথম সেক্টর (boot sector) চালাত। Windows-এর MBR কোড আজও এভাবেই কাজ করে। - বাইট ৪ =
07. Partition type 0x07 — NTFS বা exFAT. Type শুধু একটি ইঙ্গিত; আসল file system চেনা হয় partition-এর ভেতরের তথ্য দেখে। - বাইট ৮–১১ =
00 08 00 00. Little-endian, তাই উল্টো দিক থেকে পড়ুন:0x00000800= ২০৪৮. Partition শুরু LBA 2048 থেকে — ২০৪৮ × ৫১২ বাইট = ঠিক ১ MiB. আধুনিক partition tool ইচ্ছা করেই ১ MiB-তে শুরু করে, যাতে SSD আর 4K-সেক্টর ডিস্কে alignment ঠিক থাকে। - বাইট ১২–১৫ =
00 20 03 00. উল্টে পড়লে0x00032000= ২০৪৮০০টি সেক্টর। ২০৪৮০০ × ৫১২ = ১০৪৮৫৭৬০০ বাইট = ১০০ MiB. এই চার বাইটই MBR-এর সীমা ঠিক করে — ৩২ bit-এ সর্বোচ্চ ২৩২টি সেক্টর। - Signature
55 AA. বাইট ৫১০-এ0x55, ৫১১-এ0xAA— BIOS এটুকু দেখেই সেক্টরটিকে বুটযোগ্য ধরে। একটি ১৬-bit little-endian সংখ্যা হিসেবে পড়লে মানটি0xAA55, তাই বইয়ে দুই রকম লেখাই দেখবেন।
এবার একই কাজ কোড দিয়ে। নিচের প্রোগ্রামটি একটি নমুনা MBR (হাতে বসানো বাইট) থেকে signature যাচাই করে চারটি entry ছাপে। আসল ডিস্কের সেক্টর পড়তে root অনুমতি লাগে (/dev/sda), তাই এখানে বাইটগুলো কোডেই বসানো:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
static uint32_t le32(const uint8_t *p) { /* little-endian bytes -> number */
return p[0] | p[1] << 8 | p[2] << 16 | (uint32_t)p[3] << 24;
}
static const char *type_name(uint8_t t) {
switch (t) {
case 0x00: return "empty"; case 0x07: return "NTFS/exFAT";
case 0x0C: return "FAT32 (LBA)"; case 0x82: return "Linux swap";
case 0x83: return "Linux"; case 0xEE: return "GPT protective";
default: return "other";
}
}
int main(void) {
uint8_t mbr[512] = {0}; /* sector 0 of a disk */
const uint8_t part[3][16] = { /* boot,CHS(3),type,CHS(3),LBA start,size */
{0x80,0,0,0, 0x07,0,0,0, 0x00,0x08,0x00,0x00, 0x00,0x20,0x03,0x00},
{0x00,0,0,0, 0x83,0,0,0, 0x00,0x28,0x03,0x00, 0x00,0x00,0x40,0x01},
{0x00,0,0,0, 0x82,0,0,0, 0x00,0x28,0x43,0x01, 0x00,0x00,0x40,0x00}};
memcpy(mbr + 446, part, sizeof part); /* table starts at byte 446 */
mbr[510] = 0x55; mbr[511] = 0xAA; /* boot signature */
if (mbr[510] != 0x55 || mbr[511] != 0xAA) { puts("not a valid MBR"); return 1; }
puts("signature 0x55AA OK");
puts("# boot type name start LBA sectors size");
for (int i = 0; i < 4; i++) {
const uint8_t *e = mbr + 446 + 16 * i;
uint32_t start = le32(e + 8), count = le32(e + 12);
printf("%d %-4s 0x%02X %-14s %10u %10u %5u MiB\n", i + 1,
e[0] == 0x80 ? "yes" : "-", e[4], type_name(e[4]),
start, count, count / 2048); /* 2048 sectors x 512 B = 1 MiB */
}
return 0;
}একটি আসল রানের আউটপুট:
signature 0x55AA OK
# boot type name start LBA sectors size
1 yes 0x07 NTFS/exFAT 2048 204800 100 MiB
2 - 0x83 Linux 206848 20971520 10240 MiB
3 - 0x82 Linux swap 21178368 4194304 2048 MiB
4 - 0x00 empty 0 0 0 MiB
le32() ফাংশনটিই little-endian পড়ার নিয়ম: বাইট ০ সবচেয়ে ছোট ঘর, বাইট ৩ সবচেয়ে বড়। খেয়াল করুন, partition ২ শুরু হয়েছে ঠিক যেখানে ১ শেষ (২০৪৮ + ২০৪৮০০ = ২০৬৮৪৮), আর ৩ শুরু ২০৬৮৪৮ + ২০৯৭১৫২০ = ২১১৭৮৩৬৮-এ — ফাঁক নেই, ওভারল্যাপও নেই। চতুর্থ entry ফাঁকা; MBR-এ এর বেশি primary partition রাখার জায়গাই নেই। বেশি দরকার হলে একটি entry-কে “extended partition” বানিয়ে তার ভেতরে logical partition-এর শিকল রাখা হতো — একটি জোড়াতালি সমাধান। 0xEE type-টি পরের অংশে কাজে লাগবে।
৩ · UEFI আর GPT — আধুনিক পথ
BIOS-এর সীমাবদ্ধতা অনেক: ১৬-bit real mode-এ চলে, মাত্র ১ MiB ঠিকানা সরাসরি দেখতে পায়, ডিস্ক সম্পর্কে জানে শুধু সেক্টর, নেটওয়ার্ক বা গ্রাফিক্সের জন্য প্রমিত কোনো ব্যবস্থা নেই, আর MBR-এর ৩২-bit LBA-র কারণে ডিস্কের সীমা ২ TiB. ১৯৯০-এর দশকের শেষে Intel তাদের Itanium সার্ভার চিপের জন্য EFI (Extensible Firmware Interface) নকশা করে। ২০০৫ সালে কয়েকটি কোম্পানি মিলে UEFI Forum গঠন করে, আর নাম হয় UEFI (Unified EFI). ২০১০-এর দশকে প্রায় সব নতুন PC UEFI-তে চলে যায়; বহু বছর পুরোনো OS চালানোর জন্য UEFI-র ভেতরে BIOS-এর অনুকরণ (CSM, Compatibility Support Module) রাখা হতো, যা নতুন প্ল্যাটফর্মে ক্রমশ বাদ পড়ছে।
UEFI-র মূল পরিবর্তনটি দর্শনগত: সেক্টরের বদলে ফাইল। UEFI firmware নিজেই FAT file system পড়তে পারে। ডিস্কে একটি ছোট FAT32 partition থাকে, নাম EFI System Partition (ESP), সাধারণত ১০০ MiB থেকে ১ GiB. তার ভেতরে bootloader-গুলো সাধারণ ফাইল — \EFI\ubuntu\shimx64.efi, \EFI\Microsoft\Boot\bootmgfw.efi. কোন ফাইল চালাতে হবে, তা লেখা থাকে মাদারবোর্ডের NVRAM-এ রাখা কয়েকটি “boot entry” ভেরিয়েবলে। কোনো entry না মিললে firmware একটি নির্দিষ্ট পথ খোঁজে: \EFI\BOOT\BOOTX64.EFI — এজন্যই বুটেবল USB কোনো সেটিং ছাড়াই কাজ করে।
ডিস্কের partition table-ও বদলেছে। GPT (GUID Partition Table) UEFI স্পেসিফিকেশনেরই অংশ। এতে LBA 0-এ একটি “protective MBR” থাকে — একটিমাত্র entry, type 0xEE, পুরো ডিস্ক জুড়ে — যাতে পুরোনো tool ডিস্কটিকে “ফাঁকা” ভেবে মুছে না ফেলে। LBA 1-এ GPT header, LBA 2 থেকে partition entry-র তালিকা (ডিফল্টে ১২৮টি entry, প্রতিটি ১২৮ বাইট)। প্রতিটি partition-এর type আর পরিচয় একটি ১২৮-bit GUID; ESP-র type GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B. Header আর তালিকার CRC32 checksum থাকে, আর ডিস্কের শেষ সেক্টরগুলোতে থাকে একটি backup কপি — প্রথম দিক নষ্ট হলেও partition হারায় না।
- SEC + PEI
CPU, RAM initপ্রাথমিক প্রস্তুতি - DXE
UEFI driversডিস্ক, USB, GPU - Boot Manager
BootOrderNVRAM পড়ে - ESP
shimx64.efiস্বাক্ষর যাচাই - GRUB
grubx64.efikernel আনে - Kernel
ExitBootServices()firmware সরে যায়
| UEFI phase | |
| যা পড়া হচ্ছে | |
| Secure Boot যাচাই |
- SEC আর PEI. Reset vector থেকে firmware চলে। RAM তখনো প্রস্তুত নয়, তাই প্রথম কোড CPU-র cache-কে অস্থায়ী মেমরি হিসেবে ব্যবহার করে RAM কন্ট্রোলার চালু ও “training” করে। POST-এর কাজের বড় অংশ এখানেই। এই ধাপগুলোর নাম UEFI-র PI (Platform Initialization) স্পেসিফিকেশনের।
- DXE (Driver Execution Environment). Firmware এখন 32/64-bit mode-এ, পুরো RAM ব্যবহার করে। NVMe, SATA, USB, গ্রাফিক্স, এমনকি নেটওয়ার্কের UEFI driver লোড হয় — এজন্যই UEFI সেটআপ স্ক্রিনে মাউস চলে, আর নেটওয়ার্ক থেকে বুট (PXE/HTTP boot) সম্ভব।
- Boot Manager. NVRAM-এর
BootOrderভেরিয়েবল বলে কোন entry আগে: এখানেBoot0001(“ubuntu”), তারপরBoot0000(“Windows Boot Manager”). প্রতিটি entry-তে লেখা কোন ডিস্ক, কোন partition, কোন ফাইল। - ESP থেকে প্রথম .efi. Firmware GPT পড়ে ESP খুঁজে FAT32 থেকে
shimx64.efiখোলে। Secure Boot চালু থাকলে ফাইলটির ডিজিটাল স্বাক্ষর firmware-এর অনুমোদিত তালিকার (db) সাথে মেলানো হয়; না মিললে চালানো হয় না। Windows হলে এই জায়গায় থাকতbootmgfw.efi. - GRUB. shim নিজের ভেতরের distro key দিয়ে
grubx64.efiযাচাই করে চালায়। GRUB কনফিগ পড়ে মেনু দেখায়, kernel আর initrd আনে — kernel-এর স্বাক্ষরও যাচাই হয়। (systemd-boot হলে এই ধাপটি আরও সরল; Windows-এ এখানেwinload.efi.) - হাত বদল। Kernel (Linux-এ “EFI stub”-সহ) firmware থেকে memory map নেয়, তারপর
ExitBootServices()ডাকে। এরপর firmware-এর driver আর বুট-সেবা বন্ধ; থাকে শুধু অল্প কিছু “runtime service” — যেমন NVRAM ভেরিয়েবল পড়া-লেখা আর ঘড়ি। এখন থেকে হার্ডওয়্যারের পুরো নিয়ন্ত্রণ OS-এর।
Linux-এ boot entry দেখার কমান্ড efibootmgr (root লাগে, তাই এখানে চালানো যাবে না)। নিচে একটি dual-boot ল্যাপটপের নমুনা আউটপুট, সংক্ষিপ্ত করা:
$ sudo efibootmgr
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0001,0000,0002
Boot0000* Windows Boot Manager HD(1,GPT,...)/\EFI\Microsoft\Boot\bootmgfw.efi
Boot0001* ubuntu HD(1,GPT,...)/\EFI\ubuntu\shimx64.efi
Boot0002* UEFI: USB Flash Disk PciRoot(0x0)/Pci(0x14,0x0)/USB(...)
| বিষয় | BIOS + MBR | UEFI + GPT |
|---|---|---|
| শুরুর বছর | ১৯৮১ (IBM PC) | EFI ১৯৯০-এর শেষে; UEFI Forum ২০০৫ |
| Firmware-এর CPU mode | ১৬-bit real mode | 32/64-bit |
| Bootloader কোথায় | LBA 0-এর ৪৪৬ বাইট + পরের সেক্টর | ESP-তে একটি .efi ফাইল |
| File system বোঝে? | না | হ্যাঁ, অন্তত FAT |
| Partition সংখ্যা | ৪টি primary (বেশি হলে extended + logical) | ডিফল্টে ১২৮টি entry |
| সর্বোচ্চ ডিস্ক (৫১২-বাইট সেক্টর) | ২৩২ × ৫১২ B = ২ TiB | ২৬৪ × ৫১২ B = ৮ ZiB (বাস্তবে অসীম) |
| Partition-এর পরিচয় | ১ বাইটের type (0x83) | ১২৮-bit type GUID + নিজস্ব GUID |
| নির্ভরযোগ্যতা | একটিই কপি, checksum নেই | CRC32 + ডিস্কের শেষে backup |
| বুট-ক্রম কোথায় | CMOS সেটিং (কোন ডিস্ক) | NVRAM boot entry (কোন ফাইল) |
| Secure Boot | নেই | আছে |
BIOS/UEFI আর MBR/GPT দুটি আলাদা প্রশ্ন, যদিও সাধারণত জোড়ায় দেখা যায়। BIOS দিয়ে GPT ডিস্ক বুট করা যায় (GRUB-এর জন্য ছোট একটি “BIOS boot partition” লাগে), আর অনেক UEFI firmware MBR ডিস্কও বুট করে। তবে Windows-এর নিয়ম কড়া: UEFI মোডে Windows শুধু GPT ডিস্কে, BIOS মোডে শুধু MBR ডিস্কে ইনস্টল হয়। Windows 11 ইনস্টলের শর্তেই UEFI আর Secure Boot-সক্ষম firmware আছে।
৪ · Secure Boot — বিশ্বাসের শিকল
বুটের সময় যে কোড চলে, সেটি OS-এর আগে চলে — antivirus, firewall, এমনকি kernel-এর সব সুরক্ষা তখনো জন্মায়নি। তাই কোনো ক্ষতিকর প্রোগ্রাম যদি bootloader-এর জায়গা দখল করতে পারে (একে বলে bootkit), সে OS-এর নিচে বসে থাকে, আর OS তাকে সহজে দেখতেই পায় না। Secure Boot এই ঝুঁকি কমানোর জন্য UEFI-র একটি বৈশিষ্ট্য।
নীতিটি সরল: প্রতিটি ধাপ পরেরটিকে চালানোর আগে তার ডিজিটাল স্বাক্ষর যাচাই করে। Firmware-এর NVRAM-এ কয়েকটি key-তালিকা থাকে: PK (Platform Key — মালিক, সাধারণত PC নির্মাতা), KEK (যারা তালিকা হালনাগাদ করতে পারে), db (অনুমোদিত স্বাক্ষর বা hash) আর dbx (বাতিল — পরে দুর্বল প্রমাণিত হয়েছে এমন bootloader). Firmware কেবল সেই .efi চালায়, যার স্বাক্ষর db-তে আছে আর dbx-এ নেই। এভাবে firmware → shim → GRUB → kernel → kernel module পর্যন্ত একটি chain of trust তৈরি হয়।
ঢাকার একটি অফিসের দারোয়ানের কথা ভাবুন। তিনি সবাইকে চেনেন না, কিন্তু কোম্পানির আইডি কার্ড চেনেন। কার্ডে সঠিক সিল থাকলে ঢুকতে দেন, আর “বাতিল কার্ডের তালিকা”-য় নাম থাকলে আটকান। ভেতরে রিসেপশনিস্ট আবার দেখেন অতিথির নাম আজকের তালিকায় আছে কি না। প্রত্যেক ধাপের লোক শুধু পরের জনকে যাচাই করেন — কিন্তু শিকলটি মিলে পুরো ভবন সুরক্ষিত। Secure Boot-এ db হলো সিলের তালিকা, dbx বাতিল কার্ডের তালিকা।
Linux distro-গুলো কীভাবে এতে ঢুকল? বেশিরভাগ PC-র firmware-এ নির্মাতারা Microsoft-এর key বসিয়ে বিক্রি করেন। তাই Ubuntu, Fedora, Debian-এর মতো distro একটি ছোট প্রথম-ধাপ bootloader ব্যবহার করে — shim — যেটি Microsoft-এর UEFI CA দিয়ে স্বাক্ষরিত, আর ভেতরে distro-র নিজের key রাখে। shim সেই key দিয়ে GRUB আর kernel যাচাই করে। নিজের বানানো kernel module চালাতে চাইলে ব্যবহারকারী নিজের key “enroll” করতে পারেন (MOK, Machine Owner Key).
নিজের কম্পিউটারে Secure Boot চালু আছে কি না দেখার নিরাপদ উপায় (কোনো কিছু বদলায় না):
$ mokutil --sb-state
SecureBoot enabled
$ [ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
UEFIWin + R চেপে msinfo32 লিখুন — “BIOS Mode: UEFI” আর “Secure Boot State: On” দেখাবে। অথবা Administrator হিসেবে PowerShell খুলে:
PS C:\> Confirm-SecureBootUEFI
TrueApple silicon Mac-এ Secure Boot সবসময় চালু, আর নিরাপত্তা-স্তর (Full, Reduced বা Permissive) বদলানো যায় শুধু recoveryOS-এর Startup Security Utility থেকে। এই পর্বের নীতি সেখানেও একই — Boot ROM থেকে শুরু হওয়া স্বাক্ষর-যাচাইয়ের শিকল।
Secure Boot সব কিছু থেকে রক্ষা করে না। এটি শুধু নিশ্চিত করে যে বুটের সময় স্বাক্ষরিত কোডই চলছে; স্বাক্ষরিত কোডে বাগ থাকলে সমস্যা থেকে যায়। ২০২০ সালের “BootHole” (GRUB 2-এর একটি ত্রুটি) বা ২০২৩ সালে প্রকাশ্যে আসা BlackLotus bootkit-এর পর প্রতিরক্ষা ছিল একই: firmware আর OS হালনাগাদ রাখা, যাতে dbx-এ পুরোনো দুর্বল bootloader বাতিল হয়। তাই কোনো গাইড বা AI “সমস্যা মেটাতে Secure Boot স্থায়ীভাবে বন্ধ করুন” বললে আগে বিকল্প খুঁজুন — যেমন signed driver বা নিজের MOK key. Key ব্যবস্থাপনা, measured boot আর sandbox-এর বিস্তারিত পর্ব ৪৯-এ।
৫ · Bootloader — GRUB 2, systemd-boot আর Windows Boot Manager
Bootloader-এর কাজ তিনটি: (১) OS-এর kernel ফাইল খুঁজে RAM-এ আনা, (২) kernel-কে দরকারি তথ্য দেওয়া (command line, memory map, initramfs কোথায়), (৩) একাধিক OS বা একাধিক kernel থাকলে বাছাইয়ের সুযোগ দেওয়া। এরপর সে kernel-এ লাফ দিয়ে নিজে বিদায় নেয়। তিনটি বহুল-ব্যবহৃত bootloader পাশাপাশি দেখুন:
🧭 GRUB 2
GNU-র bootloader, বেশিরভাগ Linux distro-র ডিফল্ট। BIOS আর UEFI দুটোতেই চলে, বহু file system, LVM, RAID, এমনকি এনক্রিপ্ট-করা /boot পড়তে পারে, নিজস্ব ছোট shell আছে। কনফিগ /boot/grub/grub.cfg হাতে লেখা হয় না — /etc/default/grub বদলে একটি কমান্ড দিয়ে তৈরি করা হয়।
⚙️ systemd-boot
শুধু UEFI-র জন্য, আগের নাম gummiboot. খুব সরল: ESP-তে /loader/entries/ ফোল্ডারে প্রতিটি OS-এর জন্য একটি ছোট টেক্সট ফাইল। নিজে file system driver বহন করে না — kernel আর initramfs ESP-তেই রাখতে হয়। Arch Linux আর কিছু distro-তে জনপ্রিয়।
🪟 Windows Boot Manager
UEFI-তে bootmgfw.efi, BIOS-এ bootmgr. বুট-সেটিং থাকে BCD (Boot Configuration Data) নামের একটি ডেটাবেসে, যা bcdedit দিয়ে দেখা যায়। এরপর winload.efi চলে, যে ntoskrnl.exe (kernel), HAL আর বুটের সময় লাগে এমন driver মেমরিতে আনে।
GRUB-এর মেনুর একটি entry আসলে কয়েকটি কমান্ডের তালিকা। grub.cfg-এর একটি সরলীকৃত অংশ:
menuentry 'Ubuntu' {
search --no-floppy --fs-uuid --set=root 25a980c0-... # কোন partition
linux /boot/vmlinuz-6.8.0-137-generic root=UUID=25a980c0-... ro quiet splash
initrd /boot/initrd.img-6.8.0-137-generic
}linux লাইনটি kernel ফাইল দেখায় আর তার পরের সব শব্দ হয়ে যায় kernel command line; initrd লাইনটি initramfs দেখায়। কনফিগ বদলানোর নিয়ম distro-ভেদে ভিন্ন — এটি AI প্রায়ই গুলিয়ে ফেলে:
| Distro পরিবার | যে ফাইল বদলাবেন | তারপর যে কমান্ড |
|---|---|---|
| Debian, Ubuntu, Mint | /etc/default/grub | sudo update-grub |
| Fedora, RHEL (নতুন সংস্করণ) | /etc/default/grub | sudo grub2-mkconfig -o /boot/grub2/grub.cfg |
| Arch | /etc/default/grub | sudo grub-mkconfig -o /boot/grub/grub.cfg |
৬ · Kernel জেগে ওঠে — decompress, memory, hardware আর root mount
Bootloader লাফ দেওয়ার মুহূর্তে kernel একটি সংকুচিত ফাইল — vmlinuz-এর “z” সেই সংকোচনের ইঙ্গিত। প্রথম কয়েকশো নির্দেশ একটি ছোট decompressor, যে kernel-এর বাকি অংশ RAM-এ খুলে সেখানে লাফ দেয়। তারপর kernel-এর আসল প্রথম C ফাংশন start_kernel() চলে। মোটা দাগে kernel এই কাজগুলো করে:
- CPU আর মেমরি সাজানো: firmware-এর দেওয়া memory map (BIOS-এ “e820” তালিকা, UEFI-তে EFI memory map) দেখে কোন RAM ব্যবহারযোগ্য বোঝে, নিজের page table তৈরি করে virtual memory চালু করে (মডিউল ৫-এ বিস্তারিত), memory allocator প্রস্তুত করে।
- Interrupt, timer আর scheduler: interrupt table বসায় (পর্ব ৪), ঘড়ি চালু করে, scheduler প্রস্তুত করে — এখন থেকে একাধিক কাজ পালাক্রমে চলতে পারবে।
- হার্ডওয়্যার খোঁজা: x86 PC-তে firmware-এর ACPI টেবিল, আর অনেক ARM বোর্ডে bootloader-এর দেওয়া device tree বলে দেয় কোথায় কোন যন্ত্র আছে। Kernel PCI, USB ইত্যাদি bus স্ক্যান করে আর ভেতরে-জোড়া driver চালু করে।
- প্রথম দুই প্রসেস: kernel নিজের ভেতরে দুটি কাজ তৈরি করে — PID 1 (যে পরে init হবে) আর PID 2 (
kthreadd, kernel-এর নিজস্ব thread-গুলোর জনক)। - Root file system মাউন্ট: command line-এর
root=UUID=…অনুযায়ী আসল ডিস্কের partition খুঁজে/হিসেবে জোড়া, তারপর সেখান থেকে/sbin/initচালানো।
শেষ ধাপে একটি ডিম-মুরগি সমস্যা আছে। Root partition হয়তো একটি NVMe SSD-তে, LVM-এর ভেতরে, LUKS দিয়ে এনক্রিপ্ট করা। এটি পড়তে লাগবে NVMe driver, LVM tool আর পাসওয়ার্ড চাওয়ার প্রোগ্রাম। কিন্তু এগুলো তো root partition-এর ভেতরেই রাখা! সব driver kernel-এর ভেতরে জুড়ে দিলে kernel বিশাল হয়ে যেত — তাই distro-গুলো driver-কে module হিসেবে রাখে (পর্ব ৬)।
সমাধান initramfs (initial RAM file system): একটি ছোট সংকুচিত আর্কাইভ (cpio ফরম্যাট), যেটি bootloader kernel-এর সাথেই RAM-এ এনে রাখে। Kernel এটিকে মেমরিতে একটি অস্থায়ী / হিসেবে খুলে তার /init চালায়। এই ছোট জগৎ দরকারি module লোড করে, দরকার হলে ডিস্কের পাসওয়ার্ড চায়, আসল root খুঁজে মাউন্ট করে, তারপর switch_root করে — অস্থায়ী জগৎ মুছে আসল ডিস্কের /sbin/init-কে PID 1 হিসেবে চালায়। পুরোনো পদ্ধতির নাম ছিল initrd (একটি RAM-ডিস্ক image); নাম রয়ে গেছে, তাই ফাইলের নাম এখনো প্রায়ই initrd.img.
নতুন বাসায় ওঠার দিনটির কথা ভাবুন। আসবাবপত্র সব ট্রাকে, বাক্সে বাঁধা। প্রথম রাতের জন্য একটি ছোট ব্যাগে রাখেন টর্চ, স্ক্রু-ড্রাইভার, চাবি আর বিছানার চাদর — যাতে বাকি বাক্সগুলো খোলা যায়। initramfs ঠিক এই “প্রথম রাতের ব্যাগ”। বাসা গোছানো হয়ে গেলে ব্যাগটি আর লাগে না।
এবার একটি চলমান Linux-এর kernel নিজের বুট সম্পর্কে কী বলে, দেখি। নিচের কোড এই পাতার Linux কন্টেইনারে চলে:
cat /proc/uptime
read up idle < /proc/uptime
secs=${up%.*}
echo "kernel up for: $((secs / 3600)) h $((secs % 3600 / 60)) min, CPUs: $(nproc)"
if [ -d /sys/firmware/efi ]; then echo "firmware: UEFI"; else echo "firmware: BIOS (or hidden)"; fi
echo "--- kernel command line ---"
if ! cat /proc/cmdline 2>/dev/null; then
echo "(hidden inside this container)"
fiএকটি আসল রানের আউটপুট (সংখ্যা প্রতিবার আলাদা হবে):
6906866.88 9897034.33
kernel up for: 1918 h 34 min, CPUs: 2
firmware: BIOS (or hidden)
--- kernel command line ---
BOOT_IMAGE=/boot/vmlinuz-6.8.0-137-generic root=UUID=25a980c0-526d-4f97-9b82-d579b9ea2532 ro consoleblank=0 mpt3sas.max_queue_depth=1000 vultr ds=vultr console=ttyS0,115200n8 console=tty0
/proc/uptime-এর প্রথম সংখ্যা kernel বুটের পর কত সেকেন্ড, দ্বিতীয়টি সব CPU মিলিয়ে কত সেকেন্ড অলস ছিল — ২টি CPU বলে দ্বিতীয়টি প্রথমটির চেয়ে বড় হতে পারে। প্রায় ১৯১৮ ঘণ্টা মানে ৮০ দিনের মতো — অথচ আপনার কোড চলেছে এইমাত্র তৈরি একটি কন্টেইনারে! কারণ কন্টেইনার নিজের kernel বুট করে না, host-এর kernel ভাগ করে নেয়; তাই uptime আর command line দুটোই host সার্ভারের। Command line-এ GRUB-এর রেখে যাওয়া BOOT_IMAGE=, root partition-এর root=UUID= আর ro (প্রথমে শুধু-পড়া অবস্থায় মাউন্ট; পরে init সেটিকে লেখার জন্য খোলে) দেখা যাচ্ছে। /sys/firmware/efi এখানে দেখা যায়নি — হয় host BIOS মোডে বুট হয়েছে, নয় কন্টেইনার থেকে লুকানো; নিজের Linux মেশিনে এই লাইনটিই UEFI কি না বলে দেয়।
Kernel যদি root খুঁজেই না পায় — যেমন initramfs নেই বা দরকারি driver নেই — তাহলে বিখ্যাত বার্তাটি আসে: Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0). Kernel panic মানে kernel এমন অবস্থায় পৌঁছেছে যেখান থেকে নিরাপদে চলা সম্ভব নয়, তাই সে থেমে যায়। এই বার্তা দেখলে সন্দেহের তালিকায় প্রথমে থাকে ভুল root= আর অসম্পূর্ণ initramfs.
৭ · PID 1 — SysV init থেকে systemd
Kernel-এর শেষ কাজ user space-এ প্রথম প্রোগ্রামটি চালানো। Linux kernel প্রথমে initramfs-এর /init, তারপর command line-এর init=, তারপর /sbin/init, /etc/init, /bin/init আর শেষ চেষ্টা হিসেবে /bin/sh খোঁজে; কোনোটিই না পেলে panic. এই প্রোগ্রামটির প্রসেস নম্বর (PID) সবসময় ১, আর একে বলে init. এর তিনটি বিশেষ দায়িত্ব: বাকি সব সার্ভিস চালু করা, যে প্রসেসের বাবা-মা মারা গেছে তাদের দত্তক নিয়ে শেষ অবস্থা “সংগ্রহ” করা (zombie পরিষ্কার — পর্ব ১০), আর shutdown-এ সবাইকে গুছিয়ে বন্ধ করা। PID 1 নিজে মারা গেলে Linux kernel panic করে — পুরো সিস্টেমের ভিত্তি এটি।
তিন প্রজন্মের init
| init | কাল | কীভাবে চালু করে | মূল ধারণা |
|---|---|---|---|
| SysV init | ১৯৮০-এর দশক থেকে (Unix System V) | /etc/rc.d/-এর shell script, একটির পর একটি | Runlevel ০–৬ (যেমন ৩ = টেক্সট মাল্টি-ইউজার, ৫ = গ্রাফিক্যাল, ৬ = reboot) |
| Upstart | ২০০৬ সালে Ubuntu-তে; ২০১৫ সালে Ubuntu systemd-তে যায় | Event-ভিত্তিক: “ডিস্ক এলো”, “নেটওয়ার্ক এলো” ঘটনায় কাজ | অপেক্ষার বদলে ঘটনায় সাড়া |
| systemd | ২০১০ (Lennart Poettering ও Kay Sievers); ২০১১ সালে Fedora 15-এ ডিফল্ট, পরে প্রায় সব বড় distro | Declarative unit ফাইল; dependency গ্রাফ মেনে সমান্তরালে | Target, socket activation, cgroup দিয়ে সার্ভিস নজরদারি |
systemd-এ প্রতিটি সার্ভিস, mount, socket, timer হলো একটি unit — একটি ছোট টেক্সট ফাইল। একগুচ্ছ unit-কে একসাথে নাম দেওয়া যায়, যাকে বলে target: sysinit.target (মৌলিক প্রস্তুতি), basic.target, multi-user.target (পুরোনো runlevel ৩-এর মতো), graphical.target (runlevel ৫-এর মতো), rescue.target আর emergency.target (মেরামতের জন্য)। একটি সার্ভিসের unit ফাইল এমন দেখায়:
[Unit]
Description=OpenBSD Secure Shell server
After=network.target # ক্রম: network.target-এর পরে চালু হবে
[Service]
ExecStart=/usr/sbin/sshd -D
Restart=on-failure # মরে গেলে আবার চালানো হবে
[Install]
WantedBy=multi-user.target # multi-user.target চাইলে এটিও চালু হবেsystemd-এ দুটি সম্পর্ক আলাদা: প্রয়োজন (Wants=, Requires= — “এটি চালু হলে ওটিও চালু হবে”) আর ক্রম (After=, Before= — “দুটোই চালু হলে আগে ওটি”)। শুধু Requires= দিলে দুটি একসাথে শুরু হতে পারে; শুধু After= দিলে অন্যটি আদৌ চালু না-ও হতে পারে। যা ক্রমে বাঁধা নেই, systemd সেগুলো সমান্তরালে চালায় — গতির রহস্য এটাই।
নিচে একটি ছোট সার্ভার বুটের সরলীকৃত চিত্র — প্রতিটি সার্ভিস কত মিলিসেকেন্ড নেয় তা কাল্পনিক, কিন্তু ক্রমের নিয়ম আসল systemd-এর মতো:
| সময় (ms) | |
| চলছে | |
| পৌঁছানো target |
- লক্ষ্য ঠিক করা। PID 1 হিসেবে systemd চালু হলো।
default.target(এখানেmulti-user.target) থেকে শুরু করেWants/Requiresধরে কোন কোন unit লাগবে তার তালিকা আরAfterধরে ক্রমের গ্রাফ বানাল। এখনো কিছু চালু হয়নি। - প্রথম ঢেউ, সমান্তরালে। journald (লগ) আর udevd (ডিভাইস) কারও পরে চালু হওয়ার শর্ত নেই — দুটোই সময় ০-তে শুরু। journald শেষ ৪০ ms-এ, udevd ১২০ ms-এ।
- Target পার হওয়া। udevd প্রস্তুত (১২০ ms) হওয়ায়
local-fs.targetপূর্ণ; journald আগেই শেষ, তাইsysinit.target, তারপরbasic.target— সবই ১২০ ms-এ। Target নিজে কোনো কাজ করে না, সে শুধু একটি “মাইলফলক”, তাই সময় নেয় ০. - দ্বিতীয় ঢেউ। basic.target-এর পরের তিনটি সার্ভিস একসাথে শুরু ১২০ ms-এ। getty শেষ ১৩০ ms-এ — tty1-এ
login:লেখা চলে এসেছে, যদিও নেটওয়ার্ক এখনো আসেনি! cron শেষ ১৪০ ms-এ। - নেটওয়ার্ক। NetworkManager-এর ৩০০ ms লাগল: ১২০ + ৩০০ = ৪২০ ms-এ শেষ, সাথে সাথে
network.target. এবারAfter=network.targetলেখা sshd শুরু হতে পারে। - লক্ষ্যে পৌঁছানো। sshd ৪২০ + ৬০ = ৪৮০ ms-এ প্রস্তুত, আর তিনটি শর্ত পূর্ণ হওয়ায়
multi-user.targetপৌঁছাল ৪৮০ ms-এ। সব সার্ভিস একটির পর একটি চালালে লাগত ৪০ + ১২০ + ৩০০ + ২০ + ১০ + ৬০ = ৫৫০ ms. বুটের সময় ঠিক করে সবচেয়ে লম্বা নির্ভরতার পথ — udevd → NetworkManager → sshd (১২০ + ৩০০ + ৬০) — যাকে বলে critical chain.
এই হিসাবটি একটি ছোট সিমুলেটরে চালিয়ে দেখুন। কোডটি unit-গুলোকে dependency-র “ঢেউ” অনুযায়ী সাজায় (গ্রাফের ভাষায় topological sort), আর প্রতিটি unit-এর শেষ সময় = তার সবচেয়ে দেরিতে শেষ হওয়া dependency + নিজের সময়:
// unit: [time it takes in ms, units it must start After]
const units = {
'systemd-journald.service': [40, []],
'systemd-udevd.service': [120, []],
'local-fs.target': [0, ['systemd-udevd.service']],
'sysinit.target': [0, ['local-fs.target', 'systemd-journald.service']],
'basic.target': [0, ['sysinit.target']],
'NetworkManager.service': [300, ['basic.target']],
'network.target': [0, ['NetworkManager.service']],
'sshd.service': [60, ['network.target']],
'cron.service': [20, ['basic.target']],
'getty@tty1.service': [10, ['basic.target']],
'multi-user.target': [0, ['sshd.service', 'cron.service', 'getty@tty1.service']],
};
const done = {}, from = {}; // finish time, slowest dependency
let wave = 0;
while (Object.keys(done).length < Object.keys(units).length) {
const ready = Object.keys(units).filter(u => !(u in done) &&
units[u][1].every(d => d in done)).sort();
if (ready.length === 0) { console.log('ordering cycle!'); break; }
const fin = {};
for (const u of ready) {
const deps = units[u][1];
from[u] = deps.reduce((a, d) => (a === null || done[d] > done[a] ? d : a), null);
fin[u] = (from[u] ? done[from[u]] : 0) + units[u][0];
}
Object.assign(done, fin);
console.log(`wave ${++wave}: ` + ready.map(u => `${u} (done @${fin[u]}ms)`).join(', '));
}
const chain = [];
for (let u = 'multi-user.target'; u; u = from[u]) chain.unshift(`${u} @${done[u]}ms`);
console.log('critical chain: ' + chain.join(' -> '));আসল আউটপুট:
wave 1: systemd-journald.service (done @40ms), systemd-udevd.service (done @120ms)
wave 2: local-fs.target (done @120ms)
wave 3: sysinit.target (done @120ms)
wave 4: basic.target (done @120ms)
wave 5: NetworkManager.service (done @420ms), cron.service (done @140ms), getty@tty1.service (done @130ms)
wave 6: network.target (done @420ms)
wave 7: sshd.service (done @480ms)
wave 8: multi-user.target (done @480ms)
critical chain: systemd-udevd.service @120ms -> local-fs.target @120ms -> sysinit.target @120ms -> basic.target @120ms -> NetworkManager.service @420ms -> network.target @420ms -> sshd.service @480ms -> multi-user.target @480ms
“wave” মানে dependency-র গভীরতা; সময়গুলো কিন্তু ঢেউয়ের হিসাবে নয়, প্রতিটি unit-এর নিজের dependency শেষ হওয়ার সময় থেকে — আসল systemd-ও একটি কাজ তার শর্ত পূরণ হলেই শুরু করে। ফল ডায়াগ্রামের সাথে হুবহু মেলে: ৪৮০ ms, critical chain udevd → NetworkManager → sshd. পরীক্ষা হিসেবে 'cron.service'-এর তালিকায় 'multi-user.target' যোগ করে দেখুন — চক্র (cycle) তৈরি হবে, আর সিমুলেটর “ordering cycle!” বলবে। আসল systemd এমন হলে চক্রের একটি unit বাদ দিয়ে লগে সতর্কবার্তা লেখে।
এই পাতার কন্টেইনারে PID 1 কে?
echo "PID 1 is: $(ps -p 1 -o comm=)"
echo "This shell: PID $$, parent PID $PPID"
echo "--- every process in this container ---"
ps -e -o pid,ppid,comm
echo "--- kernel ---"
uname -srএকটি আসল রানের আউটপুট:
PID 1 is: podman-init
This shell: PID 2, parent PID 1
--- every process in this container ---
PID PPID COMMAND
1 0 podman-init
2 1 bash
4 2 ps
--- kernel ---
Linux 6.8.0-137-generic
আপনার ল্যাপটপের Linux-এ উত্তর হতো systemd, আর তালিকায় থাকত শত শত প্রসেস। এখানে পুরো জগতে মাত্র তিনটি প্রসেস! PID 1 হলো podman-init — Podman কন্টেইনার চালু করার সময় যে ছোট init প্রোগ্রাম বসায় (সাধারণত catatonit). এর কাজ শুধু আমাদের bash চালানো, signal পৌঁছে দেওয়া আর zombie পরিষ্কার করা। কোনো firmware, bootloader বা systemd এখানে চলেনি — কন্টেইনার পুরো OS বুট করে না; host kernel একটি আলাদা “PID namespace” তৈরি করে, যার ভেতরে প্রথম প্রসেসটি নিজেকে PID 1 দেখে। ps-এর PID ৩ না হয়ে ৪ হওয়ার মতো খুঁটিনাটি রানভেদে বদলাতে পারে। Namespace আর cgroup দিয়ে কন্টেইনার কীভাবে তৈরি হয়, পর্ব ৫১-এ দেখবেন।
অন্য OS-এ PID 1-এর কাজ কে করে
Windows-এ “PID 1” নামে কিছু নেই, কিন্তু শিকলটি একই রকম। ntoskrnl.exe নিজের ভেতরের “System” প্রসেস (সাধারণত PID 4) চালু করে, তারপর প্রথম user-mode প্রসেস smss.exe (Session Manager). smss session 0-এর জন্য csrss.exe আর wininit.exe চালায়; wininit চালায় services.exe (Service Control Manager — systemd-এর মতো সার্ভিস চালু করে) আর lsass.exe (লগইন যাচাই)। ব্যবহারকারীর session-এর জন্য আরেকটি csrss আর winlogon.exe, যে লগইন স্ক্রিন দেখায়; সফল লগইনের পর userinit.exe হয়ে explorer.exe — আপনার ডেস্কটপ আর টাস্কবার। বিস্তারিত পর্ব ৫৬-এ।
macOS-এ PID 1 হলো launchd (২০০৫ সালে Mac OS X 10.4-এ আসে)। এটি একাই init, সার্ভিস ম্যানেজার আর cron-এর কাজ করে; সার্ভিসের বিবরণ থাকে .plist ফাইলে। launchd-এর “socket activation” — সার্ভিস আগে চালু না করে তার socket খুলে রাখা, প্রথম অনুরোধ এলে তবেই চালু — systemd-এর নকশাকে সরাসরি অনুপ্রাণিত করেছিল। Apple silicon Mac-এ শিকলটি: Boot ROM → iBoot → XNU kernel → launchd → loginwindow.
Target-এ পৌঁছানোর পর login. টেক্সট কনসোলে agetty “login:” লেখে, login প্রোগ্রাম PAM দিয়ে পাসওয়ার্ড যাচাই করে আপনার shell চালায়। গ্রাফিক্যাল ডেস্কটপে একটি display manager (GDM, SDDM, LightDM) লগইন স্ক্রিন দেখায়; সফল হলে systemd-logind আপনার session হিসাব রাখে, আর আপনার নিজের একটি systemd --user প্রসেস ব্যবহারকারী-স্তরের সার্ভিস চালায়। এখান থেকেই আপনার প্রতিটি অ্যাপ জন্ম নেয় — মডিউল ২-এর বিষয়।
৮ · মোবাইল ফোনের বুট আর dual boot
আপনার Android ফোনেও একই রিলে দৌড়, শুধু দৌড়বিদদের নাম আলাদা। চিপের ভেতরে স্থায়ীভাবে লেখা Boot ROM প্রথমে চলে, যেটি কারখানার পরে আর বদলানো যায় না। সে নির্মাতার স্বাক্ষরিত bootloader যাচাই করে চালায়; bootloader boot partition থেকে Linux kernel আর ramdisk আনে; kernel চালায় Android-এর নিজস্ব init, যে init.rc পড়ে সার্ভিস চালু করে, তার মধ্যে zygote — যার থেকে প্রতিটি অ্যাপের প্রসেস জন্মায়।
নিরাপত্তার কেন্দ্রে Android Verified Boot (AVB): প্রতিটি partition-এর hash একটি স্বাক্ষরিত তালিকায় (vbmeta) থাকে, আর বিশাল system partition-এর প্রতিটি block পড়ার সময়ই যাচাই হয় dm-verity দিয়ে। Rollback protection পুরোনো, দুর্বল সংস্করণে ফিরে যাওয়া আটকায়। Bootloader “unlock” করলে (কাস্টম ROM বসানোর জন্য) ফোন বুটের সময় সতর্কবার্তা দেখায় আর নিরাপত্তার জন্য ডেটা মুছে দেয়। iPhone-এও শিকল একই ধাঁচের: Boot ROM → iBoot → kernel, প্রতিটি ধাপ Apple-এর স্বাক্ষর যাচাই করে। মোবাইল OS-এর বাকি গল্প পর্ব ৫৪-এ।
Dual boot — এক কম্পিউটারে দুই OS
অনেক শিক্ষার্থী একই ল্যাপটপে Windows আর Ubuntu রাখেন। UEFI-তে এটি তুলনামূলক সহজ: দুই OS-এর bootloader একই ESP-তে পাশাপাশি দুটি ফোল্ডারে থাকে, আর NVRAM-এ দুটি boot entry. সাধারণত GRUB মেনুতে Windows-এর entry-ও থাকে (GRUB শুধু bootmgfw.efi-কে চালিয়ে দেয় — একে বলে chainloading). কিছু পরিচিত সতর্কতা:
- দুই OS একই মোডে: একটি UEFI আর অন্যটি Legacy/CSM মোডে ইনস্টল করলে একটি থেকে অন্যটির মেনু দেখা যায় না।
- সাধারণত আগে Windows, পরে Linux: Windows ইনস্টলার অন্য OS-এর মেনু যোগ করে না, আর বড় Windows আপডেট কখনো কখনো BootOrder-এ নিজেকে প্রথমে বসায়। তখন firmware সেটিং বা
efibootmgrদিয়ে ক্রম ঠিক করতে হয় — কোনো partition মোছার দরকার নেই। - Fast Startup: Windows-এর “Fast Startup” আসলে আংশিক hibernation — বন্ধ করার সময় kernel-এর অবস্থা ডিস্কে লিখে রাখে, আর Windows partition “ব্যবহারে আছে” অবস্থায় থাকে। তখন Linux থেকে সেই partition-এ লেখা ঝুঁকিপূর্ণ; dual boot-এ এটি বন্ধ রাখাই প্রচলিত পরামর্শ।
- ঘড়ি: Windows ডিফল্টে hardware clock-কে স্থানীয় সময় ধরে, Linux ধরে UTC — তাই OS বদলালে ঘড়ি ৬ ঘণ্টা এদিক-ওদিক দেখাতে পারে (বাংলাদেশ UTC+6). একটি OS-এর সেটিং বদলে দুটিকে মেলাতে হয়।
৯ · বুট কেন ব্যর্থ হয় — recovery আর বুট-সময় মাপা
বুট একটি শিকল, তাই যেকোনো কড়া ভাঙলে থেমে যায়। ভালো খবর হলো, কোথায় থেমেছে দেখলেই বোঝা যায় কোন কড়া ভেঙেছে — ঠিক যেমন compiler-এর error দেখে বোঝা যায় কোন ধাপের সমস্যা।
| যা দেখছেন | কোন ধাপ | সম্ভাব্য কারণ |
|---|---|---|
| পাখা ঘোরে, স্ক্রিন কালো, বিপ | Firmware / POST | RAM ঠিকমতো বসেনি, হার্ডওয়্যার ত্রুটি |
No bootable device / Operating System not found | Firmware → bootloader | ভুল বুট-ক্রম, MBR/ESP নষ্ট, ডিস্ক চেনা যাচ্ছে না |
grub rescue> | GRUB | GRUB তার ফাইল খুঁজে পাচ্ছে না — partition সরানো বা মোছা হয়েছে |
Secure Boot Violation | Firmware যাচাই | স্বাক্ষরবিহীন বা বাতিল bootloader |
Kernel panic … Unable to mount root fs | Kernel / initramfs | ভুল root=, initramfs-এ driver নেই |
| “You are in emergency mode” | systemd | /etc/fstab-এ ভুল লাইন, একটি ডিস্ক মাউন্ট হচ্ছে না |
| Windows: “Automatic Repair” লুপ | bootmgr / winload / driver | BCD নষ্ট, ত্রুটিপূর্ণ driver বা আপডেট |
Recovery-র ধারণা: প্রতিটি সিস্টেমে মেরামতের একটি “বিকল্প পথ” থাকে, যা ভাঙা কড়াটি এড়িয়ে চলে। Linux-এ GRUB মেনুর “Advanced options”-এ পুরোনো kernel বা recovery mode; grub rescue>-এ সীমিত কমান্ড দিয়ে GRUB-কে তার ফাইলের ঠিকানা বলে দেওয়া যায়; আর সবচেয়ে নির্ভরযোগ্য পথ — একটি live USB থেকে বুট করে নিজের ডিস্ক মাউন্ট করা, তারপর bootloader আবার ইনস্টল বা initramfs আবার তৈরি করা। Windows-এ WinRE (Windows Recovery Environment) — Startup Repair, System Restore, পুরোনো আপডেট সরানো, Safe Mode — প্রায়ই নিজেই সমাধান করে; উন্নত ব্যবহারকারীরা সেখানকার command prompt থেকে bcdboot দিয়ে বুট-ফাইল আবার তৈরি করেন। সব ক্ষেত্রে প্রথম নিয়ম: কোনো কিছু লেখার আগে lsblk বা Disk Management দিয়ে নিশ্চিত হোন কোন ডিস্ক কোনটি, আর আগে ব্যাকআপ।
বুটে কত সময় লাগল — systemd-analyze
systemd বুটের প্রতিটি পর্বের সময় নিজেই মাপে। নিচে একটি ল্যাপটপের নমুনা আউটপুট (এই পাতার কন্টেইনারে systemd নেই, তাই এটি চালানো যাবে না):
$ systemd-analyze
Startup finished in 6.204s (firmware) + 2.511s (loader) + 1.873s (kernel) + 4.390s (userspace) = 14.979s
graphical.target reached after 4.352s in userspace.
$ systemd-analyze blame | head -4
2.104s NetworkManager-wait-online.service
812ms snapd.service
455ms dev-nvme0n1p2.device
301ms systemd-journal-flush.service
$ systemd-analyze critical-chain
graphical.target @4.352s
└─multi-user.target @4.350s
└─snapd.service @3.501s +812ms
└─basic.target @3.489sপ্রথম লাইনটিই পুরো পর্বের সারাংশ: firmware (POST, ডিভাইস প্রস্তুত), loader (GRUB-এর মেনু-অপেক্ষাসহ), kernel (initramfs পর্যন্ত), userspace (systemd থেকে target). blame দেখায় কে বেশি সময় নিয়েছে — কিন্তু সাবধান, যে সার্ভিস সমান্তরালে চলে সে বেশি সময় নিলেও বুট দেরি না-ও করতে পারে। আসল প্রশ্ন critical chain-এ কে আছে। প্রায়ই সবচেয়ে বড় অংশটি firmware-এর, যা OS থেকে কমানো যায় না; Windows-এ একই ধরনের তথ্য পাওয়া যায় Event Viewer-এর Diagnostics-Performance লগে। পারফরম্যান্স মাপার পদ্ধতি পর্ব ৫৭-এ।
আরও গভীরে — Secure Boot যাচাই করে, Measured Boot মাপে। Secure Boot শুধু “স্বাক্ষর মিলল কি না” দেখে চালায় বা আটকায়। Measured Boot প্রতিটি ধাপের hash একটি TPM চিপের PCR register-এ “extend” করে: PCRনতুন = SHA-256(PCRপুরোনো ‖ পরিমাপ)। এই নিয়মে register-এ কোনো মান সরাসরি বসানো যায় না, শুধু জোড়া যায় — তাই শেষ মানটি পুরো বুট-ইতিহাসের একটি আঙুলের ছাপ। BitLocker বা Linux-এর TPM-ভিত্তিক ডিস্ক-আনলক এই মান প্রত্যাশিত হলে তবেই ডিস্কের key ছাড়ে, আর দূরের সার্ভার “remote attestation”-এ এটি যাচাই করতে পারে। ছোট শিক্ষণ-OS xv6-এর পুরোনো x86 সংস্করণে পুরো BIOS-বুট মাত্র দুটি ফাইলে (bootasm.S, bootmain.c) লেখা; আজকের RISC-V সংস্করণে আলাদা bootloader-ই লাগে না — পর্ব ৫৮-এ দেখবেন।
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- বুট প্রক্রিয়ার ধাপগুলো লিখুন। — Power on → reset vector → firmware (POST) → bootloader → kernel (+ initramfs) → init/PID 1 → সার্ভিস → login.
- MBR-এর আকার আর গঠন? — ৫১২ বাইট: ৪৪৬ বাইট boot code, ৬৪ বাইট partition table (৪ × ১৬), ২ বাইট signature
0x55AA. - MBR আর GPT-র পার্থক্য? — MBR: ৪টি primary, ৩২-bit LBA-তে ২ TiB (৫১২-বাইট সেক্টর); GPT: ডিফল্টে ১২৮টি, ৬৪-bit LBA, CRC আর backup header.
- initramfs কেন লাগে? — আসল root মাউন্টের জন্য দরকারি driver, decryption আর tool সেই root-এর ভেতরেই থাকে; initramfs এগুলো RAM-এ আগেভাগে এনে দেয়।
- Linux-এ প্রথম user-space প্রসেস কোনটি? — init (আজ সাধারণত systemd), PID 1; এটি অনাথ প্রসেসের অভিভাবক, আর মারা গেলে kernel panic.
১০ · AI-এর যুগে বুট-সমস্যা — দ্রুত পরামর্শ, সাবধানে প্রয়োগ
বুট-সমস্যা মানেই চাপ — ল্যাপটপ চালু হচ্ছে না, কাল প্রেজেন্টেশন। এমন সময়ে AI-কে জিজ্ঞেস করা স্বাভাবিক, আর AI প্রায়ই কাজের কথাও বলে। কিন্তু বুটের কমান্ডগুলো ডিস্কের সবচেয়ে সংবেদনশীল অংশে লেখে; একটি ভুল ডিস্কের নাম বা ভুল মোডের কমান্ড পুরো ডেটা মুছে দিতে পারে। AI আপনার ডিস্ক দেখতে পায় না — সে জানে না আপনার মেশিন UEFI না BIOS, ডিস্ক /dev/sda না /dev/nvme0n1, distro Ubuntu না Fedora.
| AI-এর সাধারণ ভুল | কেন বিপজ্জনক | কীভাবে যাচাই করবেন |
|---|---|---|
UEFI মেশিনে BIOS-এর grub-install /dev/sda দেওয়া | ভুল target-এ bootloader, সমস্যা থেকে যায় | /sys/firmware/efi আছে কি না আগে দেখুন |
Fedora-তে update-grub (শুধু Debian/Ubuntu-র) | “command not found”, বা ভুল পথে কনফিগ | নিজের distro-র ডকুমেন্টেশন আর man পাতা |
grub.cfg সরাসরি সম্পাদনা | পরের kernel আপডেটে মুছে যায় | ফাইলের প্রথম লাইনের “DO NOT EDIT” লেখা পড়ুন |
| “Secure Boot বন্ধ করে দিন” — প্রথম সমাধান হিসেবে | নিরাপত্তার একটি স্তর স্থায়ীভাবে হারায় | signed driver বা MOK enrollment খুঁজুন |
GPT ডিস্কে bootrec /fixmbr বা ভুল ডিস্কে dd | অপ্রাসঙ্গিক, বা পুরো ডিস্ক নষ্ট | lsblk -f / Disk Management দিয়ে ডিস্ক আর partition style নিশ্চিত |
| পুরোনো তথ্য (যেমন “Ubuntu Upstart ব্যবহার করে”) | ভুল কমান্ড আর ভুল ফাইল | সংস্করণ উল্লেখ করে প্রশ্ন, তারপর অফিসিয়াল ডকুমেন্টেশন |
AI-কে প্রশ্ন করার আগে নিজের সিস্টেমের তথ্য সংগ্রহ করুন, তারপর এই কাঠামোয় জিজ্ঞেস করুন। শেষ দুটি অনুরোধ খেয়াল করুন — শুধু-পড়ার কমান্ড আগে, আর প্রতিটি লেখার কমান্ডের ঝুঁকি আলাদা করে।
AI-এর বুট-পরামর্শ প্রয়োগের আগে — চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১BIOS-এর মতো সীমিত একটি ব্যবস্থা প্রায় তিন দশক টিকে থাকল কেন, আর UEFI-তে যেতে এত সময় লাগল কেন?
উত্তরের মূলে আছে সামঞ্জস্য (compatibility)-এর অর্থনীতি। ১৯৮১ সালের IBM PC-র BIOS শুধু বুট করত না, DOS-এর মতো OS-কে কীবোর্ড, স্ক্রিন আর ডিস্ক ব্যবহারের জন্য কিছু প্রমিত সেবা (interrupt-ভিত্তিক BIOS call) দিত। ১৯৮২–৮৩ সালে Compaq-সহ কয়েকটি কোম্পানি আইনি ঝুঁকি এড়াতে “clean-room” পদ্ধতিতে — মূল কোড না দেখে শুধু আচরণের বিবরণ থেকে — নিজস্ব সামঞ্জস্যপূর্ণ BIOS লেখে। এর ফলেই “IBM-compatible” PC-র বিশাল বাজার জন্মায়। তখন থেকে প্রতিটি নতুন PC-কে পুরোনো সফটওয়্যার চালাতে পারতেই হতো, আর সেজন্যই আজকের সবচেয়ে শক্তিশালী x86 CPU-ও চালু হয় ১৯৭৮ সালের 8086-এর ১৬-bit real mode-এ।
সমস্যাগুলো জমতে থাকে: ২ TiB ডিস্ক সীমা, ৪টি partition, ১ MiB ঠিকানা-জগৎ, নির্মাতাভেদে বিভিন্ন অপ্রমিত বর্ধন। Intel ১৯৯০-এর দশকের শেষে Itanium-এর জন্য EFI আনে, কারণ সেই নতুন আর্কিটেকচারে BIOS-এর ভিত্তি (real mode) ছিলই না। ২০০৫ সালে UEFI Forum গঠন হয়, কিন্তু বাজারে ব্যাপক রূপান্তর আসে ২০১০-এর দশকে — যখন ২ TiB-এর বড় ডিস্ক সাধারণ হয়ে ওঠে আর Windows 8 (২০১২) সার্টিফায়েড PC-তে UEFI ও Secure Boot চায়।
রূপান্তর এত ধীর কেন? কারণ প্রতিটি পক্ষ অন্যের জন্য অপেক্ষা করছিল: OS বিক্রেতারা চাইছিলেন সব PC-তে UEFI থাকুক, PC নির্মাতারা চাইছিলেন OS প্রস্তুত থাকুক, আর ব্যবহারকারীরা চাইছিলেন পুরোনো tool চলুক। তাই এসেছিল CSM — UEFI-র ভেতরে BIOS-এর অনুকরণ — যা কয়েক বছর দুই জগৎকে জুড়ে রেখেছে। Intel জানিয়েছিল যে নতুন প্ল্যাটফর্মে legacy সমর্থন উঠে যাবে, আর আজকের অনেক নতুন মাদারবোর্ডে CSM নেই।
মূল উপলব্ধি: প্রযুক্তি শুধু ভালো নকশা দিয়ে জেতে না; চালু ব্যবস্থার সাথে সামঞ্জস্য, অংশীদারদের সমন্বয় আর একটি স্পষ্ট বাধ্যবাধকতার মুহূর্ত (বড় ডিস্ক, নতুন OS-এর শর্ত) লাগে। আপনার নিজের প্রজেক্টে API বা ডেটা ফরম্যাট বদলানোর সময়ও একই শিক্ষা — পুরোনো ব্যবহারকারীর জন্য একটি সেতু রাখুন, আর সেতুটি কবে সরাবেন তা আগেই জানান।
প্র ০২Secure Boot কি ব্যবহারকারীর নিরাপত্তা, নাকি কম্পিউটারের ওপর নির্মাতার নিয়ন্ত্রণ? বিতর্কটি কীভাবে মিটল?
২০১১ সালে Microsoft যখন জানাল যে Windows 8-এর লোগো পেতে PC-তে Secure Boot চালু অবস্থায় আসতে হবে, Linux সম্প্রদায়ে বড় উদ্বেগ তৈরি হয়। প্রশ্ন ছিল সরল: firmware-এ যদি শুধু Microsoft-এর key থাকে, তাহলে Linux বা নিজের বানানো OS কি আর চালানো যাবে? Free Software Foundation-সহ অনেকে আশঙ্কা করেন, “নিরাপত্তা”-র নামে কম্পিউটার তালাবদ্ধ হয়ে যাবে।
সমাধান এল কয়েক স্তরে। প্রথমত, Microsoft-এর শর্তেই x86 PC-তে ব্যবহারকারী Secure Boot বন্ধ করতে পারবেন এবং নিজের key বসাতে পারবেন (custom mode). তবে Windows RT চালানো ARM ডিভাইসে উল্টো নিয়ম ছিল — সেখানে বন্ধ করা যেত না — যা দেখায় যে প্রযুক্তিটি নিজে নিরপেক্ষ, নীতিই ঠিক করে সেটি সুরক্ষা না তালা। দ্বিতীয়ত, Linux ডেভেলপাররা (Matthew Garrett-সহ অনেকে) shim তৈরি করেন: Microsoft-এর UEFI CA দিয়ে স্বাক্ষরিত একটি ছোট loader, যা distro-র নিজের key বহন করে। ফলে Ubuntu বা Fedora কোনো সেটিং বদলানো ছাড়াই Secure Boot-সহ চলে। তৃতীয়ত, MOK-এর মাধ্যমে ব্যবহারকারী নিজের key যোগ করার ক্ষমতা পান।
তবু টানাপোড়েন রয়ে গেছে। ২০২০ সালের BootHole-এর পর বহু পুরোনো GRUB-কে dbx-এ বাতিল করতে হয়েছে, আর কিছু ক্ষেত্রে এই হালনাগাদ পুরোনো বুট মিডিয়া অচল করে দিয়েছে। স্বাক্ষর-যাচাইয়ের ব্যবস্থার শক্তি নির্ভর করে key-র মালিকের ওপর — একক কেন্দ্রের ওপর নির্ভরতা নিজেই একটি ঝুঁকি।
মূল উপলব্ধি: নিরাপত্তা প্রযুক্তি সবসময় একটি প্রশ্ন তোলে — “কে চাবি রাখে?” যে ব্যবস্থায় ব্যবহারকারী চাবি দেখতে, বদলাতে ও নিজের চাবি যোগ করতে পারেন, সেটি সুরক্ষা; যেখানে পারেন না, সেটি নিয়ন্ত্রণ। ভালো নকশা নিরাপত্তার ডিফল্ট দেয়, কিন্তু মালিককে বাদ দেয় না।
প্র ০৩systemd নিয়ে এত বিতর্ক কেন? নকশাগতভাবে এটি কী সমাধান করল, আর সমালোচকেরা কী আশঙ্কা করেন?
SysV init-এর মডেল ছিল সরল: একটি নির্দিষ্ট ক্রমে shell script চালানো। কিন্তু আধুনিক কম্পিউটারে সমস্যা দেখা দিল। USB ডিভাইস যেকোনো সময় আসে-যায়, ল্যাপটপ Wi-Fi বদলায়, CPU-তে অনেক core — তবু script-গুলো একটির পর একটি চলত, আর প্রতিটি script নিজের মতো করে PID ফাইল, লগ আর restart সামলাত। একটি সার্ভিস মরে গেলে প্রায়ই কেউ টেরই পেত না।
২০১০ সালে Lennart Poettering আর Kay Sievers systemd প্রস্তাব করেন, অনেকটা Apple-এর launchd (২০০৫) থেকে অনুপ্রাণিত হয়ে। মূল ধারণাগুলো: declarative unit (কী চাই লেখা, কীভাবে নয়), dependency গ্রাফ মেনে সমান্তরাল চালু, socket activation (সার্ভিসের socket আগেই খুলে রাখা, তাই নির্ভরশীল সার্ভিসকে অপেক্ষা করতে হয় না), আর প্রতিটি সার্ভিসকে একটি cgroup-এ রাখা — ফলে কোন প্রসেস কোন সার্ভিসের, নিখুঁতভাবে জানা যায় এবং সার্ভিস বন্ধ করলে তার সব সন্তান-প্রসেসও বন্ধ হয়। Fedora ২০১১ সালে এটি নেয়; Debian-এ ২০১৪ সালে তীব্র বিতর্ক ও ভোটের পর এটিকে ডিফল্ট করার সিদ্ধান্ত হয় (২০১৫ সালের Debian 8 থেকে কার্যকর), আর ২০১৫ সালের মধ্যে Ubuntu-সহ প্রায় সব বড় distro systemd-তে।
সমালোচনা মূলত দার্শনিক ও ব্যবহারিক। Unix-এর ঐতিহ্য বলে “একটি প্রোগ্রাম একটি কাজ ভালোভাবে করবে”; অথচ systemd প্রকল্প ধীরে ধীরে লগিং (journald), লগইন (logind), নেটওয়ার্ক, DNS, সময়-সমন্বয়ের মতো বহু অংশ নিজের মধ্যে এনেছে। সমালোচকদের ভয় — এক প্রকল্পের ওপর অতিরিক্ত নির্ভরতা, বাইনারি লগ, আর PID 1-এ বেশি জটিলতা মানে বেশি ঝুঁকি। তাই Devuan, Alpine (OpenRC), Void (runit)-এর মতো distro বিকল্প পথে চলে। সমর্থকেরা বলেন, অংশগুলো আলাদা প্রোগ্রাম, আর একীভূত নকশা আসলে distro-গুলোর পুনরাবৃত্তি কমিয়েছে।
মূল উপলব্ধি: এখানে “ঠিক-ভুল” নয়, একটি trade-off — একীভূত ব্যবস্থার সুবিধা (সামঞ্জস্য, গতি, নজরদারি) বনাম ছোট স্বাধীন টুকরোর সুবিধা (সরলতা, বদলানোর স্বাধীনতা)। প্রকৌশলীর কাজ নিজের পরিবেশের প্রয়োজন বুঝে বেছে নেওয়া, আর যেটিই বাছুন তার ভেতরের নিয়ম (যেমন Wants বনাম After) সত্যিই বোঝা।
প্র ০৪Container-এ তো পুরো OS বুট হয় না — তাহলে সেখানে PID 1 নিয়ে এত মাথাব্যথা কেন?
Container চালু হলে host kernel একটি নতুন PID namespace তৈরি করে, আর container-এর প্রথম প্রোগ্রামটি সেই namespace-এ PID 1 হয়। প্রায়ই সেটি আপনার অ্যাপ নিজেই — একটি Node.js সার্ভার, একটি Python স্ক্রিপ্ট। সমস্যা হলো, PID 1-এর ওপর kernel দুটি বিশেষ দায়িত্ব চাপায়, যা সাধারণ অ্যাপ জানেই না।
প্রথমত, signal. Linux PID 1-কে বিশেষভাবে রক্ষা করে: PID 1 যে signal-এর জন্য নিজে handler বসায়নি, সেই signal-এর ডিফল্ট আচরণ (যেমন SIGTERM-এ মরে যাওয়া) তার ওপর খাটে না — host থেকে পাঠানো SIGKILL বা SIGSTOP ছাড়া। তাই docker stop SIGTERM পাঠালে অনেক অ্যাপ কিছুই করে না; নির্ধারিত সময় (ডিফল্টে ১০ সেকেন্ড) পর Docker SIGKILL দিয়ে জোর করে মারে — ফলে বন্ধ হতে দেরি হয়, আর অ্যাপ গুছিয়ে বন্ধ হওয়ার (খোলা সংযোগ শেষ করা, ফাইল সেভ করা) সুযোগ পায় না। Signal-এর বিস্তারিত পর্ব ১৩-এ।
দ্বিতীয়ত, zombie. কোনো প্রসেসের বাবা মারা গেলে সে PID 1-এর সন্তান হয়ে যায়, আর তার শেষ অবস্থা wait() দিয়ে সংগ্রহ করা PID 1-এর কাজ। অ্যাপটি এটি না করলে মৃত প্রসেসগুলো zombie হয়ে জমতে থাকে, আর একসময় PID-এর সীমা ফুরিয়ে যেতে পারে।
সমাধান হিসেবে এসেছে খুব ছোট init প্রোগ্রাম — tini (Docker ১.১৩, ২০১৭ থেকে docker run --init-এ), catatonit (Podman-এর podman-init), dumb-init. এগুলো PID 1 হয়ে অ্যাপকে সন্তান হিসেবে চালায়, signal এগিয়ে দেয় আর zombie সংগ্রহ করে — এই পাতার কন্টেইনারে আপনি ঠিক এটিই দেখেছেন। আবার কিছু ক্ষেত্রে container-এর ভেতরে পুরো systemd চালানো হয় (যেমন সিস্টেম-টেস্টের জন্য), যদিও সাধারণ অ্যাপ-কন্টেইনারে সেটি অপ্রয়োজনীয় ভার।
মূল উপলব্ধি: বুটের “ভূমিকা”গুলো (প্রথম প্রসেস, অনাথের অভিভাবক, শেষ-সময়ের গুছিয়ে বন্ধ করা) OS-এর গভীর নিয়ম; পুরো বুট বাদ গেলেও ভূমিকাগুলো বাদ যায় না। কেউ সেগুলো না নিলে বাগ লুকিয়ে থাকে, যা ধরা পড়ে শুধু production-এ চাপের মুহূর্তে।
প্র ০৫“প্রথম নির্দেশটি কে দেয়?” — বুটস্ট্র্যাপের এই সমস্যা ইতিহাসে কীভাবে সমাধান হয়েছে, আর আজ Boot ROM কেন এত গুরুত্বপূর্ণ?
প্রথম দিকের কম্পিউটারে মেমরিতে কিছুই থাকত না, আর বুট করতে হতো হাতে। ১৯৬০–৭০-এর দশকের বহু মিনিকম্পিউটারে (যেমন DEC PDP-8, PDP-11) সামনের প্যানেলে সারি সারি সুইচ ছিল; অপারেটর একটি ছোট “bootstrap loader” প্রোগ্রাম বাইট ধরে ধরে সুইচ টিপে মেমরিতে বসাতেন, তারপর চালাতেন। সেই ছোট প্রোগ্রাম কাগজের টেপ বা ডিস্ক থেকে বড় প্রোগ্রাম আনত। ১৯৭৫ সালের Altair 8800-এর প্রথম ব্যবহারকারীরাও একই কাজ করতেন। পরে এই প্রথম প্রোগ্রামটি ROM চিপে স্থায়ীভাবে লেখা হতে থাকে — PC-র BIOS সেই ধারারই ফল।
আজকের সমস্যাটি আর “কীভাবে চালাব” নয়, বরং “প্রথম কোডটিকে বিশ্বাস করব কীভাবে?” বিশ্বাসের শিকলের প্রতিটি কড়া আগের কড়া যাচাই করে, কিন্তু প্রথম কড়াটিকে কে যাচাই করবে? উত্তর: কেউ না — তাকে এমনভাবে বানাতে হয় যাতে বদলানোই না যায়। এজন্যই ফোন আর আধুনিক Mac-এর চিপে একটি অপরিবর্তনীয় Boot ROM থাকে, যাকে বলে hardware root of trust. এর সুবিধা: কোনো ম্যালওয়্যার এটি বদলাতে পারে না। অসুবিধা: এতে বাগ থাকলে software আপডেটে ঠিক করা যায় না। ২০১৯ সালে কয়েক প্রজন্মের iPhone চিপের Boot ROM-এ এমন একটি ত্রুটি প্রকাশ্যে আসে; Apple পরের প্রজন্মের চিপে তা সংশোধন করে, কিন্তু পুরোনো চিপের ROM বদলানো সম্ভব ছিল না। এ কারণেই Boot ROM-কে যথাসম্ভব ছোট রাখা হয় — যত কম কোড, তত কম বাগের সম্ভাবনা।
PC-তে একই ভূমিকায় এসেছে firmware-এর ভেতরের হার্ডওয়্যার-সমর্থিত যাচাই (যেমন Intel Boot Guard) আর TPM চিপ, যা measured boot-এর মাপ রাখে।
মূল উপলব্ধি: প্রতিটি নিরাপদ ব্যবস্থার একদম নিচে একটি জিনিস থাকে যাকে বিনা প্রমাণে বিশ্বাস করতে হয়। ভালো নকশা সেই অংশটিকে যতটা সম্ভব ছোট, সরল আর অপরিবর্তনীয় রাখে — সফটওয়্যার আর্কিটেকচারে “trusted computing base” ছোট রাখার নীতিও এটাই।
অনুশীলন
হিসাব খাতায় করুন, তারপর উত্তর মেলান।
-
হিসাব — সীমাগুলো নিজে বের করুন: (ক) ৫১২-বাইট সেক্টরে MBR সর্বোচ্চ কত বড় ডিস্ক বোঝে? (খ) 4096-বাইট সেক্টরের (4Kn) ডিস্কে? (গ) GPT-র ডিফল্ট partition তালিকা (১২৮টি entry × ১২৮ বাইট) কত সেক্টর নেয়, আর ৫১২-বাইট সেক্টরে প্রথম ব্যবহারযোগ্য LBA কত?
(ক) LBA আর সেক্টর-সংখ্যা ৩২-bit, তাই সর্বোচ্চ ২৩২ = ৪২৯৪৯৬৭২৯৬টি সেক্টর। × ৫১২ = ২১৯৯০২৩২৫৫৫৫২ বাইট = ২ TiB (২৪১ বাইট)। বিক্রেতারা দশমিক TB-তে বলেন, তাই এটি প্রায় ২.২ TB.
(খ) ২৩২ × ৪০৯৬ = ২৪৪ বাইট = ১৬ TiB — তবে সব OS আর firmware এমন ডিস্কে MBR থেকে বুট সমর্থন করে না, তাই বড় ডিস্কে GPT-ই নিয়ম।
(গ) ১২৮ × ১২৮ = ১৬৩৮৪ বাইট = ১৬৩৮৪ / ৫১২ = ৩২টি সেক্টর। LBA 0 = protective MBR, LBA 1 = GPT header, LBA 2–33 = entry তালিকা, তাই প্রথম ব্যবহারযোগ্য LBA = ৩৪. (বাস্তবে tool-গুলো alignment-এর জন্য প্রথম partition LBA 2048-এ শুরু করে।) ডিস্কের শেষে আবার ৩২টি সেক্টরের তালিকা আর ১টি backup header থাকে।
-
হাতে decode করুন: একটি MBR-এর partition entry:
00 00 00 00 0C 00 00 00 00 00 10 00 00 00 A0 00. Bootable কি? Type কী? কোন LBA থেকে শুরু, কত সেক্টর, কত GiB? Partition শুরুর জায়গাটি ডিস্কের শুরু থেকে কত MiB দূরে?বাইট ০ =
00→ bootable নয়। বাইট ৪ =0C→ FAT32 (LBA). বাইট ৮–১১ =00 00 10 00→ উল্টে0x00100000= ১০৪৮৫৭৬. বাইট ১২–১৫ =00 00 A0 00→0x00A00000= ১০৪৮৫৭৬০টি সেক্টর।আকার: ১০৪৮৫৭৬০ × ৫১২ = ৫৩৬৮৭০৯১২০ বাইট = ৫ GiB (অথবা ১০৪৮৫৭৬০ / ২০৪৮ = ৫১২০ MiB). শুরুর দূরত্ব: ১০৪৮৫৭৬ × ৫১২ বাইট = ৫১২ MiB. উপরের C প্রোগ্রামের
partঅ্যারেতে এই বাইটগুলো বসিয়ে চালালে লাইনটি আসবে0x0C FAT32 (LBA) 1048576 10485760 5120 MiB. -
আউটপুট অনুমান করুন:
ps -p 1 -o comm=চালালে কী আসবে — (ক) Ubuntu 24.04 ডেস্কটপে, (খ)docker run --rm ubuntu ps -p 1 -o comm=, (গ)docker run --rm --init ubuntu ps -p 1 -o comm=, (ঘ) macOS-এ?(ক)
systemd—/sbin/initআসলে systemd-এর একটি symlink, আর kernel সেটিকেই PID 1 হিসেবে চালায়।(খ)
ps— container-এর প্রথম ও একমাত্র প্রোগ্রামpsনিজেই, তাই নিজের namespace-এ সে-ই PID 1. কোনো init নেই!(গ)
docker-init—--initদিলে Docker তার ছোট init (tini) PID 1 হিসেবে বসায়, আরpsতার সন্তান হয়ে চলে। এই পাতার Podman কন্টেইনারে একই ভূমিকায় ছিলpodman-init.(ঘ)
launchd— macOS-এ এটি পুরো পথসহ/sbin/launchdদেখাতে পারে। (WSL2-এ systemd চালু না থাকলে উত্তর হয়init— Microsoft-এর নিজস্ব ছোট init.) -
কমান্ড লিখুন — নিজের মেশিন চিনুন: নিজের কম্পিউটার UEFI না BIOS মোডে বুট হয়েছে, Secure Boot চালু কি না, আর বুটে কত সময় লেগেছে — Linux আর Windows, দুই জায়গায় কীভাবে বের করবেন? শুধু-পড়ার কমান্ড ব্যবহার করুন।
Linux:
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS(ফোল্ডারটি শুধু UEFI-বুটে থাকে);mokutil --sb-state;systemd-analyzeআরsystemd-analyze critical-chain; partition style দেখতেlsblk -o NAME,SIZE,PTTYPE,FSTYPE(PTTYPE-এgptবাdos= MBR).Windows:
msinfo32→ “BIOS Mode” আর “Secure Boot State”; Administrator PowerShell-এConfirm-SecureBootUEFI; ডিস্কের style দেখতেGet-Disk(PartitionStyle কলামে GPT বা MBR). বুট-সময়ের জন্য Event Viewer → Applications and Services Logs → Microsoft → Windows → Diagnostics-Performance.এই কমান্ডগুলো কিছু বদলায় না।
efibootmgr-এর মতো tool-এ-o,-b … -B-এর মতো অপশন NVRAM-এ লেখে — সেগুলো বুঝে-শুনে, দরকার হলে তবেই।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি UEFI Linux PC-র বুটের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- ⚡ CPU reset vector থেকে firmware চালায়, RAM ও ডিভাইস প্রস্তুত হয়
- 📇 Firmware NVRAM-এর BootOrder দেখে ESP থেকে
.efibootloader চালায় - 🧭 GRUB kernel আর initramfs RAM-এ আনে
- 🧠 Kernel হার্ডওয়্যার চেনে, initramfs-এর সাহায্যে আসল root মাউন্ট করে
- 🌱 systemd PID 1 হিসেবে target অনুযায়ী সার্ভিস চালু করে
- 👤 Login স্ক্রিন আর ব্যবহারকারীর session
MBR-এর ৫১২ বাইটের মধ্যে partition table কোথায় থাকে, আর কতটি primary partition রাখা যায়?
- বাইট ০–৬৩, ৮টি partition
- বাইট ৪৪৬–৫০৯, ৪টি partition
- বাইট ৪৪৬–৫১১, ১২৮টি partition
- বাইট ৫১০–৫১১, ১টি partition
৫১২-বাইট সেক্টরের ডিস্কে MBR partitioning সর্বোচ্চ কত বড় ডিস্ক পুরোপুরি ব্যবহার করতে পারে, আর কেন?
- ৫১২ MiB, কারণ MBR ৫১২ বাইটের
- ৪ GiB, কারণ ৩২-bit ঠিকানা
- ২ TiB, কারণ LBA ৩২-bit আর প্রতিটি সেক্টর ৫১২ বাইট
- ৮ ZiB, কারণ LBA ৬৪-bit
UEFI firmware bootloader কোথা থেকে চালায়?
- EFI System Partition (FAT)-এর একটি .efi ফাইল থেকে
- ডিস্কের সেক্টর ০-এর ৪৪৬ বাইট কোড থেকে
- Linux-এর root partition-এর /sbin/init থেকে
- initramfs-এর /init থেকে
Linux বুটে initramfs-এর মূল উদ্দেশ্য কী?
- Firmware-এর ডিজিটাল স্বাক্ষর যাচাই করা
- একাধিক OS-এর মেনু দেখানো
- RAM কম পড়লে swap হিসেবে কাজ করা
- আসল root file system মাউন্টের জন্য দরকারি driver ও tool সাময়িকভাবে দেওয়া
একটি systemd unit-এ শুধু After=network.target লেখা আছে, কোনো Wants= বা Requires= নেই। এর অর্থ কী?
- এই unit চালু হলে network.target-ও অবশ্যই চালু হবে
- দুটোই চালু হলে এটি network.target-এর পরে শুরু হবে — এর বেশি কিছু নয়
- এটি network.target-এর আগে চালু হবে
- systemd এখন সব unit একটির পর একটি চালাবে
একটি Docker/Podman কন্টেইনারের ভেতরে ps -p 1 -o comm= চালালে systemd না এসে podman-init বা অ্যাপের নাম আসে। কারণ কী?
- কন্টেইনার নিজের kernel বুট করে, কিন্তু systemd ছাড়া
- ps কমান্ড কন্টেইনারে ভুল তথ্য দেয়
- কন্টেইনার পুরো OS বুট করে না; host kernel-এর নতুন PID namespace-এ প্রথম প্রসেসটিই PID 1
- Host-এর systemd মারা গেছে
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- বুট একটি রিলে: firmware → bootloader → kernel (+ initramfs) → init/PID 1 → login; প্রত্যেকে পরের জনকে খুঁজে মেমরিতে আনে।
- BIOS + MBR: সেক্টর ০-এর ৫১২ বাইট (৪৪৬ কোড + ৪ × ১৬ টেবিল +
55 AA), ৪টি primary, ২ TiB সীমা। - UEFI + GPT: ESP-র
.efiফাইল, NVRAM-এ BootOrder, ১২৮টি entry, ৬৪-bit LBA, backup header; Secure Boot প্রতিটি ধাপের স্বাক্ষর যাচাই করে। - Kernel memory আর হার্ডওয়্যার সাজায়, initramfs দিয়ে আসল root মাউন্ট করে, তারপর PID 1 চালায় — Linux-এ সাধারণত systemd, macOS-এ launchd, Windows-এ smss → wininit → services.
- systemd-এ প্রয়োজন (Wants/Requires) আর ক্রম (After/Before) আলাদা; বুট-সময় ঠিক করে critical chain. কন্টেইনার পুরো OS বুট করে না।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ০৮ · প্রসেস — state, PCB আর memory layoutপরবর্তী পর্ববুটের পর জন্ম নেওয়া প্রসেস ভেতর থেকে কেমন।
- অপারেটিং সিস্টেম · কোর্স হোম৬৪টি পর্বপুরো কোর্সের রোডম্যাপ — ১০টি মডিউল।
- Computer Fundamentals · Boot Processসহজ পরিচিতিএকই বিষয়ের শুরুর স্তরের ব্যাখ্যা।
- DSA · Topological sortপাশের ট্র্যাকsystemd-এর dependency ক্রমের পেছনের অ্যালগরিদম।
- C প্রোগ্রামিং · প্রসেস আর IPCহাতে-কলমেfork, exec আর wait — PID 1-এর সন্তানদের কোড।