পাঠ ৪০ · ৫৬-এর মধ্যে · মডিউল ৯
Home / Courses / Operating Systems (OS) / ফ্রি স্পেস

ফ্রি স্পেস ম্যানেজমেন্ট

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

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

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

১ · সমস্যা — কোন ব্লক ফ্রি?

L39-এ যখন একটি নতুন ফাইলের জন্য ব্লক বরাদ্দ করতে হয় (কন্টিগুয়াস, লিংকড বা ইনডেক্সড — যেকোনো পদ্ধতিতেই), ফাইল সিস্টেমকে প্রথমে জানতে হয় ডিস্কের কোন ব্লকগুলো ইতিমধ্যে ব্যবহৃত এবং কোনগুলো ফ্রিFree Space Managementফাইল সিস্টেম কীভাবে ট্র্যাক রাখে কোন ডিস্ক ব্লক বরাদ্দযোগ্য (ফ্রি) এবং কোনগুলো ইতিমধ্যে ব্যবহৃত। (বরাদ্দযোগ্য)। এই ট্র্যাকিং ব্যবস্থাই ফ্রি স্পেস ম্যানেজমেন্ট।

২ · চারটি কৌশল

বিট ভেক্টর (বিটম্যাপ)
প্রতিটি ব্লকের জন্য ১টি বিট (0=ফ্রি, 1=বরাদ্দকৃত) — কমপ্যাক্ট এবং বিটওয়াইজ অপারেশনের মাধ্যমে দ্রুত বাল্ক স্ক্যান সম্ভব, কিন্তু বিটম্যাপ নিজেই মেমরিতে রাখতে/স্ক্যান করতে হয়, যার খরচ মোট ডিস্ক সাইজের সমানুপাতিক।
ফ্রি ব্লকের লিংকড লিস্ট
সব ফ্রি ব্লক একে অপরের সাথে পয়েন্টারে চেইন করা (L39-এর লিংকড অ্যালোকেশনের মতোই কাঠামো, কিন্তু ফ্রি-ডম ট্র্যাক করার জন্য) — বাড়তি স্পেস লাগে না, কিন্তু টানা ফ্রি রান খুঁজতে ট্রাভার্সাল লাগে (ধীর), আর লিস্টটি নিজেই কমপ্যাক্ট নয়।
গ্রুপিং
লিংকড লিস্ট আইডিয়ার অপ্টিমাইজেশন — প্রথম ফ্রি ব্লকে পরের N-টি ফ্রি ব্লকের ঠিকানা একসাথে রাখা হয়, ফলে অনেকগুলো ফ্রি ব্লক একসাথে খুঁজতে ভিজিট করতে হওয়া ব্লকের সংখ্যা নাটকীয়ভাবে কমে যায়।
কাউন্টিং
যেহেতু বাস্তবে ফ্রি ব্লক প্রায়ই টানা (contiguous) চাংক আকারে বরাদ্দ/মুক্ত হয়, প্রতিটি একক ব্লকের বদলে (starting_address, count) জোড়া রাখা হয় — ফ্রি স্পেস সত্যিই টানা হলে অনেক বেশি কমপ্যাক্ট।

৩ · বিটম্যাপ-ভিত্তিক ফ্রি স্পেস ম্যানেজার

নিচের কোড সেলে একটি সহজ বিটম্যাপ বাস্তবায়ন করা হয়েছে — L28-এর first-fit স্ক্যানের মতোই একটি স্ক্যান-ভিত্তিক পদ্ধতিতে টানা ফ্রি ব্লকের প্রথম যথেষ্ট বড় রান খুঁজে বের করা হয়, তারপর বরাদ্দ (allocate) ও মুক্ত (free) করার ফাংশন দিয়ে বিটম্যাপের সংশ্লিষ্ট বিট ফ্লিপ করা হয়।

Python
# L40 -- বিটম্যাপ-ভিত্তিক ফ্রি স্পেস ম্যানেজমেন্ট (toy in-memory, বাস্তব ডিস্ক নয়)
# 0 = ফ্রি ব্লক, 1 = বরাদ্দকৃত ব্লক
TOTAL_BLOCKS = 16
bitmap = [0] * TOTAL_BLOCKS

