পাঠ ৫২ · ৫৬-এর মধ্যে · মডিউল ১৩
Home / Courses / Operating Systems (OS) / কেস স্টাডি

কেস স্টাডি: Linux কার্নেল আর্কিটেকচার

Case study: Linux kernel architecture
১০ মিনিট পড়া উচ্চ · Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • Linux কেন মনোলিথিক কার্নেল, অথচ কীভাবে লোডেবল মডিউল দিয়ে তার একটি বড় দুর্বলতা মোকাবিলা করে
  • CFS শিডিউলার আসলে কী করে এবং তা M3-এর Round Robin/প্রায়োরিটি ধারণার সাথে কীভাবে সম্পর্কিত
  • Linux-এর ভার্চুয়াল মেমরি সাবসিস্টেম কীভাবে ডিমান্ড পেজিং ও clock অ্যালগরিদম ব্যবহার করে
  • ext4-এর জার্নালিং কীভাবে M9/L41-এর ক্র্যাশ-কনসিস্টেন্সি ধারণার একটি বাস্তব প্রয়োগ
  • এই কোর্সের প্রতিটি মডিউলকে একটি বাস্তব, বহুল-ব্যবহৃত OS-এর সাথে সরাসরি সংযুক্ত করে দেখা

১ · মনোলিথিক কার্নেল + লোডেবল কার্নেল মডিউল

M1/L04-এ আমরা দেখেছিলাম মনোলিথিক কার্নেল-এর একটি বড় দুর্বলতা — পুরো OS (প্রসেস ম্যানেজমেন্ট, মেমরি ম্যানেজমেন্ট, ফাইল সিস্টেম, ডিভাইস ড্রাইভার) একটিমাত্র প্রোগ্রাম হিসেবে কার্নেল মোডে চলে, তাই একটি ডিভাইস ড্রাইভারের বাগও পুরো সিস্টেম ক্র্যাশ করাতে পারে। Linux ঠিক এই ডিজাইনই বেছে নিয়েছে (গতি ও পারফরম্যান্সের জন্য), কিন্তু লোডেবল কার্নেল মডিউল (LKM)Loadable Kernel Moduleএকটি কম্পাইল করা কোড ইউনিট যা চলমান কার্নেলে রানটাইমে যোগ বা সরানো যায় — পুরো কার্নেল রিবিল্ড বা রিবুট না করেই। দিয়ে এই দুর্বলতা আংশিকভাবে মোকাবিলা করে — ডিভাইস ড্রাইভার, ফাইল সিস্টেম ড্রাইভার ইত্যাদি রানটাইমে যোগ/অপসারণ করা যায়, পুরো কার্নেল রিবিল্ড বা রিবুট ছাড়াই। এটি মাইক্রোকার্নেলের ফল্ট-আইসোলেশন সুবিধা পুরোপুরি না দিলেও, ব্যবহারিকভাবে রক্ষণাবেক্ষণ ও নমনীয়তা অনেকটাই সহজ করে দেয় — মনোলিথিক গতি রেখে দিয়েই।

ইউজার-স্পেস অ্যাপ্লিকেশন সিস্টেম কল ইন্টারফেস (M1/L03) মনোলিথিক Linux কার্নেল CFS শিডিউলার M3/L09-11 ভার্চুয়াল মেমরি M8/L32,L34 VFS + ext4 M9/L41 লোডেবল ডিভাইস ড্রাইভার হার্ডওয়্যার
Linux-এর পুরো কার্নেল একটি ঠিকানা-স্পেসে চলে (মনোলিথিক) — তবে ডিভাইস ড্রাইভারের মতো অংশ রানটাইমে লোড/আনলোড করা যায় (লোডেবল মডিউল)।

২ · CFS — Linux-এর বাস্তব CPU শিডিউলার

