পাঠ ৩০ · ৫৬-এর মধ্যে · মডিউল ৭
Home / Courses / Operating Systems (OS) / মেমরি ম্যানেজমেন্ট

সেগমেন্টেশন

Segmentation
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

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

  • সেগমেন্টেশন কীভাবে প্রোগ্রামের স্বাভাবিক লজিক্যাল গঠনের (কোড/ডেটা/স্ট্যাক) সাথে মিলিয়ে মেমরি ভাগ করে
  • সেগমেন্ট টেবিলের গঠন — base ও limit — এবং এর মাধ্যমে অ্যাড্রেস ট্রান্সলেশন
  • বাউন্ডস-চেকিং কীভাবে একটি প্রোটেকশন মেকানিজম হিসেবে কাজ করে
  • Python দিয়ে বাস্তব সেগমেন্টেশন ট্রান্সলেশন — বৈধ ও অবৈধ (আউট-অফ-বাউন্ডস) উভয় অ্যাক্সেসসহ

১ · সেগমেন্টেশন — লজিক্যাল গঠন অনুযায়ী ভাগ

L29-এর পেজিং মেমরিকে ফিক্সড-সাইজ, লজিক্যালি-অর্থহীন টুকরোয় ভাগ করে — পেজ ২ আসলে প্রোগ্রামের কোন অংশ, তা নির্দিষ্ট কিছু বোঝায় না। সেগমেন্টেশনSegmentationপ্রসেসের অ্যাড্রেস স্পেসকে ভ্যারিয়েবল-সাইজ, লজিক্যালি-অর্থবহ সেগমেন্টে (যেমন কোড, ডেটা, স্ট্যাক) ভাগ করার মেমরি-ম্যানেজমেন্ট কৌশল। এর বিপরীতে, প্রোগ্রামের স্বাভাবিক গঠনকেই ভিত্তি ধরে — একটি কোড সেগমেন্ট, একটি ডেটা সেগমেন্ট, একটি স্ট্যাক সেগমেন্ট — প্রতিটি সেগমেন্ট একটি প্রাকৃতিক প্রোগ্রাম-উপাদানের সাথে মিলে যায়, এবং প্রতিটির আকার ভিন্ন ভিন্ন হতে পারে (কোড সেগমেন্ট বড়, স্ট্যাক ছোট হতে পারে)।

কোড সেগমেন্ট
প্রোগ্রামের ইনস্ট্রাকশন — সাধারণত read-only হিসেবে মার্ক করা যায়, একটি স্বাভাবিক প্রোটেকশন সুবিধা।
ডেটা সেগমেন্ট
গ্লোবাল ভ্যারিয়েবল ও হিপ — read-write, প্রোগ্রাম চলাকালীন আকারে বাড়তে পারে।
স্ট্যাক সেগমেন্ট
ফাংশন কল, লোকাল ভ্যারিয়েবল — সাধারণত বিপরীত দিকে বাড়ে, প্রতিটি নতুন ফাংশন কলের সাথে।

২ · সেগমেন্ট টেবিল ও বাউন্ডস-চেকিং

একটি লজিক্যাল অ্যাড্রেস এখানে একটি জোড়া — (segment_number, offset)। একটি সেগমেন্ট টেবিল প্রতিটি segment_number-কে দুটি মান দেয় — base (সেগমেন্টটি ফিজিক্যাল মেমরিতে কোথায় শুরু হয়) এবং limit (সেগমেন্টের প্রকৃত দৈর্ঘ্য)। ট্রান্সলেশনের আগে একটি গুরুত্বপূর্ণ চেক হয় —

$$\text{if } \text{offset} \geq \text{limit} \Rightarrow \text{সেগমেন্টেশন ফল্ট (প্রত্যাখ্যাত)}$$

চেক পাস হলে তবেই —

$$\text{physical\_address} = \text{base} + \text{offset}$$

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

