সরাসরি পর্বে যান
পর্ব ০২ · ৬৪-এর মধ্যে · মডিউল ১

OS-এর ইতিহাস আর ধরন — batch থেকে মোবাইল আর ক্লাউড

History and Types of Operating Systems — from Batch to Mobile and Cloud

Taught in Bangla, this lesson traces operating system history as answers to waste: manual operation to batch, multiprogramming and time-sharing. It works CPU utilisation with the 1 − p^n formula, gives precise definitions of multiprogramming, multitasking, multiprocessing and multithreading, compares real-time, embedded, distributed, network, mobile and cloud OS, and maps the Unix and Windows families with a live Linux check of kernel version and CPU count.

এই পর্বে যা শিখবেন

  • OS-এর প্রজন্মগুলো — প্রতিটি কোন সমস্যার সমাধান হিসেবে এসেছিল
  • Uniprogramming আর multiprogramming-এ CPU ব্যবহার হাতে হিসাব করা, আর 1 − pn সূত্রের অনুমানগুলো
  • multiprogramming, multitasking, multiprocessing আর multithreading-এর নিখুঁত সংজ্ঞা
  • batch, time-sharing, real-time (hard/soft), distributed, network, embedded, মোবাইল আর ক্লাউড OS-এর trade-off
  • Unix আর Windows-এর বংশলতিকা, আর নিজের Linux-এ kernel version ও CPU সংখ্যা দেখা

১ · OS ছাড়া কম্পিউটার — হাতে চালানো থেকে batch

আগের পর্বে দেখেছেন, অপারেটিং সিস্টেম (OS) হলো কম্পিউটারের ব্যবস্থাপক — হার্ডওয়্যার ভাগ করে দেয়, প্রোগ্রামকে সুরক্ষা দেয়, আর সবার জন্য একটি সহজ ইন্টারফেস দেয়। কিন্তু প্রথম কম্পিউটারগুলোতে এই ব্যবস্থাপক ছিল না। OS-এর ইতিহাস আসলে একটি প্রশ্নের বারবার উত্তর খোঁজার গল্প: “এই দামি যন্ত্রটির সময় কোথায় নষ্ট হচ্ছে?”

প্রথম প্রজন্ম: OS নেই, সব হাতে (১৯৪০ ও ১৯৫০-এর দশকের শুরু)

১৯৪০-এর দশকের কম্পিউটার (যেমন ENIAC) ছিল ঘরভর্তি vacuum tube. প্রোগ্রামার নিজেই অপারেটর। তিনি একটি খাতায় নাম লিখে যন্ত্রের সময় “বুক” করতেন — ধরুন রাত ২টা থেকে ৩টা। নির্ধারিত সময়ে এসে সুইচ, প্লাগবোর্ড বা পরে punch card দিয়ে প্রোগ্রাম ঢোকাতেন, চালাতেন, ফল প্রিন্ট করে নিয়ে যেতেন। একে বলে serial processing — একজনের পর একজন, হাতে হাতে।

এতে দুটি বড় অপচয় ছিল। প্রথমত, setup time: compiler-এর টেপ লাগানো, কার্ড সাজানো, প্রিন্টার তৈরি করা — এই সময়ে যন্ত্র কিছুই গণনা করছে না। দ্বিতীয়ত, বুকিংয়ের অপচয়: ৪৫ মিনিটে কাজ শেষ হলে বাকি ১৫ মিনিট যন্ত্র ফাঁকা; আর কাজ শেষ না হলে মাঝপথে উঠে যেতে হতো। যন্ত্রটির দাম তখন লক্ষ লক্ষ ডলার, তাই প্রতিটি অলস মিনিটই ছিল বিশাল ক্ষতি।

দ্বিতীয় প্রজন্ম: batch system আর resident monitor (১৯৫০-এর দশকের মাঝামাঝি থেকে)

সমাধান এলো: প্রোগ্রামাররা আর যন্ত্রের সামনে যাবেন না। তাঁরা punch card-এ কাজ (job) জমা দেবেন একজন পেশাদার অপারেটরের কাছে। অপারেটর একই ধরনের কাজগুলো (যেমন সব FORTRAN কাজ) একসাথে সাজিয়ে একটি “batch” বানাবেন, যাতে compiler একবার লোড করেই অনেক কাজ চালানো যায়। এটিই batch system.

কিন্তু এক কাজ শেষে পরেরটি শুরু করবে কে? এর জন্য মেমরিতে সবসময় একটি ছোট প্রোগ্রাম বসে থাকত — resident monitor. এটিকেই আধুনিক OS-এর পূর্বপুরুষ বলা যায়। Monitor কার্ড পড়ত, প্রতিটি কাজের শুরুর বিশেষ নির্দেশ-কার্ড দেখে বুঝত কোন compiler লাগবে, কাজটি চালাত, শেষ হলে নিয়ন্ত্রণ ফিরে পেয়ে পরের কাজে যেত। এই নির্দেশগুলোর ভাষাকে বলা হতো job control language (JCL) — IBM-এর বড় যন্ত্রগুলোর JCL আজও কিছু ব্যাংক আর বিমা প্রতিষ্ঠানের mainframe-এ চলে।

পাড়ার লন্ড্রির কথা ভাবুন। আপনি দোকানের ইস্ত্রির টেবিলে নিজে দাঁড়িয়ে নিজের জামা ইস্ত্রি করছেন না — জামা জমা দিয়ে রসিদ নিয়ে চলে যান, পরদিন তৈরি জামা নেন। দোকানি সাদা কাপড় একসাথে, রঙিন কাপড় একসাথে ধোন (batch). দোকানের দক্ষতা বাড়ে, কিন্তু আপনার “turnaround” — জমা থেকে ফেরত পাওয়া পর্যন্ত সময় — হয়ে যায় এক দিন। জামায় একটি দাগ থেকে গেলে জানবেন পরদিন, আবার জমা দিতে হবে। Batch-যুগের প্রোগ্রামাররা ঠিক এভাবেই একটি কমা ভুলের জন্য পুরো এক দিন হারাতেন।

Batch-যুগে আরও একটি কৌশল আসে: ধীর card reader আর printer যাতে দ্রুত CPU-কে আটকে না রাখে, তাই একটি ছোট, সস্তা কম্পিউটার আগেই কার্ড থেকে ম্যাগনেটিক টেপে কাজগুলো কপি করে রাখত (offline I/O). পরে ডিস্ক আসার পর এর উন্নত রূপ হলো spooling (Simultaneous Peripheral Operation On-Line) — ইনপুট আগেই ডিস্কে জমা, আউটপুট ডিস্কে লিখে পরে ধীরে ধীরে প্রিন্ট। আজও আপনার কম্পিউটারে “print spooler” সার্ভিসটি ঠিক এই কাজ করে।

১৯৫৬ সালের দিকে General Motors আর North American Aviation মিলে IBM 704 যন্ত্রের জন্য GM-NAA I/O নামে একটি batch-পরিচালক তৈরি করে — অনেক ইতিহাসবিদ এটিকে প্রথম অপারেটিং সিস্টেমগুলোর একটি হিসেবে ধরেন (এক্ষেত্রে “প্রথম” দাবিটি নিয়ে মতভেদ আছে)। প্রথম OS-গুলো তাই কোনো কম্পিউটার কোম্পানি নয়, যন্ত্রের ব্যবহারকারীরাই নিজেদের প্রয়োজনে বানিয়েছিলেন।

Batch-এর ধারণা আজও মরে যায়নি। ব্যাংকের দিনশেষের হিসাব মেলানো (end-of-day processing), মাসশেষে বেতনের হিসাব, গবেষণাগারের supercomputer-এ জমা দেওয়া simulation কাজ (Slurm-এর মতো job scheduler), কিংবা Linux-এর cron দিয়ে রাতে চালানো backup — সবই batch-চিন্তা: মানুষ পাশে না বসেও কাজ সারির পর সারি চলে।

২ · Multiprogramming — CPU-কে অলস বসে থাকতে না দেওয়া

Batch অপারেটরের সময় বাঁচাল, কিন্তু একটি কাজ চলার ভেতরেও অপচয় রয়ে গেল। একটি সাধারণ কাজ কিছুক্ষণ হিসাব করে (CPU burst), তারপর টেপ বা ডিস্ক থেকে ডেটা পড়ে (I/O burst), আবার হিসাব করে। I/O যন্ত্র CPU-র চেয়ে হাজার গুণ ধীর। মেমরিতে যদি একটিমাত্র কাজ থাকে (uniprogramming), তাহলে প্রতিবার I/O-র সময় CPU চুপচাপ বসে থাকে।

সমাধান: মেমরিকে কয়েক ভাগে ভাগ করে একসাথে কয়েকটি কাজ রাখা। একটি কাজ I/O-র জন্য অপেক্ষা শুরু করলেই OS CPU-টি আরেকটি প্রস্তুত (ready) কাজকে দিয়ে দেবে। এটাই multiprogramming. এর লক্ষ্য একটাই — CPU utilisation (CPU কত শতাংশ সময় কাজে ব্যস্ত) বাড়ানো।

একটি ছোট রেস্তোরাঁর রান্নাঘরে একটিই চুলা, একজনই বাবুর্চি। ভাত চুলায় দিয়ে ২০ মিনিট দাঁড়িয়ে থাকলে বাবুর্চির সময় নষ্ট। দক্ষ বাবুর্চি ভাত ফুটতে থাকার সময় (I/O-র অপেক্ষা) পেঁয়াজ কাটেন, মাছ মশলায় মাখান — অর্থাৎ আরেকটি পদের কাজ করেন। চুলা আর বাবুর্চি যত বেশি সময় ব্যস্ত, রেস্তোরাঁর লাভ তত বেশি। রান্নাঘরে একসাথে কয়েকটি অর্ডার রাখার এই কৌশলই multiprogramming. লক্ষ্য করুন: এখানে বাবুর্চি নিজে থেকে কাজ ছেড়ে দেন না — একটি পদ যখন নিজেই অপেক্ষায় যায়, তখনই অন্যটিতে যান।

নিচের ডায়াগ্রামে একই তিনটি কাজ (J1, J2, J3) দুইভাবে চালানো হয়েছে। প্রতিটি কাজ CPU → I/O → CPU — এই তিন ভাগে। সময়ের একক ধরুন মিলিসেকেন্ড। ধরে নেওয়া হয়েছে প্রতিটি কাজের I/O আলাদা যন্ত্রে হয়, তাই একাধিক I/O একসাথে চলতে পারে।