M3-এ আমরা FCFS (L10), SJF (L10), প্রায়োরিটি ও Round Robin (L11) শিখেছি। Linux-এর ডিফল্ট শিডিউলার, Completely Fair Scheduler (CFS)Completely Fair SchedulerLinux-এর ডিফল্ট CPU শিডিউলার — প্রতিটি প্রসেসকে CPU-এর একটি ন্যায্য, আনুপাতিক ভাগ দেওয়ার চেষ্টা করে, একটি "virtual runtime" ট্র্যাক করে।, এই ধারণাগুলোরই একটি অনেক বেশি পরিশীলিত রূপ — প্রতিটি প্রসেসের একটি "virtual runtime" ট্র্যাক করে এবং সবসময় যে প্রসেস এখন পর্যন্ত সবচেয়ে কম virtual runtime পেয়েছে তাকে পরবর্তী CPU সময় দেয় — ধারণাগতভাবে L11-এর Round Robin-এর "প্রতিটি প্রসেস নিয়মিত পালা পাক" লক্ষ্যেরই একটি অনেক মসৃণ, নিখুঁত সংস্করণ (একটি নির্দিষ্ট quantum-এর পরিবর্তে, রেড-ব্ল্যাক ট্রি ব্যবহার করে সবসময় "সবচেয়ে কম পাওয়া" প্রসেসটি দ্রুত খুঁজে বের করে)। L11-এর প্রায়োরিটি ধারণাও এখানে আছে — "nice" ভ্যালুর মাধ্যমে একটি প্রসেসকে তুলনামূলক বেশি বা কম CPU-শেয়ার দেওয়া যায়, যা virtual runtime বাড়ার হারকে প্রভাবিত করে।

৩ · ভার্চুয়াল মেমরি — ডিমান্ড পেজিং ও clock অ্যালগরিদম

Linux-এর মেমরি ম্যানেজমেন্ট সাবসিস্টেম M8/L32-এর ডিমান্ড পেজিং হুবহু বাস্তবায়ন করে — একটি পেজ শুধু তখনই ফিজিক্যাল মেমরিতে লোড হয় যখন প্রথমবার সত্যিকারভাবে অ্যাক্সেস করা হয়। পেজ রিপ্লেসমেন্টের জন্য Linux M8/L34-এর ঠিক LRU ব্যবহার করে না (প্রতিটি অ্যাক্সেসে টাইমস্ট্যাম্প রাখা পারফরম্যান্সের দিক থেকে ব্যয়বহুল) — বরং একটি বাস্তবসম্মত approximation ব্যবহার করে, যাকে বলে clock অ্যালগরিদমClock AlgorithmLRU-এর একটি সস্তা approximation — প্রতিটি পেজে একটি "reference bit" থাকে, একটি ঘড়ির কাঁটার মতো ঘোরা পয়েন্টার পেজগুলো পরীক্ষা করে; bit সেট থাকলে ক্লিয়ার করে এগিয়ে যায়, ক্লিয়ার থাকলে সেই পেজ evict করে। (এটি "second-chance algorithm" নামেও পরিচিত) — প্রতিটি পেজে একটি একক reference bit রাখে, ঘড়ির কাঁটার মতো একটি পয়েন্টার ঘুরে ঘুরে পেজ পরীক্ষা করে, bit সেট থাকলে সেটি ক্লিয়ার করে এগিয়ে যায় (পেজটিকে "দ্বিতীয় সুযোগ" দেয়), bit ইতিমধ্যে ক্লিয়ার থাকলে সেই পেজটিকেই evict করে। এটি পুরো LRU অর্ডার বজায় না রেখেও, বাস্তবে LRU-এর কাছাকাছি পারফরম্যান্স দেয় — অনেক কম ওভারহেডে।

৪ · ext4 ও জার্নালিং

Linux-এর সবচেয়ে সাধারণ ফাইল সিস্টেম, ext4, M9/L41-এ শেখা জার্নালিং (write-ahead logging) ব্যবহার করে ক্র্যাশ কনসিস্টেন্সি নিশ্চিত করতে — কোনো মেটাডেটা/ডেটা পরিবর্তনের আগে সেই পরিবর্তনের বিবরণ প্রথমে একটি সিকোয়েন্সিয়াল জার্নালে লেখা হয়; বিদ্যুৎ বিভ্রাট বা ক্র্যাশ হলে রিবুটের সময় জার্নাল থেকে অসম্পূর্ণ এন্ট্রি replay বা বাতিল করে দ্রুত একটি সামঞ্জস্যপূর্ণ অবস্থায় ফিরে আসা যায় — পুরো ডিস্ক স্ক্যান করার প্রয়োজন হয় না।