def find_free_blocks(bmp, count_needed):
    """count_needed সংখ্যক টানা ফ্রি ব্লকের প্রথম রান খুঁজে বের করে (first-fit স্টাইল স্ক্যান)।"""
    run_start = None
    run_len = 0
    for i, bit in enumerate(bmp):
        if bit == 0:
            if run_start is None:
                run_start = i
            run_len += 1
            if run_len == count_needed:
                return run_start
        else:
            run_start = None
            run_len = 0
    return None  # যথেষ্ট বড় টানা ফ্রি রান নেই

def allocate(bmp, count_needed):
    start = find_free_blocks(bmp, count_needed)
    if start is None:
        print(f"বরাদ্দ ব্যর্থ -> {count_needed}টি টানা ফ্রি ব্লক পাওয়া যায়নি")
        return None
    for i in range(start, start + count_needed):
        bmp[i] = 1
    print(f"বরাদ্দ সফল -> ব্লক {start}-{start + count_needed - 1}")
    return start

def free(bmp, start, count):
    for i in range(start, start + count):
        bmp[i] = 0
    print(f"মুক্ত করা হলো -> ব্লক {start}-{start + count - 1}")


def show(bmp):
    print("বিটম্যাপ:", "".join(str(b) for b in bmp))


print("প্রাথমিক অবস্থা:")
show(bitmap)

a1 = allocate(bitmap, 4)   # প্রত্যাশা: ব্লক 0-3
show(bitmap)

a2 = allocate(bitmap, 3)   # প্রত্যাশা: ব্লক 4-6
show(bitmap)

free(bitmap, a1, 4)        # ব্লক 0-3 মুক্ত করা হলো
show(bitmap)

a3 = allocate(bitmap, 5)   # এখন 0-3 আবার ফ্রি -> কিন্তু 5 লাগবে, 0-3 (4টি) যথেষ্ট নয়
                            # তাই স্ক্যান পরের রান খুঁজবে: 7-15 (9টি ফ্রি) থেকে 5টি নেবে -> 7-11
show(bitmap)

# পুরো ডিস্ক ভরাট করার চেষ্টা -- ব্যর্থ হওয়া উচিত
a4 = allocate(bitmap, 20)
show(bitmap)

    
লক্ষ্য করুন a3 = allocate(bitmap, 5)-এর ধাপটি — ব্লক 0-3 তখন আবার ফ্রি (মোট ৪টি), কিন্তু আমাদের ৫টি টানা ব্লক দরকার, তাই find_free_blocks সঠিকভাবে সেই রানটি বাদ দিয়ে পরের যথেষ্ট বড় রান (ব্লক 7-15) পর্যন্ত স্ক্যান চালিয়ে যায় এবং সেখান থেকে 7-11 বরাদ্দ করে।
মূল কথা · Key takeaway

ফ্রি স্পেস ম্যানেজমেন্ট হলো L39-এর অ্যালোকেশন সিদ্ধান্তের ভিত্তি — একটি অ্যালোকেশন মেথড যতই ভালো হোক না কেন, সেটি কার্যকর হয় তখনই যখন কোন ব্লক ফ্রি তা দ্রুত ও নির্ভুলভাবে জানা যায়। বিটম্যাপ তার সরলতা ও দ্রুত বাল্ক স্ক্যানের জন্য বাস্তব ফাইল সিস্টেমে (যেমন ext-পরিবারের ফাইল সিস্টেমে) ব্যাপকভাবে ব্যবহৃত হয়।

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

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

প্র ০১ বিটম্যাপ "কমপ্যাক্ট" বলা হলো, কিন্তু একটি বিশাল ডিস্কের জন্য এটি কি সত্যিই ছোট থাকে?