সময়রেখা (প্রতিটি অক্ষর = ১ একক)CPU সারিতে অঙ্ক = যে কাজ চলছে, - = CPU অলস

            
  1. তিনটি কাজ। J1-এর দরকার CPU 2 → I/O 3 → CPU 1; J2-এর CPU 1 → I/O 4 → CPU 2; J3-এর CPU 2 → I/O 2 → CPU 2. তিনটির মোট CPU-সময় 3 + 3 + 4 = 10 একক। যেভাবেই চালান, CPU-কে এই ১০ একক কাজ করতেই হবে — প্রশ্ন হলো মাঝে কতটা সময় নষ্ট হয়।
  2. Uniprogramming, t = 0 থেকে 6. মেমরিতে শুধু J1. t = 2 থেকে 5 পর্যন্ত J1 I/O করছে (i), আর CPU সারিতে --- — CPU টানা ৩ একক অলস। J2 আর J3 মেমরিতে ঢোকারই সুযোগ পায়নি, ডিস্কের সারিতে বসে আছে (·)।
  3. Uniprogramming শেষ। J2 চলল t = 6 থেকে 13 (তার I/O-তে CPU অলস ৪ একক), J3 চলল 13 থেকে 19 (অলস ২ একক)। মোট অলস 3 + 4 + 2 = 9 একক। মোট সময় 19, CPU ব্যস্ত 10, তাই CPU ব্যবহার 10 ÷ 19 ≈ 52.6%. প্রায় অর্ধেক সময় এই দামি যন্ত্র কিছুই করেনি।
  4. Multiprogramming, t = 0 থেকে 3. এবার তিনটি কাজই শুরু থেকে মেমরিতে (w = ready, CPU-র অপেক্ষায়)। J1 চলল 0 থেকে 2. t = 2-এ J1 I/O-তে যেতেই OS CPU দিল J2-কে (2 থেকে 3). t = 3-এ J2-ও I/O-তে গেল — CPU পাবে J3. CPU এখনো একবারও অলস হয়নি।
  5. t = 3 থেকে 6. J3 চলল 3 থেকে 5, তারপর তার I/O (5 থেকে 7). ঠিক t = 5-এ J1-এর I/O শেষ, J1 ready — তাই 5 থেকে 6 J1 তার শেষ CPU অংশ চালিয়ে শেষ হলো। খেয়াল করুন, একই মুহূর্তে J1-এর CPU, J2 আর J3-এর I/O — তিনটি কাজ একসাথে এগোচ্ছে।
  6. t = 6 থেকে 11. t = 6 থেকে 7 CPU অলস (-): J1 শেষ, J2 আর J3 দুটোই I/O-তে — এই একটি মাত্র অলস একক। t = 7-এ দুটোই ready হলো; আগে-আসা-আগে-পাবে নিয়মে (সমান হলে ছোট নম্বর আগে) J2 চলল 7 থেকে 9, J3 অপেক্ষা (w) করে চলল 9 থেকে 11. মোট সময় 11, CPU ব্যস্ত 10 — ব্যবহার 10 ÷ 11 ≈ 90.9%.
  7. তুলনা। একই ১০ একক CPU-কাজ — uniprogramming-এ লাগল 19, multiprogramming-এ 11. CPU ব্যবহার 52.6% থেকে 90.9%, আর throughput (একক সময়ে শেষ হওয়া কাজ) 3/19 থেকে 3/11. কোনো কাজ নিজে দ্রুত হয়নি — শুধু অপেক্ষার ফাঁকগুলো ভরাট হয়েছে। এটাই multiprogramming-এর পুরো রহস্য।

হাতে হিসাব করা ভালো, কিন্তু কাজ বাড়লে হাতে আর কুলায় না। নিচের ছোট simulator একই তিনটি কাজের হিসাব নিজে করে। jobs তালিকার সংখ্যা বদলে নিজের কাজের মিশ্রণ দিয়ে চালিয়ে দেখুন:

// each job: alternating CPU and I/O bursts (time units), starting and ending with CPU
const jobs = [
  { name: "J1", bursts: [2, 3, 1] },
  { name: "J2", bursts: [1, 4, 2] },
  { name: "J3", bursts: [2, 2, 2] },
];
function uni(jobs) {               // one job in memory at a time
  let t = 0, busy = 0, line = "";
  for (const j of jobs)
    j.bursts.forEach((b, k) => {
      t += b; if (k % 2 === 0) busy += b;
      line += (k % 2 === 0 ? j.name[1] : ".").repeat(b);
    });
  return { t, busy, line };
}
function multi(jobs) {             // all jobs in memory, FCFS ready queue
  const st = jobs.map(j => ({ ...j, k: 0, readyAt: 0 }));
  let t = 0, busy = 0, line = "", done = 0;
  while (done < st.length) {
    const ready = st.filter(j => j.k < j.bursts.length && j.readyAt <= t)
                    .sort((a, b) => a.readyAt - b.readyAt);
    if (!ready.length) { t++; line += "."; continue; }   // CPU idle
    const j = ready[0], b = j.bursts[j.k];
    t += b; busy += b; line += j.name[1].repeat(b);
    if (++j.k < j.bursts.length) { j.readyAt = t + j.bursts[j.k]; j.k++; }
    else done++;
  }
  return { t, busy, line };
}

for (const [label, r] of [["Uniprogramming  ", uni(jobs)], ["Multiprogramming", multi(jobs)]]) {
  console.log(label, "CPU:", r.line);
  console.log("   total time =", r.t, " CPU busy =", r.busy,
              " utilisation =", (100 * r.busy / r.t).toFixed(1) + "%");
}

আউটপুট:

Uniprogramming   CPU: 11...12....2233..33
   total time = 19  CPU busy = 10  utilisation = 52.6%
Multiprogramming CPU: 112331.2233
   total time = 11  CPU busy = 10  utilisation = 90.9%

CPU সারির প্রতিটি অক্ষর এক একক সময়: অঙ্ক মানে সেই কাজ CPU-তে, . মানে CPU অলস। Uniprogramming-এর সারি 11...12....2233..33 — ঠিক ডায়াগ্রামের ধাপ ৩. Multiprogramming-এ 112331.2233 — একটিমাত্র অলস একক (t = 6), ডায়াগ্রামের ধাপ ৬-এর সাথে হুবহু মিল। multi() ফাংশন প্রতি মুহূর্তে দেখে কোন কাজ ready (readyAt <= t), যে আগে ready হয়েছে তাকে চালায়, আর কাজটি I/O-তে গেলে কখন ফিরবে (readyAt) লিখে রাখে। কেউ ready না থাকলে CPU এক একক অলস থাকে। এটি একটি সরল মডেল: context switch-এর খরচ ধরা হয়নি, আর ধরে নেওয়া হয়েছে I/O যন্ত্র নিয়ে কাজগুলোর মধ্যে কাড়াকাড়ি নেই।

কতগুলো কাজ মেমরিতে রাখলে CPU কতটা ব্যস্ত থাকে — 1 − pn

একটি সহজ সম্ভাবনার মডেল দিয়ে multiprogramming-এর লাভ মাপা যায়। ধরুন প্রতিটি কাজ তার সময়ের p অংশ I/O-র অপেক্ষায় কাটায় (p = 0.8 মানে ৮০% সময় অপেক্ষা)। মেমরিতে একসাথে n-টি কাজ আছে — একে বলে degree of multiprogramming. CPU অলস থাকে কেবল তখনই, যখন সব কাজ একসাথে অপেক্ষায়। কাজগুলো একে অপরের থেকে স্বাধীন ধরলে সেই সম্ভাবনা p × p × … × p = pn. তাই:

CPU utilisation ≈ 1 − pn

সমাধান করা উদাহরণ। একটি সার্ভারে RAM 8 GB; OS নিজে রাখে 2 GB, আর প্রতিটি কাজের লাগে 1.5 GB. প্রতিটি কাজ ৮০% সময় I/O-র অপেক্ষায় (p = 0.8).

  • কয়টি কাজ ধরবে? (8 − 2) ÷ 1.5 = 4টি। CPU ব্যবহার = 1 − 0.84 = 1 − 0.4096 = 0.5904 ≈ ৫৯.০%.
  • আরও 6 GB RAM কিনলে (মোট 14 GB): (14 − 2) ÷ 1.5 = 8টি কাজ। 0.88 ≈ 0.1678, তাই ব্যবহার ≈ ৮৩.২% — লাভ প্রায় ২৪ শতাংশ-বিন্দু।
  • আরও 6 GB (মোট 20 GB): 12টি কাজ। 0.812 ≈ 0.0687, ব্যবহার ≈ ৯৩.১% — এবার লাভ মাত্র প্রায় ১০ শতাংশ-বিন্দু।

একই পরিমাণ RAM দ্বিতীয়বার কিনে লাভ অর্ধেকেরও কম। একে বলে diminishing returns (ক্রমহ্রাসমান লাভ) — pn যত ছোট হয়, ১ থেকে তার দূরত্ব কমানো তত কঠিন। নিচের কোড পুরো টেবিলটি তৈরি করে:

// CPU utilisation = 1 - p^n  (p = fraction of time a job waits for I/O)
const util = (p, n) => 100 * (1 - Math.pow(p, n));

console.log(" n   p=0.2    p=0.5    p=0.8");
for (const n of [1, 2, 3, 4, 6, 8, 10]) {
  const row = [0.2, 0.5, 0.8].map(p => util(p, n).toFixed(1).padStart(6) + "%");
  console.log(String(n).padStart(2), row.join("  "));
}

// RAM example: OS keeps 2 GB, each job needs 1.5 GB, p = 0.8
for (const ram of [8, 14, 20]) {
  const n = Math.floor((ram - 2) / 1.5);
  console.log(`RAM ${ram} GB -> ${n} jobs -> CPU ${util(0.8, n).toFixed(1)}%`);
}

আউটপুট:

 n   p=0.2    p=0.5    p=0.8
 1   80.0%    50.0%    20.0%
 2   96.0%    75.0%    36.0%
 3   99.2%    87.5%    48.8%
 4   99.8%    93.8%    59.0%
 6  100.0%    98.4%    73.8%
 8  100.0%    99.6%    83.2%
10  100.0%    99.9%    89.3%
RAM 8 GB -> 4 jobs -> CPU 59.0%
RAM 14 GB -> 8 jobs -> CPU 83.2%
RAM 20 GB -> 12 jobs -> CPU 93.1%

তিনটি কলাম তিন ধরনের কাজ। p = 0.2 মানে কাজটি বেশিরভাগ সময় হিসাব করে — CPU-bound; একটিতেই CPU ৮০% ব্যস্ত, দুটিতে ৯৬%. p = 0.8 মানে কাজটি বেশিরভাগ সময় ডিস্ক বা নেটওয়ার্কের অপেক্ষায় — I/O-bound; একটিতে মাত্র ২০%, আর ৯০% ছুঁতে ১১টি কাজ লাগে — ১০টিতে মাত্র ৮৯.৩ শতাংশ। শেষ তিন লাইন ওপরের RAM-এর উদাহরণ — ৫৯.০%, ৮৩.২%, ৯৩.১%. টেবিলে “100.0%” আসলে ৯৯.৯৫%-এর বেশি কোনো মানকে এক দশমিকে গোল করা — 1 − pn কখনো পুরো ১ হয় না।

সূত্রটির অনুমানগুলো মনে রাখুন — পরীক্ষায় প্রায়ই জিজ্ঞেস করা হয়: (১) কাজগুলোর I/O-অপেক্ষা পরস্পর স্বাধীন — বাস্তবে সবাই একই ডিস্কের জন্য লাইনে দাঁড়ালে তা নয়; (২) CPU একটিই, আর ready কাজ থাকলে CPU কখনো অলস নয়; (৩) কাজ বদলের (context switch) খরচ শূন্য; (৪) সব কাজের p একই; (৫) মেমরিতে জায়গা থাকলেই কাজ আছে। তাই 1 − pn একটি মোটা দাগের অনুমান — প্রবণতা বোঝার জন্য চমৎকার, সঠিক সংখ্যার জন্য queueing theory লাগে। আর উল্টো দিকও আছে: মেমরিতে খুব বেশি কাজ ঠাসলে প্রত্যেকের ভাগে মেমরি কমে যায়, যার ফল thrashing — পর্ব ৩৭-এ দেখবেন।