৫ · কোড: Linux সাবসিস্টেম বনাম এই কোর্সের মডিউল

নিচের কোড সেলে Linux-এর প্রতিটি বাস্তব সাবসিস্টেমকে এই কোর্সের নির্দিষ্ট মডিউল/পাঠের সাথে সরাসরি সংযুক্ত করা হলো।

Python
# Linux-এর বাস্তব সাবসিস্টেম -- এই কোর্সের মডিউল/পাঠের সাথে সরাসরি সংযোগ
linux_subsystems = {
    "CFS শিডিউলার": {
        "course_module": "M3 (CPU শিডিউলিং), L09-L11",
        "real_technique": "Virtual-runtime-ভিত্তিক ন্যায্য শিডিউলিং (রেড-ব্ল্যাক ট্রি)",
    },
    "ভার্চুয়াল মেমরি (mm সাবসিস্টেম)": {
        "course_module": "M8 (ভার্চুয়াল মেমরি), L32",
        "real_technique": "ডিমান্ড পেজিং + clock/second-chance পেজ রিপ্লেসমেন্ট",
    },
    "ext4 ফাইল সিস্টেম": {
        "course_module": "M9 (ফাইল সিস্টেম), L41",
        "real_technique": "Write-ahead জার্নালিং দিয়ে ক্র্যাশ কনসিস্টেন্সি",
    },
    "লোডেবল কার্নেল মডিউল": {
        "course_module": "M1 (OS স্ট্রাকচার), L04",
        "real_technique": "মনোলিথিক ডিজাইন + রানটাইম মডিউল লোড/আনলোড",
    },
    "সিস্টেম কল ইন্টারফেস": {
        "course_module": "M1, L03",
        "real_technique": "user mode -> kernel mode নিয়ন্ত্রিত ট্র্যাপ",
    },
}

print(f"{'Linux সাবসিস্টেম':32} | {'কোর্স মডিউল':28} | বাস্তব কৌশল")
print("-" * 100)
for name, info in linux_subsystems.items():
    print(f"{name:32} | {info['course_module']:28} | {info['real_technique']}")

    
মূল কথা · Key takeaway

Linux কোনো "নতুন তত্ত্ব" ব্যবহার করে না — এটি এই কোর্সে শেখা প্রতিটি ধারণারই (মনোলিথিক কার্নেল, শিডিউলিং, ডিমান্ড পেজিং, জার্নালিং) একটি প্রকৌশলগতভাবে অপ্টিমাইজ করা, বাস্তব-জগতের বাস্তবায়ন। তত্ত্ব বুঝলে বাস্তব সিস্টেমের নকশা পড়া অনেক সহজ হয়ে যায় — এটাই এই কেস স্টাডির মূল উদ্দেশ্য।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ Linux মনোলিথিক কার্নেল বেছে নিয়েও কীভাবে L04-এর "একটি বাগযুক্ত ড্রাইভার পুরো সিস্টেম ক্র্যাশ করাতে পারে" সমস্যাটি ব্যবহারিকভাবে কমায়?

লোডেবল কার্নেল মডিউলের মাধ্যমে। এটি সমস্যাটি সম্পূর্ণ দূর করে না — একটি বাগযুক্ত মডিউল এখনও কার্নেল মোডে চলে, তাই এখনও ক্র্যাশ করাতে পারে (মাইক্রোকার্নেলের মতো সম্পূর্ণ ফল্ট-আইসোলেশন নেই)। কিন্তু এটি রক্ষণাবেক্ষণ ও আপডেটকে অনেক সহজ করে — একটি নতুন বা ঠিক করা ড্রাইভার পুরো কার্নেল রিবিল্ড/রিবুট ছাড়াই লোড করা যায়, যা L04-এর মূল দুর্বলতার একটি ব্যবহারিক (যদিও আংশিক) সমাধান।

প্র ০২ CFS শিডিউলার L11-এর Round Robin থেকে ধারণাগতভাবে কীভাবে আলাদা, অথচ কী লক্ষ্যে একই?