তুলনামূলকভাবে ছোট, কিন্তু শূন্য নয় — বিটম্যাপের আকার মোট ব্লক সংখ্যার সমানুপাতিক, ব্লকের সাইজ নির্বিশেষে। যেমন ১ টেরাবাইট ডিস্ক ৪KB ব্লকে ভাগ করলে প্রায় ২৬ কোটি ব্লক হয় — অর্থাৎ প্রায় ৩২ মেগাবাইটের একটি বিটম্যাপ। এটি পুরো ডিস্কের তুলনায় নগণ্য (০.০০৩% এর কম), কিন্তু এটিকে "ফ্রি" বলা যায় না — এই বিটম্যাপ মেমরিতে লোড ও দ্রুত স্ক্যান করা যায় বলেই এটি ব্যবহারিকভাবে কার্যকর, সম্পূর্ণ ব্যয়হীন নয়।

প্র ০২ "কাউন্টিং" পদ্ধতি ঠিক কোন পরিস্থিতিতে "গ্রুপিং"-এর চেয়ে বেশি কমপ্যাক্ট হবে?

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

প্র ০৩ কোড সেলে a4 = allocate(bitmap, 20) কেন ব্যর্থ হলো, যদিও বিটম্যাপে মোট ফ্রি ব্লকের সংখ্যা গুনলে হয়তো ২০-এর কাছাকাছি বা বেশি হতে পারত?

কারণ find_free_blocks মোট ফ্রি ব্লকের সংখ্যা গোনে না — এটি খোঁজে একটি টানা (contiguous) রান যার দৈর্ঘ্য অন্তত count_needed। এই মুহূর্তে বিটম্যাপে সর্বোচ্চ টানা ফ্রি রানের দৈর্ঘ্য ১৬-এর কম (আগের বরাদ্দগুলো বিটম্যাপকে খণ্ডিত করে ফেলেছে), তাই ২০টি ব্লকের জন্য কোনো একক রানই যথেষ্ট নয় — এমনকি মোট ফ্রি ব্লক ২০ বা তার বেশি থাকলেও। এটিই টানা-অ্যালোকেশনের ফ্র্যাগমেন্টেশন সমস্যা, যা L39-এর কন্টিগুয়াস অ্যালোকেশনেও একইভাবে দেখা দেয়।

অনুশীলন

  1. চিন্তা করুন: একটি ফাইল সিস্টেমে ব্লক সাইজ ৪KB আর মোট ডিস্ক ১ গিগাবাইট হলে বিটম্যাপে কতগুলো বিট লাগবে, এবং সেটি কত বাইটের সমান?

    ১ গিগাবাইট = ১,০৭৩,৭৪১,৮২৪ বাইট, ব্লক সাইজ ৪০৯৬ বাইট হলে মোট ব্লক সংখ্যা = ১,০৭৩,৭৪১,৮২৪ / ৪০৯৬ = ২৬২,১৪৪টি ব্লক — তাই বিটম্যাপে ২৬২,১৪৪টি বিট লাগবে, যা ৮ দিয়ে ভাগ করলে ৩২,৭৬৮ বাইট (৩২ কিলোবাইট) হয়। এই ছোট্ট হিসাব দেখায় কেন বিটম্যাপ বাস্তবে "সস্তা" — মূল ডিস্কের তুলনায় এটি নগণ্য জায়গা নেয়।

  2. পরীক্ষা করুন: উপরের কোড সেলে TOTAL_BLOCKS-কে 16 থেকে 32-এ পরিবর্তন করে চালান — শেষের a4 = allocate(bitmap, 20) কল এখন সফল হয় কি না দেখুন।

    হ্যাঁ, এখন সফল হবে। বিটম্যাপের আকার ৩২-এ বেড়ে যাওয়ায় আগের বরাদ্দগুলোর (মোট ১২টি ব্লক ব্যবহৃত) পরও ব্লক ১২ থেকে ৩১ পর্যন্ত ২০টি টানা ফ্রি ব্লক পাওয়া যাবে — যা ঠিক প্রয়োজনীয় দৈর্ঘ্যের সমান। এটি দেখায় ফ্র্যাগমেন্টেশন সমস্যাটি স্থির নয় — ডিস্কের মোট আকার ও ব্যবহারের ধরনের ওপর নির্ভরশীল একটি পরিস্থিতি-নির্ভর সমস্যা।

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

আগের পাঠ
ফাইল অ্যালোকেশন মেথড