Multiprogramming চালু করতে OS-কে হঠাৎ অনেক নতুন দায়িত্ব নিতে হলো: কোন কাজ মেমরির কোথায় থাকবে (memory management — মডিউল ৫), কে পরে CPU পাবে (CPU scheduling — মডিউল ৩), আর এক কাজ যেন অন্যের মেমরিতে হাত না দেয় (protection — মডিউল ৭)। মানচেস্টারের Atlas কম্পিউটার (১৯৬০-এর দশকের শুরু) আর IBM-এর OS/360 (১৯৬০-এর দশকের মাঝামাঝি) এই ধারণাকে বড় আকারে বাস্তবে আনে। আজকের OS-এর প্রায় সব মূল সমস্যার জন্ম এখানেই।

৩ · Time-sharing — অনেক মানুষ, একটি কম্পিউটার

Multiprogramming যন্ত্রকে ব্যস্ত রাখল, কিন্তু মানুষকে নয়। প্রোগ্রামার তখনো কার্ড জমা দিয়ে ঘণ্টার পর ঘণ্টা অপেক্ষা করেন। ১৯৬০-এর দশকের শুরুতে একটি নতুন প্রশ্ন উঠল: যদি অনেক মানুষ একসাথে আলাদা আলাদা terminal (কীবোর্ড আর স্ক্রিন/টেলিপ্রিন্টার) থেকে একটি কম্পিউটারের সাথে সরাসরি “কথা” বলতে পারেন?

উত্তর time-sharing: CPU-র সময়কে ছোট ছোট টুকরোয় (time quantum, পাঠ্যবইয়ের উদাহরণে সাধারণত কয়েক থেকে কয়েক ডজন মিলিসেকেন্ড) ভাগ করে প্রত্যেক ব্যবহারকারীকে পালা করে দেওয়া। পালা এত দ্রুত ঘোরে যে প্রত্যেকের মনে হয় যন্ত্রটি শুধু তাঁরই। এখানে চাবিকাঠি হলো একটি হার্ডওয়্যার timer interrupt: নির্দিষ্ট সময় পরপর ঘড়িটি CPU-কে থামিয়ে OS-কে ডাকে, আর OS চলতি কাজকে সরিয়ে (preemption) পরের জনকে CPU দেয়। কাজ বদলের এই প্রক্রিয়াই context switch — এর খুঁটিনাটি পর্ব ০৯-এ।

বিকেলের চায়ের দোকানে একজন দোকানি, সামনে দশজন খদ্দের। তিনি যদি প্রথমজনের পুরো অর্ডার — চা, পরোটা, ডিম ভাজি — শেষ করে তবেই দ্বিতীয়জনের দিকে তাকান, তাহলে দশম জন রেগে চলে যাবেন। দক্ষ দোকানি একজনের চায়ে চিনি দিয়েই পাশের জনকে পরোটা দেন, তারপর আরেকজনকে বিল বলেন — প্রত্যেকে কয়েক সেকেন্ডের মধ্যেই কিছু একটা “সাড়া” পান। মোট কাজের সময় একই, বরং হাত বদলের একটু বাড়তি সময়ও লাগে, কিন্তু কেউ অবহেলিত বোধ করেন না। Time-sharing-এর লক্ষ্য তাই CPU-কে ব্যস্ত রাখা নয়, response time কমানো।

নিচের ডায়াগ্রামে তিনজন ব্যবহারকারী — রিনা (A, তার কাজে CPU লাগবে মোট 5 ms), সাকিব (B, 3 ms) আর তানিয়া (C, 4 ms) — একসাথে কমান্ড দিলেন। Quantum 2 ms, পালা চলে গোল হয়ে (round robin). Context switch-এর খরচ এখানে শূন্য ধরা হয়েছে।

Gantt chartওপরে কে চলছে, নিচে সময় (ms)

            
প্রতিটি পালার পর
এই পালা
CPU-তে
বাকি CPU-সময় A / B / C
সারি (ready queue)
শেষ হয়েছে
  1. 0 → 2 ms: রিনা। সারির প্রথম A পেল 2 ms. তার বাকি 5 − 2 = 3 ms. Timer interrupt বাজল, OS তাকে সারির শেষে পাঠাল — সারি এখন B, C, A.
  2. 2 → 4 ms: সাকিব। B প্রথম সাড়া পেলেন মাত্র 2 ms-এ। তাঁর বাকি 3 − 2 = 1 ms; সারি C, A, B.
  3. 4 → 6 ms: তানিয়া। C-এর বাকি 4 − 2 = 2 ms. মাত্র 4 ms-এর মধ্যে তিনজনই অন্তত একবার CPU পেয়েছেন — terminal-এ বসা মানুষের চোখে এটি “সঙ্গে সঙ্গে সাড়া”. সারি আবার A, B, C.
  4. 6 → 8 ms: আবার রিনা। A-এর বাকি 3 − 2 = 1 ms; সারি B, C, A. দ্বিতীয় রাউন্ড চলছে।
  5. 8 → 9 ms: সাকিব শেষ। B-এর দরকার ছিল মাত্র 1 ms, তাই পুরো quantum না নিয়েই 9 ms-এ কাজ শেষ — CPU আগেভাগেই পরের জনের কাছে যায়, টাইমারের অপেক্ষা করে না। সারি C, A.
  6. 9 → 11 ms: তানিয়া শেষ। C-এর বাকি 2 ms ঠিক একটি quantum — 11 ms-এ শেষ। সারিতে শুধু A.
  7. 11 → 12 ms: রিনা শেষ। সবার কাজ শেষ 12 ms-এ — একটানা চালালেও মোট 5 + 3 + 4 = 12 ms-ই লাগত। পার্থক্য সাড়ায়: এখানে প্রথম সাড়া A 0, B 2, C 4 ms-এ; আগে-আসা-আগে-পাবে নিয়মে একটানা চালালে (A 0–5, B 5–8, C 8–12) হতো 0, 5 আর 8 ms. বাস্তবে প্রতিটি পালা বদলে কিছু মাইক্রোসেকেন্ড খরচ হয় — quantum খুব ছোট হলে সেই খরচই প্রধান হয়ে ওঠে (পর্ব ১৮-এ Round Robin-এর পূর্ণ হিসাব)।

১৯৬১ সালে MIT-তে Fernando Corbató-র দল CTSS (Compatible Time-Sharing System) প্রথম প্রদর্শন করে — প্রথম সফল time-sharing ব্যবস্থাগুলোর একটি; পরে এটি IBM 7094-এ নিয়মিত সেবা দিত। এর সাফল্যে ১৯৬০-এর দশকের মাঝামাঝি MIT, General Electric আর Bell Labs মিলে শুরু করে উচ্চাভিলাষী Multics — লক্ষ্য ছিল বিদ্যুৎ বা টেলিফোনের মতো একটি “computer utility”, যেখান থেকে গোটা শহর কম্পিউটিং সেবা নেবে। Multics জটিল আর ধীরগতির প্রকল্প হয়ে দাঁড়ায়; ১৯৬৯ সালে Bell Labs প্রকল্প ছেড়ে দেয়। কিন্তু Multics-এর বহু ধারণা — hierarchical file system, protection ring, dynamic linking — আধুনিক OS-এ ঢুকে যায়, আর শেষ Multics যন্ত্রটি বন্ধ হয় ২০০০ সালে। Corbató ১৯৯০ সালে Turing Award পান।

৪ · চারটি “multi”-র জট — নিখুঁত সংজ্ঞা

বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় সবচেয়ে বেশি গুলিয়ে ফেলা প্রশ্নগুলোর একটি: multiprogramming, multitasking, multiprocessing আর multithreading-এর পার্থক্য কী? শব্দগুলো কাছাকাছি, কিন্তু প্রত্যেকে একেবারে আলাদা প্রশ্নের উত্তর দেয়। প্রথমে দুটি ভিত্তি-শব্দ: process হলো চলমান একটি প্রোগ্রাম, নিজের মেমরিসহ (পর্ব ০৮); আর thread হলো একটি প্রসেসের ভেতরের একটি স্বাধীন নির্বাহ-ধারা (execution path), যা প্রসেসের মেমরি অন্য thread-এর সাথে ভাগ করে (পর্ব ১৪)।

শব্দনিখুঁত সংজ্ঞাযে প্রশ্নের উত্তরমূল লক্ষ্য
Multiprogrammingএকসাথে একাধিক প্রোগ্রাম মেমরিতে রাখা; চলতি কাজ অপেক্ষায় গেলে CPU আরেকটিকে দেওয়া। জোর করে কাজ থামানো (preemption) জরুরি নয়।মেমরিতে কয়টি কাজ?CPU ব্যবহার বাড়ানো
Multitasking (time-sharing)multiprogramming + timer interrupt দিয়ে নিয়মিত পালা বদল, যাতে প্রত্যেক কাজ (বা ব্যবহারকারী) দ্রুত সাড়া পায়।কে কখন CPU পায়, কতক্ষণ?response time কমানো
Multiprocessingএকটি কম্পিউটারে একাধিক CPU বা core — একই মুহূর্তে সত্যিই একাধিক নির্দেশ চলে।হার্ডওয়্যারে কয়টি CPU?সত্যিকারের সমান্তরাল গতি, নির্ভরযোগ্যতা
Multithreadingএকটি প্রসেসের ভেতরে একাধিক thread, যারা একই মেমরি ভাগ করে আলাদা আলাদা কাজ চালায়।এক প্রোগ্রামের ভেতরে কয়টি ধারা?এক প্রোগ্রামের ভেতরে কাজ ভাগ, সাড়া বজায় রাখা

এদের সম্পর্কটি বোঝার সবচেয়ে ভালো উপায় — এগুলো পরস্পর-বিরোধী নয়, আলাদা অক্ষের মাপ। আজকের একটি ল্যাপটপ চারটিই একসাথে করে: মেমরিতে শতাধিক প্রসেস (multiprogramming), timer দিয়ে পালা বদল (multitasking), ৮টি core (multiprocessing), আর ব্রাউজারের ভেতরে ডজন ডজন thread (multithreading). আবার ১৯৯০-এর দশকের একক-core কম্পিউটারেও multithreading সম্ভব ছিল — thread-গুলো পালা করে চলত, একসাথে নয়।

মূল ধারণা

Concurrency মানে একাধিক কাজ একই সময়কাল জুড়ে এগোচ্ছে — পালা করে হলেও। Parallelism মানে একাধিক কাজ একই মুহূর্তে চলছে — এর জন্য একাধিক CPU লাগে। একক-core-এ multitasking = concurrency, কিন্তু parallelism নয়। Multiprocessing ছাড়া parallelism সম্ভব নয়।

Cooperative বনাম preemptive multitasking

Multitasking দুই রকম। Cooperative-এ প্রতিটি প্রোগ্রাম নিজে থেকে মাঝে মাঝে CPU ছেড়ে দেয় — একটি প্রোগ্রাম আটকে গেলে (অসীম লুপে পড়লে) পুরো কম্পিউটার জমে যায়। Windows 3.x আর পুরোনো Mac OS (Mac OS 9 পর্যন্ত) মূলত এভাবে চলত। Preemptive-এ OS timer interrupt দিয়ে জোর করে CPU কেড়ে নেয়; কোনো প্রোগ্রাম চাইলেও CPU আটকে রাখতে পারে না। Unix প্রথম থেকেই preemptive ছিল; Windows-এ ৩২-বিট প্রোগ্রামের জন্য তা আসে Windows 95 আর NT-তে, Mac-এ আসে Mac OS X-এ। আজকের সব সাধারণ OS preemptive.

Multiprocessing-এর দুই নকশা