(segment, offset) লজিক্যাল অ্যাড্রেস সেগমেন্ট টেবিল base, limit লুকআপ offset < limit? না হলে ফল্ট, হলে base+offset
বাউন্ডস-চেক ব্যর্থ হলে ট্রান্সলেশনই সম্পন্ন হয় না — এটি প্রোটেকশনের একটি হার্ডওয়্যার-স্তরের গ্যারান্টি।

৩ · বাস্তব বাস্তবায়ন — বাউন্ডস-চেকিংসহ

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

Python
# সেগমেন্টেশন অ্যাড্রেস ট্রান্সলেশন -- বাউন্ডস-চেকিংসহ
def translate(segment_number, offset, segment_table):
    if segment_number not in segment_table:
        raise ValueError(f"অজানা সেগমেন্ট নাম্বার: {segment_number}")
    base, limit = segment_table[segment_number]
    if offset >= limit:
        raise ValueError(
            f"সেগমেন্টেশন ফল্ট: সেগমেন্ট {segment_number}-এ offset {offset} "
            f">= limit {limit} -- আউট-অফ-বাউন্ডস অ্যাক্সেস প্রত্যাখ্যাত"
        )
    return base + offset

# segment_number -> (base, limit)
segment_table = {
    0: (14000, 2000),  # কোড সেগমেন্ট
    1: (18000, 1500),  # ডেটা সেগমেন্ট
    2: (22000, 3000),  # স্ট্যাক সেগমেন্ট
}

test_accesses = [
    (0, 500),    # ইন-বাউন্ডস: কোড সেগমেন্টের মাঝামাঝি
    (1, 1499),   # ইন-বাউন্ডস: ডেটা সেগমেন্টের একদম শেষ বৈধ বাইট
    (2, 2999),   # ইন-বাউন্ডস: স্ট্যাক সেগমেন্টের শেষ বৈধ বাইট
    (1, 1500),   # আউট-অফ-বাউন্ডস: ডেটা সেগমেন্টের limit-এর ঠিক বাইরে
    (2, 3200),   # আউট-অফ-বাউন্ডস: স্ট্যাক সেগমেন্টের সীমা ছাড়িয়ে
]

for segment_number, offset in test_accesses:
    try:
        physical = translate(segment_number, offset, segment_table)
        print(f"সেগমেন্ট {segment_number}, offset {offset} -> ফিজিক্যাল {physical} (গৃহীত)")
    except ValueError as e:
        print(f"সেগমেন্ট {segment_number}, offset {offset} -> প্রত্যাখ্যাত: {e}")

    
হাতে যাচাই: সেগমেন্ট ১-এর limit 1500, তাই বৈধ offset-এর রেঞ্জ 0 থেকে 1499 পর্যন্ত (1500 নিজেই অবৈধ, যেহেতু চেক হলো offset >= limit)। তাই (1, 1499) গৃহীত হবে (physical = 18000+1499 = 19499), কিন্তু (1, 1500) প্রত্যাখ্যাত হবে — ঠিক এভাবেই কোড সেলের আউটপুট মিলবে।
মূল কথা · Key takeaway

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

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

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

প্র ০১ সেগমেন্টেশন কীভাবে পেজিং-এর তুলনায় "প্রাকৃতিক" প্রোটেকশন দেয়, যা পেজিং সহজে দিতে পারে না?

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

প্র ০২ উপরের কোড সেলে (2, 3200) অ্যাক্সেসটি কেন প্রত্যাখ্যাত হলো, যদিও ফিজিক্যাল মেমরিতে হয়তো সেই অ্যাড্রেসে (22000+3200=25200) আসলে কোনো ডেটা থাকতেও পারে?