দুটোরই লক্ষ্য একই — প্রতিটি প্রসেসকে নিয়মিত, ন্যায্য CPU সময় দেওয়া, কোনো প্রসেস যেন বঞ্চিত না হয়। Round Robin এটি করে একটি ফিক্সড quantum ও একটি সাধারণ কিউ ঘুরিয়ে; CFS আরও সূক্ষ্মভাবে করে — প্রতিটি প্রসেসের "virtual runtime" (এখন পর্যন্ত সে কত CPU সময় পেয়েছে, তার priority/nice মান দিয়ে স্কেল করা) ট্র্যাক করে এবং সবসময় সবচেয়ে কম পাওয়া প্রসেসটিকে বেছে নেয় — এটি একটি ধারাবাহিক, স্বয়ংক্রিয়ভাবে self-balancing ন্যায্যতা তৈরি করে, ফিক্সড quantum-এর কঠোরতা ছাড়াই।

প্র ০৩ clock অ্যালগরিদম কেন সত্যিকারের LRU (L34) ব্যবহার না করে একটি approximation ব্যবহার করে?

সত্যিকারের LRU রাখতে হলে প্রতিটি মেমরি অ্যাক্সেসে (যা প্রতি সেকেন্ডে কোটি কোটিবার ঘটে) একটি টাইমস্ট্যাম্প আপডেট করতে হবে অথবা একটি লিংকড লিস্টে পেজ পুনর্বিন্যাস করতে হবে — এই ওভারহেড বাস্তব হার্ডওয়্যারে ব্যবহারিকভাবে অসহনীয়। clock অ্যালগরিদম মাত্র একটি বিট (reference bit) দিয়ে "সম্প্রতি ব্যবহৃত হয়েছে কি না" আনুমানিকভাবে ট্র্যাক করে — সম্পূর্ণ নির্ভুল LRU অর্ডার না দিলেও, বাস্তবে খুব কাছাকাছি পারফরম্যান্স দেয়, অনেক কম খরচে।

অনুশীলন

  1. চিন্তা করুন: উপরের কোড সেলের টেবিলে আরেকটি সারি যোগ করুন — "TCP/IP নেটওয়ার্ক স্ট্যাক" — এটি কোন কোর্স মডিউলের সাথে সবচেয়ে বেশি সম্পর্কিত হবে বলে আপনার মনে হয়?

    এই কোর্সের বাইরে — এটি সরাসরি Computer Networks কোর্সের বিষয়। যদিও নেটওয়ার্ক স্ট্যাকও Linux কার্নেলের একটি অংশ (এবং এটিও লোডেবল মডিউল হিসেবে গঠন করা যায়), এর প্রোটোকল-লেয়ারিং যুক্তি এই OS কোর্সের সুযোগের বাইরে — এটাই কেন এই কোর্সের CLAUDE.md রুল অনুযায়ী আমরা নেটওয়ার্কিং-নির্দিষ্ট বিষয়ে গভীরে না গিয়ে সহোদর কোর্সের দিকে নির্দেশ করি।

  2. পরীক্ষা করুন: কোড সেলে linux_subsystems ডিকশনারিতে একটি নতুন এন্ট্রি যোগ করুন — "প্রসেস টেবিল / PCB" — যেটি M2/L06-এর সাথে যুক্ত, এবং টেবিলটি আবার প্রিন্ট করে দেখুন এটি সঠিকভাবে যোগ হয়েছে কি না।

    linux_subsystems["প্রসেস টেবিল"] = {"course_module": "M2 (প্রসেস ম্যানেজমেন্ট), L06", "real_technique": "প্রতি প্রসেসে একটি task_struct (Linux-এর PCB-এর বাস্তব রূপ)"} যোগ করলে লুপ স্বয়ংক্রিয়ভাবে এটি টেবিলের নতুন সারি হিসেবে প্রিন্ট করবে — এটি দেখায় কীভাবে Linux-এর task_struct কাঠামো সরাসরি M2/L06-এ শেখা PCB ধারণার একটি বাস্তব নাম মাত্র।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
VM বনাম কন্টেইনার — কখন কোনটা