Symmetric multiprocessing (SMP)-এ সব CPU সমান — যেকোনো CPU OS-এর কোড আর যেকোনো প্রসেস চালাতে পারে, সবাই একই মেমরি দেখে। আজকের ল্যাপটপ আর সার্ভার এই নকশার। Asymmetric (AMP)-এ একটি প্রধান CPU কাজ বণ্টন করে, বাকিরা নির্দিষ্ট দায়িত্ব পালন করে — পুরোনো কিছু বড় যন্ত্রে আর এখনকার অনেক embedded চিপে (যেমন একটি core OS চালায়, আরেকটি শুধু রেডিও সামলায়) দেখা যায়। ফোনের big.LITTLE ধরনের চিপে core-গুলোর ক্ষমতা আলাদা হলেও সবাই একই OS চালায় — একে heterogeneous multiprocessing বলা হয়। একাধিক CPU থাকলে কোন প্রসেস কোন core-এ চলবে, সেই প্রশ্ন পর্ব ২০-এ।

আরও গভীরে: Linux kernel প্রসেস আর thread-কে আলাদা জিনিস হিসেবে দেখে না — দুটোই একটি task_struct, শুধু clone() system call-এর flag ঠিক করে দেয় কী কী ভাগ হবে (CLONE_VM দিলে মেমরি ভাগ, অর্থাৎ thread). Windows NT-তে উল্টো: process হলো সম্পদের পাত্র, আর schedule হয় শুধু thread. আবার হার্ডওয়্যারেও “multithreading” আছে — Intel-এর Hyper-Threading বা সাধারণভাবে SMT-তে একটি physical core দুটি thread-এর register রাখে, ফলে OS একটি core-কে দুটি “logical CPU” হিসেবে দেখে। এজন্যই /proc/cpuinfo-র processor সংখ্যা প্রায়ই physical core-এর দ্বিগুণ।

৫ · ব্যক্তিগত কম্পিউটার, নেটওয়ার্ক আর distributed OS

১৯৭০-এর দশকে microprocessor আসার পর কম্পিউটার ঘর থেকে নেমে এলো টেবিলে। Altair 8800 (১৯৭৫), Apple II (১৯৭৭), IBM PC (১৯৮১) — এক মানুষ, এক যন্ত্র। মজার ব্যাপার, প্রথম দিকের PC OS-গুলো (CP/M, MS-DOS) ছিল আবার uniprogramming আর প্রায় সুরক্ষাহীন — এক ব্যবহারকারী, একটি প্রোগ্রাম, মেমরি-সুরক্ষা নেই। কারণ লক্ষ্য বদলে গিয়েছিল: যন্ত্র এখন সস্তা, মানুষের সময় দামি। তাই অগ্রাধিকার পেল সহজ ব্যবহার — Xerox PARC-এর Alto-তে (১৯৭৩) জন্ম নেওয়া graphical user interface (GUI), যা জনপ্রিয় করে Apple Macintosh (১৯৮৪) আর পরে Windows.

যন্ত্র যখন শক্তিশালী হলো আর ইন্টারনেটে যুক্ত হলো, তখন বড় যন্ত্রের পুরোনো সমস্যাগুলো — একাধিক প্রোগ্রাম, সুরক্ষা, ভাইরাস — আবার ফিরে এলো। তাই আজকের PC OS ভেতরে আসলে ১৯৬০-৭০-এর time-sharing OS-এর বংশধর। ইতিহাস এখানে একটি বৃত্ত: প্রতিটি নতুন ধরনের যন্ত্র (mainframe → minicomputer → PC → ফোন → ঘড়ি) প্রথমে সরল OS দিয়ে শুরু হয়, তারপর ধীরে ধীরে বড় যন্ত্রের সব ধারণা আবার শেখে।

Network OS বনাম distributed OS

একাধিক কম্পিউটার নেটওয়ার্কে জুড়লে দুই ধরনের নকশা সম্ভব, আর পরীক্ষায় দুটির পার্থক্য প্রায়ই চাওয়া হয়:

Network OS

প্রতিটি যন্ত্রে নিজের পূর্ণ OS. ব্যবহারকারী জানেন যে অনেক যন্ত্র আছে, আর স্পষ্টভাবে অন্য যন্ত্রে লগইন করেন বা তার ফাইল/প্রিন্টার ব্যবহার করেন। সরল, প্রতিটি যন্ত্র স্বাধীন — একটি বন্ধ হলেও বাকিরা চলে।

Novell NetWare, Windows Server, Linux + NFS/SSH

Distributed OS

অনেক যন্ত্র মিলে ব্যবহারকারীর চোখে একটি কম্পিউটার — কোন যন্ত্রে প্রসেস চলছে, ফাইল কোথায় আছে, তা লুকানো (transparency). শক্তিশালী ধারণা, কিন্তু নকশা অনেক কঠিন: আংশিক ব্যর্থতা, ঘড়ির অমিল, নেটওয়ার্কের দেরি।

Amoeba, Plan 9 (মূলত গবেষণা)

একটি distributed system-এ বিশুদ্ধ distributed OS বাস্তবে খুব কমই সফল হয়েছে। তার বদলে আজকের দুনিয়া চলে মাঝামাঝি পথে: প্রতিটি যন্ত্রে সাধারণ OS (প্রায় সবসময় Linux), আর তার ওপরে একটি স্তর — Kubernetes, Hadoop, distributed database — যা অনেক যন্ত্রকে একসাথে পরিচালনা করে। এই স্তরগুলোকে কখনো কখনো “ডেটা সেন্টারের OS” বলা হয়। বড় ই-কমার্স সাইট বা মোবাইল ব্যাংকিং সেবার পেছনে ঠিক এমন শত শত যন্ত্রের ক্লাস্টার কাজ করে। পর্ব ৫৩-এ এর OS-দিকটি দেখবেন।

৬ · Real-time আর embedded OS — সময়ই যেখানে সঠিকতা

সাধারণ OS-এর কাছে আমরা চাই “গড়ে দ্রুত”. কিন্তু কিছু সিস্টেমে গড় দিয়ে চলে না। গাড়ির airbag-কে ধাক্কা লাগার পর কয়েক ডজন মিলিসেকেন্ডের মধ্যে ফুলতেই হবে — এক সেকেন্ড পরে ফুললে সেটি সঠিক উত্তর নয়, ভুল উত্তর। Real-time OS (RTOS)-এ তাই সঠিকতা দুই অংশের: ফল ঠিক হতে হবে, এবং নির্দিষ্ট সময়সীমার (deadline) মধ্যে আসতে হবে।

বাস টার্মিনালের সময়সূচির কথা ভাবুন। ঢাকা থেকে রাত ১০টার বাস ছাড়বে — যাত্রীর কাছে “গড়ে বাস দ্রুত চলে” কথাটির কোনো দাম নেই; দাম “১০টায় ছাড়বে কি না” তার। আবার রেলক্রসিংয়ের গেট নামানো আরও কঠোর: ট্রেন আসার আগে নামতেই হবে, এক সেকেন্ড দেরিও দুর্ঘটনা। প্রথমটি soft, দ্বিতীয়টি hard real-time.

ধরনDeadline মিস করলেউদাহরণ
Hard real-timeসিস্টেম ব্যর্থ — প্রাণ বা বড় সম্পদের ঝুঁকি। একটি মিসও গ্রহণযোগ্য নয়।airbag, ABS ব্রেক, pacemaker, বিমানের flight control, কারখানার রোবট-বাহু
Firm real-timeদেরিতে আসা ফল মূল্যহীন, ফেলে দেওয়া হয়; মাঝে মাঝে মিস সহ্য করা যায়।উৎপাদন লাইনের ক্যামেরা-পরীক্ষা, কিছু সংকেত-প্রক্রিয়াকরণ
Soft real-timeমান কমে যায়, কিন্তু সিস্টেম চলে; দেরিতে আসা ফলেরও কিছু দাম আছে।ভিডিও কল, YouTube/গান বাজানো, অনলাইন গেম

RTOS-এর নকশার মূল কথা নির্ধারণযোগ্যতা (determinism) — সবচেয়ে খারাপ অবস্থায় (worst case) কতক্ষণ লাগবে, তা আগে থেকে জানা ও প্রমাণ করা যায়। এজন্য RTOS সাধারণত কঠোর priority-ভিত্তিক preemptive scheduling ব্যবহার করে, interrupt দ্রুত সামলায়, আর অনির্ধারিত সময় নেয় এমন কৌশল (যেমন demand paging বা অনিয়ন্ত্রিত মেমরি বরাদ্দ) এড়িয়ে চলে। Trade-off পরিষ্কার: গড় গতি আর সুবিধা কম, কিন্তু নিশ্চয়তা বেশি। পরিচিত RTOS: VxWorks, QNX, FreeRTOS, Zephyr. সাধারণ Linux-কেও আংশিক real-time করার PREEMPT_RT প্যাচ বহু বছর পর ২০২৪ সালে মূল kernel-এ (Linux 6.12) যুক্ত হয় — তবু hard real-time নিশ্চয়তার জন্য সাধারণত বিশেষায়িত RTOS-ই বেছে নেওয়া হয়। Rate-monotonic আর EDF scheduling-এর গণিত পর্ব ২০-এ।

Embedded OS

আপনার বাসার ওয়াশিং মেশিন, মাইক্রোওয়েভ, Wi-Fi রাউটার, স্মার্ট টিভি, ডিজিটাল মিটার — প্রত্যেকটির ভেতরে একটি কম্পিউটার আছে যা নির্দিষ্ট একটি কাজের জন্য বানানো। এগুলোকে বলে embedded system. এদের OS-এর বৈশিষ্ট্য: খুব কম মেমরি (কখনো মাত্র কয়েক কিলোবাইট), কম বিদ্যুৎ, ব্যবহারকারীর সাথে সামান্য বা কোনো ইন্টারফেস নেই, আর বছরের পর বছর রিস্টার্ট ছাড়া চলা। ছোট যন্ত্রে প্রায়ই OS-ই থাকে না — একটি লুপ সরাসরি হার্ডওয়্যার চালায় (bare-metal); একটু বড় হলে FreeRTOS বা Zephyr-এর মতো RTOS; আর রাউটার বা স্মার্ট টিভির মতো বড় যন্ত্রে প্রায়ই embedded Linux (যেমন OpenWrt). Embedded মানে সবসময় real-time নয় — রাউটারের deadline কঠোর নয়, কিন্তু pacemaker-এর আছে।

৭ · মোবাইল আর ক্লাউড — হাতের ফোন থেকে ডেটা সেন্টার

মোবাইল OS

২০০০-এর দশকে Symbian, BlackBerry OS আর Windows Mobile-এর মতো ফোন-OS ছিল। কিন্তু মোড় ঘোরায় ২০০৭ সালে Apple-এর iPhone (তার OS তখন “iPhone OS”, পরে iOS) আর ২০০৮ সালে প্রথম Android ফোন (HTC Dream, যা T-Mobile G1 নামেও পরিচিত)। বিভিন্ন জরিপ অনুযায়ী আজ বাংলাদেশসহ বেশিরভাগ দেশে স্মার্টফোনের বড় অংশ চলে Android-এ। মোবাইল OS-এর অগ্রাধিকারগুলো ডেস্কটপ থেকে আলাদা:

  • ব্যাটারি সবার আগে: পর্দা বন্ধ হলে অ্যাপকে ঘুম পাড়িয়ে রাখা, CPU-র গতি কমানো, পেছনের কাজ একসাথে জড়ো করে চালানো।
  • মেমরি কম, swap প্রায় নেই: জায়গা ফুরোলে OS পেছনের অ্যাপকে নিজেই বন্ধ করে দেয় — Android-এ low-memory killer; অ্যাপকে তাই যেকোনো মুহূর্তে বন্ধ হওয়ার জন্য তৈরি থাকতে হয়।
  • কঠোর নিরাপত্তা: প্রতিটি অ্যাপ আলাদা sandbox-এ; ক্যামেরা, লোকেশন, কন্টাক্ট — প্রতিটির জন্য আলাদা অনুমতি। আপনার মোবাইল ব্যাংকিং অ্যাপের ডেটা অন্য অ্যাপ পড়তে পারে না।
  • স্পর্শ, সেন্সর আর রেডিও: touch screen, GPS, accelerometer, মোবাইল নেটওয়ার্ক — সবই OS-এর পরিচালনায়।