বাউন্ডস-চেকিং শুধু জিজ্ঞেস করে না "ফিজিক্যাল মেমরিতে সেই ঠিকানায় কিছু আছে কি না" — বরং জিজ্ঞেস করে "এই নির্দিষ্ট সেগমেন্টের জন্য এই offset বৈধ কি না।" সেগমেন্ট ২-এর limit মাত্র 3000, তাই offset 3200 এই সেগমেন্টের নিজস্ব সীমার বাইরে — এমনকি সেই ফিজিক্যাল ঠিকানায় অন্য কোনো সেগমেন্ট বা প্রসেসের বৈধ ডেটা থাকলেও, এই প্রসেসকে সেখানে অ্যাক্সেস করতে দেওয়া একটি সুরক্ষা লঙ্ঘন হবে — তাই হার্ডওয়্যার সীমা অনুযায়ীই প্রত্যাখ্যান করে, প্রকৃত মেমরি কন্টেন্ট বিবেচনা না করেই।

প্র ০৩ সেগমেন্টেশন কীভাবে L28-এর এক্সটার্নাল ফ্র্যাগমেন্টেশন সমস্যা ফিরিয়ে আনে, যেখানে পেজিং তা এড়িয়ে গিয়েছিল?

পেজিং-এ সব পেজ ঠিক একই আকারের বলে যেকোনো ফাঁকা ফ্রেম যেকোনো পেজের জন্য কাজে লাগে। কিন্তু সেগমেন্ট ভ্যারিয়েবল-সাইজ — একটি ৫০০০ বাইটের সেগমেন্টের জন্য ফিজিক্যাল মেমরিতে একটানা ৫০০০ বাইটের একটি ফাঁকা জায়গাই লাগবে। সময়ের সাথে সাথে সেগমেন্ট আসা-যাওয়ার ফলে ঠিক L28-এর ভ্যারিয়েবল পার্টিশনিং-এর মতোই বিক্ষিপ্ত, ভিন্ন-আকারের ফাঁকা হোল তৈরি হয় — একই মৌলিক সমস্যা, ভিন্ন প্রেক্ষাপটে ফিরে আসে।

অনুশীলন

  1. চিন্তা করুন: একটি প্রোগ্রামের স্ট্যাক চলাকালীন বাড়তে থাকে (আরও ফাংশন কল হলে)। সেগমেন্ট টেবিলে সেই সেগমেন্টের limit যদি স্থির থাকে, তাহলে কী সমস্যা হতে পারে?

    স্ট্যাক তার বরাদ্দকৃত limit ছাড়িয়ে গেলে ("স্ট্যাক ওভারফ্লো") প্রতিটি নতুন অ্যাক্সেস বাউন্ডস-চেকে প্রত্যাখ্যাত হবে — এটি বাস্তবে ঠিক তাই ঘটে যখন একটি প্রোগ্রামে অসীম বা অতিরিক্ত গভীর রিকার্শন হয়। কিছু বাস্তব সিস্টেম প্রয়োজনে স্ট্যাক সেগমেন্টের limit ডাইনামিকভাবে বাড়ানোর ব্যবস্থা রাখে (যদি পাশের মেমরি ফাঁকা থাকে), কিন্তু এটি একটি সীমিত, নিয়ন্ত্রিত সুবিধা — অসীম বাড়ানো যায় না।

  2. পরীক্ষা করুন: উপরের কোড সেলে segment_table-এ সেগমেন্ট ০-এর limit 2000 থেকে 400 করে Run চাপুন — (0, 500) অ্যাক্সেসটি এখন কী ফলাফল দেয়?

    limit 400 হলে offset 500 এখন limit-এর বাইরে (500 >= 400), তাই এই অ্যাক্সেসটি এখন প্রত্যাখ্যাত হবে — আগের রানে যা গৃহীত হয়েছিল। এটি দেখায় সেগমেন্ট টেবিলের limit-এর মান পরিবর্তনই সরাসরি নির্ধারণ করে কোন অ্যাক্সেসগুলো বৈধ — বাউন্ডস-চেকিং সম্পূর্ণভাবে এই টেবিলের ওপর নির্ভরশীল, হার্ডকোড করা কোনো নিয়মের ওপর নয়।

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

আগের পাঠ
পাঠ ২৯ · পেজিং