ক্লাউড আর virtualization

শেষ বড় পরিবর্তনটি এসেছে ডেটা সেন্টারে। একটি শক্তিশালী সার্ভারকে একজন গ্রাহককে দিলে বেশিরভাগ সময় সেটি অলস থাকে — multiprogramming-এর পুরোনো সমস্যা, শুধু বড় আকারে! সমাধানও পুরোনো চিন্তার নতুন রূপ: একটি যন্ত্রে অনেকগুলো virtual machine (VM) চালানো, প্রত্যেকটি ভাবে সে একটি পূর্ণ কম্পিউটার, নিজের আলাদা OS-সহ। VM-গুলোকে পরিচালনা করে hypervisor:

  • Type 1 (bare-metal): সরাসরি হার্ডওয়্যারের ওপর চলে, নিজেই একরকম ছোট OS — VMware ESXi, Xen, Microsoft Hyper-V; Linux-এর KVM kernel-কেই hypervisor বানিয়ে দেয়। ক্লাউড ডেটা সেন্টার এগুলোর ওপর চলে।
  • Type 2 (hosted): আপনার সাধারণ OS-এর ওপর একটি অ্যাপ হিসেবে চলে — VirtualBox, VMware Workstation. শেখা আর পরীক্ষার জন্য সুবিধাজনক।

ধারণাটি নতুন নয়: IBM ১৯৬০-এর দশকের শেষে CP/CMS আর ১৯৭২ সালে VM/370-এ virtual machine চালাত। x86 যন্ত্রে এটি জনপ্রিয় হয় ১৯৯০-এর দশকের শেষে VMware দিয়ে; ২০০৩ সালে আসে Xen, আর ২০০৭ সালে KVM Linux kernel-এর অংশ হয়। ২০০৬ সালে Amazon EC2 ঘণ্টা ধরে VM ভাড়া দেওয়া শুরু করলে “cloud computing” মূলধারায় আসে। এরপর আসে আরও হালকা container (Docker, ২০১৩) — এখানে প্রতিটি অ্যাপের আলাদা OS নেই, সবাই একটিই host kernel ভাগ করে, শুধু চোখে আলাদা দেখায়। পার্থক্যটি নিচের কোডে নিজেই দেখবেন। VM আর container-এর ভেতরের কাজ পর্ব ৫০–৫২-তে।

এবার দেখা যাক আপনার কোড যে Linux যন্ত্রে চলছে, তার kernel কোনটি আর কয়টি CPU আছে। নিচের bash কমান্ডগুলো একটি সার্ভারের container-এ চলে:

# এই যন্ত্রের kernel আর CPU — মানগুলো যন্ত্রভেদে আলাদা হবে
echo "Kernel name    : $(uname -s)"
echo "Kernel release : $(uname -r)"
echo "Machine (arch) : $(uname -m)"
echo "nproc          : $(nproc)"
echo "/proc/cpuinfo  : $(grep -c '^processor' /proc/cpuinfo) processor entries"
grep -m1 'model name' /proc/cpuinfo
cut -d' ' -f1-3 /proc/version
grep '^PRETTY_NAME' /etc/os-release

একটি রানে আউটপুট এসেছিল:

Kernel name    : Linux
Kernel release : 6.8.0-137-generic
Machine (arch) : x86_64
nproc          : 2
/proc/cpuinfo  : 2 processor entries
model name	: AMD EPYC-Rome Processor
Linux version 6.8.0-137-generic
PRETTY_NAME="Ubuntu 24.04.1 LTS"

এই সংখ্যাগুলো যন্ত্রভেদে বদলাবে — আপনি চালালে অন্য version বা অন্য CPU দেখতে পারেন। uname -r দেখায় kernel-এর release (6.8.0-...-generic মানে Linux 6.8, Ubuntu-র বানানো রূপ)। nproc বলে এই প্রসেস কয়টি CPU ব্যবহার করতে পারে, আর /proc/cpuinfo তালিকা দেয় kernel যে কয়টি logical CPU দেখে — এখানে দুটোই 2. দুটো সবসময় মেলে না: taskset -c 0 nproc চালালে প্রসেস একটিমাত্র CPU-তে বাঁধা পড়ে, nproc বলবে 1, অথচ cpuinfo বদলাবে না। আবার container-এ CPU-কোটা দিলেও (যেমন Docker-এর --cpus=1) cpuinfo-তে host-এর সব CPU-ই দেখা যায়। সবচেয়ে মজার লাইন শেষটি: userland বলছে Ubuntu 24.04.1 LTS — কিন্তু kernel তো container-এর নিজের নয়, host যন্ত্রের! Container-এর ভেতরের সব প্রোগ্রাম host-এর একটিই kernel ভাগ করে; শুধু ফাইলগুলো (userland) আলাদা। এটাই VM আর container-এর মূল পার্থক্য।

অন্য OS-এ একই তথ্য দেখার কমান্ড আলাদা — Linux-এর কমান্ড সেখানে সরাসরি চলবে না:

PS> [System.Environment]::OSVersion.Version
Major  Minor  Build  Revision
-----  -----  -----  --------
10     0      26100  0
PS> $env:NUMBER_OF_PROCESSORS
8

Windows 11-ও নিজেকে ভেতরে “10.0” বলে, আলাদা হয় শুধু build নম্বরে (Windows 11 হলে সাধারণত 22000 বা তার বেশি) — এটা ইচ্ছাকৃত, পুরোনো প্রোগ্রাম যাতে version দেখে বিভ্রান্ত না হয়। macOS-এ Terminal-এ uname -r দেয় Darwin kernel-এর version (macOS-এর বাজারি নম্বর নয়), আর CPU সংখ্যা দেখায় sysctl -n hw.ncpu. ওপরের সংখ্যাগুলো একটি উদাহরণমাত্র।

সব প্রজন্ম এক নজরে

নিচের ডায়াগ্রামে প্রতিটি যুগের মূল সমস্যা আর OS-এর জবাব একসাথে দেখুন। লক্ষ্য করুন, প্রতিটি জবাব পরের যুগের নতুন সমস্যার জন্ম দিয়েছে:

সময়রেখানিচের সারিটি এই ধাপের যুগ

            
এই যুগে
মূল সমস্যা
OS-এর জবাব
উদাহরণ
  1. ১৯৪০-এর দশক: OS নেই। প্রোগ্রামার যন্ত্রের সময় বুক করে নিজেই সুইচ, প্লাগবোর্ড বা কার্ড দিয়ে প্রোগ্রাম চালাতেন। একজনের পর একজন — serial processing.
  2. ১৯৫০-এর দশক: batch. অপারেটর একই ধরনের কাজ একসাথে সাজান, resident monitor একটির পর একটি চালায়। যন্ত্রের সময় বাঁচল, কিন্তু প্রোগ্রামারের turnaround হলো ঘণ্টা বা দিন।
  3. ১৯৬০-এর দশক: multiprogramming. মেমরিতে কয়েকটি কাজ — একটি I/O-তে গেলে আরেকটি CPU পায়। CPU ব্যবহার বাড়ল, সাথে এলো memory management, scheduling আর protection-এর সমস্যা।
  4. ১৯৬০-৭০-এর দশক: time-sharing. Timer interrupt দিয়ে ছোট ছোট পালা — অনেক মানুষ terminal থেকে একসাথে। CTSS থেকে Multics, আর Multics-এর ছাই থেকে Unix.
  5. ১৯৭০-৮০-এর দশক: ব্যক্তিগত কম্পিউটার। যন্ত্র সস্তা, মানুষের সময় দামি — অগ্রাধিকার পেল সহজ ব্যবহার আর GUI. প্রথম PC OS আবার uniprogramming আর সুরক্ষাহীন ছিল।
  6. ১৯৮০-৯০-এর দশক: নেটওয়ার্ক। যন্ত্রগুলো জুড়ে গেল — network OS দিয়ে ফাইল আর প্রিন্টার ভাগ, distributed OS-এর স্বপ্ন “অনেক যন্ত্র = এক কম্পিউটার”. ইন্টারনেট সবকিছুকে সংযুক্ত করল।
  7. ২০০৭ থেকে: মোবাইল। iPhone আর Android — কম্পিউটার পকেটে। নতুন অগ্রাধিকার ব্যাটারি, স্পর্শ আর প্রতিটি অ্যাপের আলাদা sandbox.
  8. ২০০০-এর দশকের মাঝামাঝি থেকে: ক্লাউড। একটি সার্ভারে অনেক VM বা container — ১৯৬০-এর দশকের “computer utility” স্বপ্ন অবশেষে বাস্তব। এক অর্থে ইতিহাস ঘুরে আবার time-sharing-এ ফিরেছে, শুধু terminal-এর জায়গায় এখন ইন্টারনেট।

৮ · দুটি বড় বংশ — Unix আর Windows

আজকের প্রায় সব কম্পিউটার, ফোন আর সার্ভার দুটি বংশের কোনো একটি থেকে এসেছে। বংশলতিকা জানা থাকলে বুঝবেন কেন Mac-এর Terminal-এ Linux-এর মতো কমান্ড চলে, অথচ Windows-এ চলে না।

Multics (১৯৬০-এর দশক, MIT + GE + Bell Labs)
  └─ Unix — Bell Labs, ১৯৬৯ (Ken Thompson, Dennis Ritchie, PDP-7)
       ├─ ১৯৭৩: kernel C ভাষায় নতুন করে লেখা
       ├─ BSD — UC Berkeley, ১৯৭০-এর দশকের শেষ থেকে
       │    ├─ FreeBSD, NetBSD, OpenBSD
       │    └─ NeXTSTEP (BSD + Mach) ─┐
       ├─ System V — AT&T, ১৯৮৩     │
       │    └─ Solaris, AIX, HP-UX     │
       └─ POSIX মান — IEEE, ১৯৮৮      │
                                       ▼
            macOS / iOS — Darwin, XNU kernel (Mach + BSD)

GNU প্রকল্প (১৯৮৩) + Linux kernel (১৯৯১)
  └─ GNU/Linux distro: Debian, Ubuntu, Fedora, RHEL …
  └─ Android — Linux kernel-এর ওপর (২০০৮)
MS-DOS (১৯৮১, IBM PC)
  └─ Windows 1.0 – 3.x (১৯৮৫–৯২) — DOS-এর ওপর গ্রাফিক্যাল স্তর
       └─ Windows 95 / 98 / ME (১৯৯৫–২০০০) — “9x”, এখনো DOS-নির্ভর

Windows NT 3.1 (১৯৯৩) — একেবারে নতুন kernel (Dave Cutler-এর দল)
  └─ NT 4.0 → Windows 2000 (ব্যবসার জন্য)
       └─ Windows XP (২০০১) — ঘরের আর অফিসের দুই ধারা এক হলো NT-তে
            └─ Vista → 7 → 8 → 10 (২০১৫) → 11 (২০২১)
                 └─ সবই NT kernel-এর উত্তরসূরি

Unix: ছোট, সরল, বহনযোগ্য

Multics থেকে বেরিয়ে আসার পর ১৯৬৯ সালে Bell Labs-এর Ken Thompson আর Dennis Ritchie একটি অব্যবহৃত PDP-7 যন্ত্রে অনেক ছোট একটি OS লেখেন। নামটি Multics-এর ওপর একটি রসিকতা — “Unics”, পরে Unix. এর দর্শন: প্রতিটি প্রোগ্রাম একটি কাজ ভালোভাবে করবে, আর ছোট প্রোগ্রামগুলো pipe দিয়ে জুড়ে বড় কাজ হবে (পর্ব ০৩ আর ১২-এ দেখবেন)। ১৯৭৩ সালে Unix-এর kernel নতুন তৈরি C ভাষায় আবার লেখা হয় — তখনকার দিনে OS লেখা হতো assembly-তে, তাই এটি ছিল বিপ্লব। ফল: Unix যেকোনো নতুন যন্ত্রে নেওয়া সহজ হলো, শুধু C compiler থাকলেই চলে।

AT&T তখন আইনগত কারণে কম্পিউটার ব্যবসায় নামতে পারছিল না, তাই বিশ্ববিদ্যালয়গুলোকে সামান্য খরচে source code-সহ Unix দেয়। UC Berkeley তাতে নিজেদের উন্নতি যোগ করে BSD তৈরি করে — virtual memory, আর ইন্টারনেটের TCP/IP-এর একটি অত্যন্ত প্রভাবশালী বাস্তবায়ন। অন্যদিকে AT&T বাণিজ্যিক System V (১৯৮৩) আনে। নানা কোম্পানির নিজস্ব Unix (Solaris, AIX, HP-UX…) পরস্পরের সাথে পুরো মিলত না; তাই ১৯৮৮ সালে IEEE POSIX মান প্রকাশ করে — একটি সাধারণ system call আর shell-এর চুক্তি, যা মানলে প্রোগ্রাম সব Unix-ধাঁচের OS-এ চলে। এই কোর্সের fork, exec, pthread — সবই POSIX.

GNU, Linux আর বাকি গল্প

১৯৮৩ সালে Richard Stallman ঘোষণা দেন GNU প্রকল্পের — সম্পূর্ণ মুক্ত (free software) একটি Unix-সদৃশ OS. ১৯৯০ সালের মধ্যে compiler (GCC), shell, editor, library — প্রায় সব তৈরি, শুধু kernel (Hurd) পিছিয়ে ছিল। ১৯৯১ সালে ফিনল্যান্ডের ছাত্র Linus Torvalds শখের প্রকল্প হিসেবে একটি kernel লিখে ইন্টারনেটে ঘোষণা দেন। GNU-র টুল আর Linux kernel মিলে তৈরি হলো একটি পূর্ণ মুক্ত OS — অনেকে একে GNU/Linux বলেন। আজ Linux চলে বেশিরভাগ ওয়েব সার্ভার আর ক্লাউড VM-এ, বিশ্বের শীর্ষ supercomputer-গুলোতে, আর kernel হিসেবে প্রতিটি Android ফোনে। (Android-এ Linux kernel থাকলেও userland GNU নয় — সেখানে Google-এর নিজস্ব library আর runtime.)

অন্যদিকে Apple থেকে বেরিয়ে Steve Jobs NeXT কোম্পানিতে তৈরি করেন NeXTSTEP — Mach microkernel আর BSD-র অংশ মিলিয়ে। ১৯৯৭ সালে Apple NeXT কিনে নেয়, আর NeXTSTEP থেকে জন্ম নেয় Mac OS X (২০০১)। তার কেন্দ্র Darwin, যার kernel XNU — Mach আর BSD-র সংকর। iOS, iPadOS, watchOS — সবই এই একই কেন্দ্রের ওপর। তাই macOS-এর বেশ কিছু সংস্করণ আনুষ্ঠানিক UNIX সনদ পেয়েছে, আর Linux “Unix-সদৃশ” — কোডে Unix-এর বংশধর নয়, কিন্তু আচরণে ও মানে (POSIX) কাছাকাছি।

Windows: দুটি ধারা, তারপর এক

Microsoft-এর যাত্রা শুরু ১৯৮১ সালে IBM PC-র জন্য MS-DOS দিয়ে — একক ব্যবহারকারী, একক কাজ, মেমরি-সুরক্ষা নেই। Windows 1.0 থেকে 3.x ছিল DOS-এর ওপর একটি গ্রাফিক্যাল স্তর। Windows 95, 98 আর ME (একসাথে “Windows 9x”) অনেক আধুনিক হলেও ভেতরে DOS-এর উত্তরাধিকার বয়ে চলত — একটি খারাপ প্রোগ্রাম পুরো সিস্টেম ফেলে দিতে পারত, সেই কুখ্যাত “নীল পর্দা” প্রায়ই দেখা যেত।

সমান্তরালে Microsoft DEC-এর VMS OS-এর অভিজ্ঞ প্রকৌশলী Dave Cutler-কে নিয়ে শূন্য থেকে নতুন একটি OS বানায় — Windows NT (১৯৯৩ সালে NT 3.1). NT শুরু থেকেই ৩২-বিট, preemptive multitasking, প্রতিটি প্রসেসের সুরক্ষিত মেমরি, ফাইলে অনুমতির ব্যবস্থা (NTFS), আর একাধিক CPU-র সমর্থন নিয়ে আসে। প্রায় এক দশক দুটি ধারা পাশাপাশি চলে — ঘরের জন্য 9x, অফিস ও সার্ভারের জন্য NT/2000. ২০০১ সালে Windows XP দিয়ে ঘরের ব্যবহারকারীরাও NT kernel-এ চলে আসেন। আজকের Windows 10 আর 11 সেই NT-রই উত্তরসূরি — ভেতরের খুঁটিনাটি পর্ব ৫৬-তে।

পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:

  • Multiprogramming আর multitasking-এর পার্থক্য? — Multiprogramming মেমরিতে অনেক কাজ রেখে CPU ব্যবহার বাড়ায়; multitasking তার সাথে timer দিয়ে নিয়মিত পালা বদলে response time কমায়।
  • p = 0.8 হলে ৪টি কাজে CPU utilisation কত? — 1 − 0.84 = 1 − 0.4096 ≈ ৫৯%; অনুমান: কাজগুলোর I/O-অপেক্ষা স্বাধীন, একক CPU, switch-খরচ শূন্য।
  • Hard আর soft real-time-এর উদাহরণ দিন। — Hard: airbag, pacemaker (deadline মিস = ব্যর্থতা); soft: ভিডিও কল (মিস = মান কমা)।
  • Network OS আর distributed OS-এর পার্থক্য? — Network OS-এ ব্যবহারকারী আলাদা যন্ত্র সম্পর্কে জানেন; distributed OS অনেক যন্ত্রকে একটি কম্পিউটার হিসেবে দেখায় (transparency).
  • Android কোন kernel-এ চলে, macOS কোনটিতে? — Android: Linux kernel; macOS: Darwin-এর XNU (Mach + BSD).

৯ · AI-এর যুগে — OS-এর ইতিহাস আর কমান্ড যাচাই করা

AI-কে “Windows NT কবে এসেছে” বা “আমার CPU কয়টি দেখার কমান্ড কী” জিজ্ঞেস করলে সাধারণত দ্রুত উত্তর পাবেন। কিন্তু এই বিষয়ে AI-এর কয়েকটি পরিচিত দুর্বলতা আছে, যা জানা থাকলে আপনি সময় ও ঝামেলা দুটোই বাঁচাবেন।

AI-এর ভুলউদাহরণকীভাবে ধরবেন
ভুল OS বা distro-র কমান্ডWindows-এ চাইলেন, দিল lscpu; Fedora-তে দিল aptপ্রশ্নেই OS আর version লিখুন; কমান্ডটি man বা --help দিয়ে আছে কি না দেখুন
সাল বা নাম গুলিয়ে ফেলাUnix-এর C-রূপান্তর ১৯৬৯ বলা, বা Windows 2000-কে 9x ধারার বলাঅন্তত দুটি নির্ভরযোগ্য উৎস মেলান — প্রকল্পের নিজস্ব ইতিহাস-পাতা, পাঠ্যবই
পুরোনো kernel-তথ্য“Linux-এর scheduler CFS” — নতুন kernel-এ EEVDF এসেছে (পর্ব ২১)নিজের যন্ত্রে uname -r দেখে সেই version-এর kernel ডকুমেন্টেশন পড়ুন
সূত্রের অনুমান বাদ দেওয়া বা হিসাবে ভুল1 − pn-কে নিখুঁত বলা, বা 0.84-এর ভুল মাননিজে হাতে বা ছোট কোডে আবার হিসাব করুন; অনুমানগুলো জিজ্ঞেস করুন
অনিরাপদ পরামর্শ“কাজ না হলে sudo দিয়ে চালান” বা chmod 777কেন admin-ক্ষমতা লাগবে জিজ্ঞেস করুন; ক্ষমতা যত কম, তত নিরাপদ (পর্ব ৪৭)

AI-কে এমনভাবে প্রশ্ন করুন যাতে সে আপনার পরিবেশ জানে আর নিজের উত্তর যাচাইয়ের পথও দেখায়:

আমি Ubuntu 24.04 (Linux kernel 6.8) ব্যবহার করি, নিজের ল্যাপটপে, sudo ছাড়া। ১. আমার kernel version, logical CPU সংখ্যা আর physical core সংখ্যা দেখার কমান্ড দাও — প্রতিটি কমান্ড কোন ফাইল বা system call থেকে তথ্য নেয়, এক লাইনে বলো। ২. nproc আর /proc/cpuinfo-র সংখ্যা কখন আলাদা হতে পারে, উদাহরণসহ বলো। ৩. কোনো কমান্ডে sudo লাগলে আলাদা করে চিহ্নিত করো আর কেন লাগবে বলো। ৪. যে তথ্যে তুমি নিশ্চিত নও, সেটি স্পষ্টভাবে "অনিশ্চিত" লিখে দিও।

AI-এর দেওয়া ইতিহাস বা কমান্ড হাতে পেলে — যাচাইয়ের চেকলিস্ট

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

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। ইতিহাস এখানে গল্প নয়, নকশার সিদ্ধান্তের ভাণ্ডার।

প্র ০১Multics তো বাণিজ্যিকভাবে ব্যর্থ — তাহলে কেন বলা হয়, আধুনিক OS-এর প্রায় সবকিছুর বীজ এখানে?

Multics-কে “ব্যর্থ” বলা অর্ধসত্য। লক্ষ্যের তুলনায় এটি দেরিতে এসেছে, জটিল ছিল, আর বিশেষ হার্ডওয়্যার (GE-645) লাগত — তাই ব্যাপকভাবে ছড়ায়নি। ১৯৬৯ সালে Bell Labs সরে দাঁড়ায়। কিন্তু ধারণার দিক থেকে Multics অসাধারণ সফল:

  • Hierarchical file system: ফোল্ডারের ভেতরে ফোল্ডার, / দিয়ে পথ — আজ সব OS-এ।
  • Protection ring: কোড কতটা বিশ্বাসযোগ্য তা অনুযায়ী স্তর। আজকের x86 CPU-র ring 0 (kernel) আর ring 3 (user) এই ধারণার বংশধর (পর্ব ০৫ আর ৪৮)।
  • Dynamic linking আর মেমরিতে ফাইল ম্যাপ করা: আজকের .so/.dll আর mmap-এর পূর্বসূরি।
  • উচ্চস্তরের ভাষায় OS লেখা: Multics লেখা হয়েছিল PL/I-এ — Unix-এর C-তে লেখার অনেক আগে।
  • নিরাপত্তা নিয়ে গুরুতর চিন্তা: পরে মার্কিন প্রতিরক্ষা বিভাগের নিরাপত্তা-মূল্যায়নে Multics উঁচু মান পায়।

সবচেয়ে বড় উত্তরাধিকার মানুষের মাধ্যমে: Thompson আর Ritchie Multics-এর অভিজ্ঞতা নিয়েই Unix বানান — অনেক ধারণা রেখে, কিন্তু জটিলতা ঝেড়ে ফেলে। “Unix” নামটিই Multics-এর ওপর রসিকতা। আর শেষ Multics যন্ত্রটি বন্ধ হয় ২০০০ সালে — তিন দশকেরও বেশি সেবা দিয়ে, যা কোনো “ব্যর্থ” সিস্টেমের পক্ষে বিরল।

এখান থেকে প্রকৌশলের একটি গুরুত্বপূর্ণ শিক্ষা মেলে, যাকে Fred Brooks বলেছিলেন “second-system effect” — প্রথম সফল সিস্টেমের পর দ্বিতীয়টিতে সব ইচ্ছা একসাথে ঢোকানোর লোভ। CTSS-এর পর Multics সেই ফাঁদে কিছুটা পড়েছিল; Unix জিতেছিল কম করে, কিন্তু ভালোভাবে করে।

মূল উপলব্ধি: একটি সিস্টেমের সাফল্য শুধু বাজার-অংশ দিয়ে মাপা যায় না — তার ধারণা কত দূর ছড়াল, সেটাও মাপকাঠি। আর জটিলতা কমিয়ে মূল ধারণা রক্ষা করাই প্রায়ই জয়ী নকশা।

প্র ০২Microsoft কেন দুটি আলাদা Windows (9x আর NT) প্রায় এক দশক চালাল? পুরোনো প্রোগ্রাম চালু রাখার (backward compatibility) দাম কত?

১৯৯০-এর দশকের শুরুতে Microsoft-এর সামনে দুটি পরস্পরবিরোধী চাপ ছিল। একদিকে কোটি কোটি ঘরোয়া ব্যবহারকারী, যাঁদের পুরোনো DOS গেম, প্রিন্টার driver আর অফিস সফটওয়্যার চালু রাখতেই হবে, আর যাঁদের কম্পিউটারে RAM খুব কম (কয়েক মেগাবাইট)। অন্যদিকে ব্যবসা আর সার্ভার, যাদের দরকার স্থিতিশীলতা, নিরাপত্তা আর একাধিক CPU.

NT দ্বিতীয় দলের জন্য শূন্য থেকে নকশা করা: প্রতিটি প্রসেসের আলাদা সুরক্ষিত মেমরি, kernel আর user mode-এর কঠোর বিভাজন, NTFS-এ অনুমতি, preemptive scheduling. কিন্তু এর দাম ছিল — বেশি RAM লাগত, আর হার্ডওয়্যারে সরাসরি হাত দেওয়া পুরোনো DOS প্রোগ্রাম ও গেম সেখানে প্রায়ই চলত না, কারণ NT সেই সরাসরি হাত দেওয়াটাই নিষেধ করে।

9x প্রথম দলের জন্য আপস: আধুনিক চেহারা আর ৩২-বিট প্রোগ্রাম, কিন্তু ভেতরে DOS-এর ভিত্তি রেখে পুরোনো সব কিছু চালু রাখা। ফল — একটি খারাপ driver বা প্রোগ্রাম সহজেই পুরো সিস্টেম ফেলে দিত। সেই যুগের ঘন ঘন “নীল পর্দা” আর রিস্টার্টের অভিজ্ঞতা অনেকেরই মনে আছে।

২০০১ সালে XP দুটি ধারা এক করতে পারল, কারণ ততদিনে (১) সাধারণ কম্পিউটারে যথেষ্ট RAM এসেছে, (২) NT-তে পুরোনো প্রোগ্রাম চালানোর compatibility স্তর অনেক উন্নত হয়েছে। Backward compatibility-র দাম আজও দেখা যায়: Windows এখনো বহু দশক পুরোনো API সমর্থন করে, আর পুরোনো প্রোগ্রাম যাতে না ভাঙে সেজন্য Windows 11-ও ভেতরে নিজেকে “10.0” বলে। Linux kernel-এর নীতিও একই সুরে — “we do not break userspace”: kernel বদলালেও পুরোনো প্রোগ্রাম যেন ভাঙে না।

মূল উপলব্ধি: OS-এর সবচেয়ে বড় সম্পদ তার ওপর চলা প্রোগ্রামগুলো। পুরোনো প্রোগ্রাম ভাঙলে ব্যবহারকারী চলে যান — তাই নতুন নকশা প্রায়ই পাশাপাশি চালিয়ে ধীরে ধীরে আনতে হয়, এক রাতে নয়।

প্র ০৩GNU-র নিজস্ব kernel (Hurd) পিছিয়ে থাকল, অথচ এক ছাত্রের শখের Linux জয়ী হলো — কেন?

এর পেছনে প্রযুক্তি, সময় আর মানুষ — তিনটিই কাজ করেছে।

  • নকশার উচ্চাকাঙ্ক্ষা বনাম বাস্তববাদ: Hurd বানানো হচ্ছিল Mach microkernel-এর ওপর অনেকগুলো আলাদা server হিসেবে — তাত্ত্বিকভাবে মার্জিত, কিন্তু তৈরি ও ডিবাগ করা কঠিন, আর তখনকার microkernel-এ বার্তা-আদানপ্রদানের খরচ বেশি ছিল। Linux ছিল প্রচলিত monolithic kernel — “কাজ চলে” এমন সরল পথ। পর্ব ০৬-এ এই দুই নকশার তুলনা দেখবেন।
  • সময়: ১৯৯১ সালে সস্তা 386 PC সবার হাতে, ইন্টারনেট বিশ্ববিদ্যালয়গুলোতে ছড়াচ্ছে, আর GNU-র বাকি সব টুল তৈরি — শুধু একটি kernel-এর অপেক্ষা। BSD তখন AT&T-র সাথে আইনি বিবাদে জড়িয়ে ছিল (১৯৯০-এর দশকের শুরুতে), যা অনেককে অনিশ্চয়তায় রেখেছিল।
  • উন্নয়নের পদ্ধতি: Torvalds প্রথম থেকেই ইন্টারনেটে কোড খুলে দেন, ঘন ঘন নতুন version ছাড়েন আর অন্যদের প্যাচ গ্রহণ করেন। GPL লাইসেন্স নিশ্চিত করল যে কেউ উন্নতি নিলে সেটি আবার সবার জন্য খুলে দিতে হবে।

একটি বিখ্যাত বিতর্কও আছে। ১৯৯২ সালে MINIX-এর স্রষ্টা অধ্যাপক Andrew Tanenbaum একটি আলোচনা-গোষ্ঠীতে লেখেন, “Linux is obsolete” — তাঁর যুক্তি, monolithic নকশা পুরোনো আর microkernel-ই ভবিষ্যৎ। Torvalds জোরালো উত্তর দেন। তাত্ত্বিক যুক্তিতে Tanenbaum-এর কথার যথেষ্ট ওজন ছিল (আজ নিরাপত্তা-সংবেদনশীল জায়গায় seL4-এর মতো microkernel ব্যবহৃত হয়), কিন্তু বাজারে জিতল Linux — loadable module যোগ করে সে monolithic নকশাকেও নমনীয় করে তোলে।

মূল উপলব্ধি: সেরা নকশা নয়, “যথেষ্ট ভালো এবং এখনই পাওয়া যায়” এমন নকশা প্রায়ই জেতে — বিশেষত যখন তার পেছনে একটি খোলা, সক্রিয় সম্প্রদায় থাকে। তবে হেরে যাওয়া ধারণাগুলোও পরে অন্য রূপে ফিরে আসে।

প্র ০৪আপনার স্মার্টফোন কি একটি real-time সিস্টেম? Android-এর Linux kernel কি airbag চালানোর মতো নির্ভরযোগ্য?

উত্তরটি দুই স্তরের, আর এখানেই hard ও soft real-time-এর পার্থক্য সবচেয়ে পরিষ্কার বোঝা যায়।

অ্যাপের স্তরে — soft real-time: ভিডিও কল, গান বাজানো, স্ক্রল করার সময় পর্দা ঝরঝরে রাখা — এসবের সময়সীমা আছে (৬০ Hz পর্দায় প্রতিটি ফ্রেম মোটামুটি ১৬.৭ ms-এর মধ্যে আঁকতে হয়)। কিন্তু একটি ফ্রেম মিস হলে শুধু একটু “ঝাঁকুনি” লাগে, কেউ আহত হন না। Android-এর kernel আর framework এই ধরনের কাজকে বাড়তি অগ্রাধিকার দেয়, কিন্তু কোনো কঠোর গাণিতিক নিশ্চয়তা দেয় না।

হার্ডওয়্যারের গভীরে — প্রায়ই আলাদা RTOS: ফোনের মোবাইল-নেটওয়ার্ক রেডিও (baseband) চালাতে সাধারণত একটি আলাদা প্রসেসর থাকে, যেখানে আলাদা একটি real-time OS বা firmware চলে — কারণ রেডিও-প্রোটোকলের সময়সীমা অত্যন্ত কঠোর। অর্থাৎ আপনার এক ফোনেই অন্তত দুটি OS: Android আর একটি RTOS-ধাঁচের firmware (নির্মাতাভেদে বিস্তারিত আলাদা)।

Airbag কেন Linux-এ নয়? সাধারণ Linux লাখ লাখ লাইনের, page fault আর জটিল driver-সহ — তার worst-case দেরি প্রমাণ করা প্রায় অসম্ভব। Airbag বা ABS-এর মতো নিরাপত্তা-সংকটপূর্ণ কাজ চলে ছোট microcontroller-এ, বিশেষ RTOS বা bare-metal কোডে, যা কঠোর মানদণ্ড (যেমন গাড়ির জন্য ISO 26262) মেনে যাচাই করা হয়। PREEMPT_RT মূল kernel-এ আসার পর Linux-এর latency অনেক কমেছে, তবু “কম গড় দেরি” আর “প্রমাণিত সর্বোচ্চ দেরি” এক জিনিস নয়।

আধুনিক গাড়িতেও এই বিভাজন: ইনফোটেইনমেন্ট-পর্দা হয়তো Linux বা Android-এ, কিন্তু ব্রেক আর airbag আলাদা চিপে আলাদা RTOS-এ।

মূল উপলব্ধি: “Real-time” মানে দ্রুত নয় — মানে পূর্বানুমানযোগ্য। বাস্তব সিস্টেম প্রায়ই কাজ ভাগ করে: সুবিধার কাজ সাধারণ OS-এ, জীবন-মরণের কাজ ছোট, প্রমাণযোগ্য RTOS-এ।

প্র ০৫ক্লাউড আর serverless-এর যুগে কি “অপারেটিং সিস্টেম” ধারণাটিই অপ্রয়োজনীয় হয়ে যাচ্ছে?

উল্টোটাই সত্যি — OS অদৃশ্য হচ্ছে না, বরং কয়েক স্তরে ভাগ হয়ে আরও গুরুত্বপূর্ণ হচ্ছে। একটি serverless ফাংশন (যেমন AWS Lambda) লিখলে আপনি কোনো সার্ভার দেখেন না, কিন্তু ভেতরে:

  • ভৌত সার্ভারে একটি hypervisor — Amazon-এর ক্ষেত্রে KVM-ভিত্তিক — যা নিজেই এক ধরনের OS: CPU, মেমরি আর I/O ভাগ করে।
  • তার ওপর অত্যন্ত হালকা microVM (Amazon ২০১৮ সালে Firecracker নামে এমন একটি প্রকল্প open source করে), যার ভেতরে একটি পূর্ণ Linux kernel.
  • তার ভেতরে আপনার কোড — একটি সাধারণ Linux প্রসেস, যার জন্য fork, ফাইল, মেমরি, scheduling — এই কোর্সের সব কিছু কাজ করছে।

অর্থাৎ আপনাকে OS পরিচালনা করতে হচ্ছে না, কিন্তু OS-এর আচরণ এখনো আপনার খরচ আর গতি ঠিক করে। “Cold start” — প্রথম অনুরোধে কয়েকশো মিলিসেকেন্ড দেরি — এর বড় অংশ একটি microVM আর তার kernel বুট করা (পর্ব ০৭), তারপর runtime আর আপনার কোড চালু করার সময়। Container-এ মেমরির সীমা পেরোলে প্রসেস হঠাৎ মারা যায় — সেটি Linux-এর OOM killer আর cgroup (পর্ব ৩৮ আর ৫১)।

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

ইতিহাসের ধারা এখানে পরিষ্কার: batch থেকে time-sharing, time-sharing থেকে VM — প্রতিবার OS-এর একটি অংশ নিচে নেমে অদৃশ্য পরিকাঠামো হয়েছে, আর তার ওপরে নতুন সুবিধা এসেছে। কিন্তু নিচের স্তর যে বোঝে, সমস্যা হলে সে-ই সমাধান করতে পারে।

মূল উপলব্ধি: বিমূর্ততা (abstraction) যত উঁচুতে ওঠে, নিচের OS তত অদৃশ্য হয় — কিন্তু অপ্রয়োজনীয় হয় না। ক্লাউডের বিল, latency আর হঠাৎ crash — সবকিছুর মূলে এখনো সেই process, memory আর scheduling.

অনুশীলন

কাগজ-কলম নিন — প্রথম দুটি হাতে হিসাবের, তৃতীয়টি কমান্ডের, চতুর্থটি শ্রেণিবিন্যাসের।

  1. Utilisation হিসাব: প্রতিটি কাজ ৭০% সময় I/O-র অপেক্ষায় থাকে (p = 0.7). (ক) n = 1, 2, 3, 4 হলে CPU utilisation কত? (খ) RAM 16 GB, OS নেয় 4 GB, প্রতিটি কাজ 2 GB — কয়টি কাজ ধরবে, utilisation কত? (গ) utilisation অন্তত ৯৫% করতে ন্যূনতম কয়টি কাজ লাগবে?

    (ক) 1 − 0.7 = ৩০%; 1 − 0.49 = ৫১%; 1 − 0.343 = ৬৫.৭%; 1 − 0.2401 ≈ ৭৬.০%.

    (খ) (16 − 4) ÷ 2 = 6টি কাজ। 0.76 = 0.117649, তাই utilisation ≈ ৮৮.২%.

    (গ) দরকার 0.7n ≤ 0.05. দুই পাশে log নিলে n ≥ ln 0.05 ÷ ln 0.7 ≈ (−2.996) ÷ (−0.357) ≈ ৮.৪, তাই n = ৯ (কাজ ভগ্নাংশে হয় না, তাই ওপরের পূর্ণসংখ্যা)। যাচাই: 0.78 ≈ 0.0576 → ৯৪.২% (যথেষ্ট নয়), 0.79 ≈ 0.0404 → ৯৬.০%. মনে রাখুন, এটি স্বাধীনতার অনুমানের ওপর দাঁড়ানো হিসাব।

  2. হাতে trace: দুটি কাজ — P: CPU 3 → I/O 2 → CPU 1; Q: CPU 1 → I/O 3 → CPU 2. (ক) uniprogramming-এ (আগে P, পরে Q) মোট সময় আর CPU utilisation কত? (খ) multiprogramming-এ (দুটিই শুরু থেকে মেমরিতে, আগে-আসা-আগে-পাবে, I/O আলাদা যন্ত্রে)? প্রতিটি একক সময়ে CPU-তে কে, লিখে দেখান।

    (ক) P: 0–3 CPU, 3–5 I/O (CPU অলস), 5–6 CPU; Q: 6–7 CPU, 7–10 I/O (অলস), 10–12 CPU. মোট 12, CPU ব্যস্ত 3 + 1 + 1 + 2 = 7, utilisation 7 ÷ 12 ≈ ৫৮.৩%. CPU সারি: 111..12...22.

    (খ) P 0–3 (Q অপেক্ষায়); 3-এ P I/O-তে (3–5), Q চলে 3–4, তারপর Q-এর I/O 4–7; 4–5 CPU অলস (P আর Q দুটোই I/O-তে); 5-এ P ফিরে 5–6 চলে শেষ; 6–7 আবার অলস; 7-এ Q ফিরে 7–9 চলে শেষ। মোট 9, ব্যস্ত 7, utilisation 7 ÷ 9 ≈ ৭৭.৮%. CPU সারি: 1112.1.22. ওপরের simulator-এ jobs বদলে ([3, 2, 1] আর [1, 3, 2]) চালালে ঠিক এই দুটি সারি আর 58.3% ও 77.8% আসে।

  3. কমান্ড লিখুন ও ফল অনুমান করুন: (ক) Linux, macOS আর Windows (PowerShell)-এ kernel/OS version আর logical CPU সংখ্যা দেখার একটি করে কমান্ড লিখুন। (খ) যে Linux যন্ত্রে nproc 2 দেখায়, সেখানে taskset -c 0 nproc কী দেখাবে? grep -c ^processor /proc/cpuinfo কি বদলাবে?

    (ক) Linux: uname -r আর nproc (বা grep -c ^processor /proc/cpuinfo). macOS: uname -r (Darwin-এর version) আর sysctl -n hw.ncpu. Windows PowerShell: [System.Environment]::OSVersion.Version আর $env:NUMBER_OF_PROCESSORS.

    (খ) 1 — taskset -c 0 প্রসেসটিকে শুধু CPU 0-তে বাঁধে, আর nproc দেখায় প্রসেসটি কয়টি CPU ব্যবহার করতে পারে (CPU affinity). /proc/cpuinfo বদলাবে না — এখনো 2, কারণ সেটি kernel-এর দেখা সব logical CPU-র তালিকা, কোনো একটি প্রসেসের অনুমতি নয়।

  4. কোন ধরনের OS? প্রতিটির জন্য সবচেয়ে উপযুক্ত OS-ধরন বলুন, এক লাইনে কারণসহ: (ক) গাড়ির airbag controller (খ) মোবাইলে YouTube ভিডিও চালানো (গ) ব্যাংকের রাতের সুদ-হিসাব (ঘ) বাসার Wi-Fi রাউটার (ঙ) ভাড়া নেওয়া একটি ক্লাউড সার্ভার।

    (ক) Hard real-time RTOS — deadline মিস মানে প্রাণের ঝুঁকি। (খ) মোবাইল OS-এ soft real-time কাজ — ফ্রেম মিস হলে শুধু মান কমে। (গ) Batch — মানুষের সাথে কথোপকথন লাগে না, রাতে সারিবদ্ধভাবে চলে। (ঘ) Embedded OS (প্রায়ই embedded Linux, যেমন OpenWrt) — নির্দিষ্ট কাজ, কম মেমরি, বছরের পর বছর একটানা চলা। (ঙ) Hypervisor-এর ওপর চলা একটি VM (ক্লাউড/virtualized) — সাধারণত ভেতরে Linux বা Windows Server; একটি ভৌত যন্ত্র অনেক গ্রাহকে ভাগ হয়।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমOS-এর যুগগুলো সময়ের ক্রমে সাজান (▲▼ চেপে সরান)

  1. Serial processing — প্রোগ্রামার নিজেই অপারেটর, OS নেই
  2. Batch system আর resident monitor
  3. Multiprogramming — মেমরিতে একাধিক কাজ
  4. Time-sharing — CTSS, Multics
  5. ব্যক্তিগত কম্পিউটার — MS-DOS, Macintosh
  6. স্মার্টফোন — iOS, Android

প্রতিটি কাজ ৬০% সময় I/O-র অপেক্ষায় থাকে। স্বাধীনতার অনুমানে মেমরিতে ৩টি কাজ থাকলে CPU utilisation কত?

  • ২১.৬%
  • ৭৮.৪%
  • ৬০%
  • ৯৩.৬%

Multiprogramming থেকে time-sharing (multitasking)-কে মূলত কোনটি আলাদা করে?

  • মেমরিতে একাধিক কাজ রাখা
  • একাধিক CPU থাকা
  • Timer interrupt দিয়ে নিয়মিত পালা বদল, যাতে প্রত্যেকে দ্রুত সাড়া পায়
  • Punch card দিয়ে কাজ জমা দেওয়া

নিচের কোনটি hard real-time সিস্টেমের সবচেয়ে ভালো উদাহরণ?

  • গাড়ির airbag controller
  • মোবাইলে ভিডিও কল
  • মাসশেষের বেতন-হিসাব
  • ল্যাপটপে ওয়েব ব্রাউজার

“একটি কম্পিউটারে একাধিক CPU বা core থাকায় একই মুহূর্তে একাধিক নির্দেশ চলে” — এই সংজ্ঞাটি কোন শব্দের?

  • Multiprogramming
  • Multithreading
  • Multitasking
  • Multiprocessing

Windows-এর ঘরোয়া (home) সংস্করণ প্রথম কোনটিতে Windows NT kernel-এ চলে আসে?

  • Windows 95
  • Windows ME
  • Windows XP
  • Windows 3.1

Android স্মার্টফোনের OS কোন kernel-এর ওপর তৈরি?

  • XNU
  • Linux
  • Windows NT
  • MINIX

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. OS-এর প্রতিটি প্রজন্ম একটি অপচয়ের জবাব: serial → batch → multiprogramming → time-sharing → PC → network → মোবাইল → ক্লাউড.
  2. Multiprogramming I/O-র অপেক্ষার ফাঁক ভরায়; মোটা দাগের হিসাব CPU utilisation ≈ 1 − pn — অনুমান: স্বাধীন অপেক্ষা, একক CPU, switch-খরচ শূন্য।
  3. Multiprogramming (মেমরিতে অনেক কাজ), multitasking (timer দিয়ে পালা), multiprocessing (একাধিক CPU), multithreading (এক প্রসেসে অনেক thread) — চারটি আলাদা অক্ষ।
  4. Real-time মানে পূর্বানুমানযোগ্য: hard-এ deadline মিস = ব্যর্থতা, soft-এ = মান কমা। Embedded, মোবাইল আর ক্লাউড OS-এর অগ্রাধিকারও আলাদা।
  5. Unix (১৯৬৯) থেকে BSD, macOS; Unix-সদৃশ Linux (১৯৯১) থেকে Android; আর Windows NT (১৯৯৩) থেকে XP, 10, 11.

পরের পর্বে: ইতিহাসের Unix-দর্শন — “ছোট টুল, pipe দিয়ে জোড়া” — এবার হাতে-কলমে। Linux টার্মিনালে shell, কমান্ড আর ফাইল নিয়ে কাজ শুরু করবেন, যা এই কোর্সের বাকি সব পরীক্ষার হাতিয়ার।

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

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান