تخصیص استاتیک تا پیشگیری از Stack Overflow - قسمت اول مدیریت صحیح حافظه در سیستم های امبدد

مدیریت_صحیح_حافظه_در_سیستم‌های_امبدد
46 بازدید
۱۴۰۴-۰۳-۰۵
5 دقیقه

چند روز پیش توی دورهمی سوم سیسوگ (sug3) یه ارائه در مورد مقوله مدیریت حافظه داشتم ولی خوب به دلیل کمبود تایم نشد اونظور که دوست داشتم به چالش ها وباید و نباید های مدیریت حافظه مخصوصاً در سیستم‌های امبدد بپردازم، برای همین در این مقاله سعی می‌کنم تا جای ممکن مبحث رو بازش کنم و اونچه در مورد مدیریت حافظه میدونم رو باشما به اشتراک بذارم برای نوشتن ایم مطلب هم از منبع ۱ و منبع ۲ و منبع ۳ و البته دو سه تای دیگه که لینکشون رو الان پیدا نکردم. فرقی نمی‌کنه از حافظهٔ استاتیک استفاده می‌کنید، یا یه پشتهٔ ساده دارین یا حافظه رو به‌صورت داینامیک روی هیپ مدیریت می‌کنید؛ در هر حال باید با دقت و وسواس جلو رفت مخصوصاً اگر میخوایم دچار باگ های عجیب و غریب نشیم.
تو دنیای امبدد، بی‌توجهی و سرسری گرفتن ریسک‌های مدیریت حافظه، می‌تونه خیلی گرون تموم بشه (خیلی گرون)!

تقریباً هر برنامه‌ای با RAM سر و کار داره، اما این که این حافظه چطوری بین بخش‌های مختلف برنامه  تقسیم بشه، داستان‌های زیادی داره که توی این مقاله قراره به چندتاییش بپردازیم.
توی این مطلب، قراره روش‌های مختلف مدیریت حافظه رو یه دور مرور کنیم تا توی پروژه‌های بعدی، انتخاب‌‌های بهتری داشته باشیم.

از تخصیص کامل حافظه به‌صورت استاتیک گرفته، تا استفاده از یه یا چندتا پشته و همین‌طور هیپ(heap)، همه رو بررسی می‌کنیم.
همچنین قراره ببینیم که پیاده‌سازی هیپ چطور ممکنه باعث تکه‌تکه شدن حافظه (Fragmentation) بشه و چه تأثیری روی عملکرد سیستم‌ها داره.

تخصیص استاتیک حافظه؛ خیال راحت از همون اول!

اگه کل حافظه رو به‌صورت استاتیک تخصیص بدیم، می‌تونیم دقیقاً موقع کامپایل مشخص کنیم که هر بایت از RAM قراره کجا و چطوری مصرف بشه. تو دنیای امبدد، این یه مزیت خیلی بزرگه! چون دیگه خبری از باگ‌های مرموز حافظه مثل memory Leak ، خطاهای تخصیص، یا اشاره‌گرهای سرگردان (Dangling Pointers) نیست.

خیلی از کامپایلرهای پردازنده‌های ۸ بیتی مثل خانوادهٔ 8051 یا PIC، دقیقاً برای همین کار طراحی شدن: یعنی همه چیز رو استاتیک مدیریت می‌کنن.
توی این مدل، داده‌ها یا global هستن، یا static (داخل فایل یا تابع)، یا local به یک تابع.

  • داده‌های global و static همیشه تو یه جای ثابت از حافظه قرار می‌گیرن، چون باید در طول عمر برنامه در دسترس بمونن.
  • داده‌های local هم یه مدل جالب دارن: برای هر تابع، یه بلوک مشخص از حافظه کنار گذاشته میشه. یعنی مثلاً اگه یه تابع متغیر محلی x داشته باشه، هر بار که این تابع صدا زده میشه، x دقیقاً تو همون جای همیشگی حافظه قرار می‌گیره.
    وقتی تابع اجرا نمی‌شه، اون فضا آزاد می‌مونه.

این شیوه بیشتر توی C Compiler هایی استفاده میشه که سخت‌افزارشون پشتیبانی مناسبی برای استک نداره.

شکل زیر ساختار حافظه رو در این حالت نشون میده: بدون هیپ، بدون استک، فقط دیتاهای global و یک بلاک استاتیک برای هر تابع.

ساختار حافظه بدون هیپ، بدون استک، فقط دیتاهای global و یک بلاک استاتیک برای هر تابع

ساختار حافظه بدون هیپ، بدون استک، فقط دیتاهای global و یک بلاک استاتیک برای هر تابع

این روش یه محدودیت مهم داره: دیگه خبری از تابع بازگشتی (Recursion) یا صدا زدن تابع در تابع نیست!
مثلاً یه روال وقفه (Interrupt Handler) نمی‌تونه تابعی رو صدا بزنه که ممکنه همزمان از مسیر اصلی برنامه هم صدا زده بشه. در عوض، خیال برنامه‌نویس از بابت مشکلات تخصیص حافظه در زمان اجرا راحت میشه.

خیلی خوب می‌شد اگه همهٔ کامپایلرها یه گزینه داشتن که اجازه می‌داد بدون استفاده از استک، همهٔ حافظه رو به صورت استاتیک تخصیص بدیم.
البته باید قبول کنیم که با این کار، مقداری از انعطاف و کارایی سیستم قربانی میشه، ولی در عوض، پایداری و امنیت حافظه واقعاً زیاد میشه.

کامپایلرهای باهوش‌تر حتی می‌تونن بفهمن که دو تا تابع خاص هیچ وقت همزمان صدا زده نمیشن؛ برای همین، اجازه میدن حافظهٔ این دو تابع با هم overlap داشته باشه (یعنی یه جا رو مشترک استفاده کنن).
البته این کار یه محدودیت اضافه هم داره: دیگه نمی‌تونیم از function pointerها استفاده کنیم.

اگه می‌خوای واقعاً از حافظهٔ استاتیک لذت ببری، نباید با کارهایی مثل استفادهٔ دوباره از global data برای اهداف مختلف، محیط امن استاتیک رو خراب کنی!

البته این روش برای سیستم‌های بزرگ جوابگو نیست، چون اگه بخوایم هر مسیر اجرایی احتمالی رو پوشش بدیم، مقدار وحشتناکی RAM لازم داریم و این در عمل شدنی نیست.

مدیریت حافظه با استک!

قدم بعدی تو مدیریت حافظه اینه که به سیستم استک اضافه کنیم. حالا دیگه به جای این‌که فقط یه بلاک حافظه برای هر تابع وجود داشته باشه، برای هر بار فراخوانی تابع باید یه بلاک جدید روی استک ساخته بشه. این بلاک‌ها همون چیزین که بهشون Stack Frame می‌گیم.

استک با اجرای برنامه مدام بزرگ و کوچیک میشه. توی خیلی از برنامه‌ها، پیش‌بینی اینکه “بدترین حالت” مصرف استک چقدره، موقع کامپایل ممکن نیست 🙁
تو سیستم‌های چندوظیفه‌ای (Multitasking)، هر تسک (Task) استک خودش رو داره (و شاید یه استک اضافی هم برای وقفه‌ها).

برنامه‌نویس باید حسابی حواسش جمع باشه که هر استک برای کارهای خودش به اندازه کافی جا داشته باشه.
هیچ چیز بدتر از یه Stack Overflow ناگهانی نیست! مخصوصاً اگه ببینی یه استک دیگه کلی جا خالی داره که اصلاً استفاده نمی‌شه!

متأسفانه اکثر سیستم‌های امبدد هم چیزی به اسم Virtual Memory ندارن که تسک‌ها بتونن در صورت نیاز از حافظهٔ اشتراکی استفاده کنن.
پس طراحی درست اندازهٔ استک‌ها یه مهارت خیلی حیاتی محسوب میشه که حیات و ممات یه پرژه بهش بستگی داره !

تخصیص استاتیک تا پیشگیری از Stack Overflow - قسمت اول مدیریت صحیح حافظه در سیستم های امبدد

یه قاعدهٔ طلایی برای محاسبه سایز استک هست که میگه :

اندازهٔ هر استک رو ۵۰٪ بزرگ‌تر از بیشترین مقداری که موقع تست دیدین، در نظر بگیرین.

اما برای اینکه بتونیم این قانون رو درست اجرا کنیم، اول باید بدونیم استک واقعاً تا کجا رشد کرده بوده. یه روش ساده و خلاقانه برای فهمیدن این موضوع هست بهش میگیم “رنگ کردن” فضای استک.
یعنی قبل از اجرای برنامه، کل فضای استک رو با یه الگوی مشخص (مثلاً یه عدد غیر صفر) پر می‌کنیم. وقتی برنامه اجرا میشه و استک بزرگ و کوچیک میشه، داده‌های واقعی این الگو رو کم‌کم پاک می‌کنن. بعداً با یه حلقه ساده میشه استک رو اسکن کرد و فهمید که رشد استک تا کجا پیش رفته.
(شکل زیر یه تصویر واضح از چرخهٔ عمر یک استک ساده رو نشون میده.)

چرخهٔ عمر یک استک ساده

چرخهٔ عمر یک استک ساده

فقط یادتون باشه « الگویی که برای نوشتن توی استک استفاده می‌کنید نباید صفر باشه » چون خیلی وقتا داده‌هایی که روی استک نوشته میشن مقدار صفر دارن، و اون موقع دیگه نمی‌تونین راحت تشخیص بدین کجا واقعاً استفاده شده و کجا نه.

ردیابی استک آورفلو

خیلی از RTOSها یه ویژگی خوب دارن به اسم stack size tracing. اما اگه سیستم عاملت این قابلیت رو نداره، یا اصلاً از RTOS استفاده نمی‌کنی، خبر خوب اینه که خودت هم می‌تونی یه نسخه ساده‌شو پیاده‌سازی کنی.

این تکنیک هم تو فاز تست به درد می‌خوره (برای بهینه کردن اندازهٔ استک)، هم تو محصول نهایی میشه ازش برای هشدار زودهنگام استفاده کرد. داستان اینطوریه که یه watermark (خط نشون) روی استک تعریف می‌کنی و دوره‌ای چک می‌کنی ببینی الگویی که قبلاً نوشتی، پاک شده یا نه. دیگه نیازی نیست هر بار که روی استک چیزی نوشته میشه، بخوای چک کنی که پر شده یا نه ( این کار خیلی پرهزینه و سنگینه). با یه بررسی زمان‌بندی شده میشه خیلی راحت وضعیت رو کنترل کرد.

البته باید بدونی که این روش ممکنه نتونه سرریزهای خیلی سریع (مثل بی‌نهایت بازگشتی‌ها) رو ردیابی کنه، چون استک خیلی سریع پر میشه. اما برای رشدهای کوچیک و غیرمنتظرهٔ استک، این سیستم هشدار عالی جواب میده!

اطلاعات
46
0
1
لینک و اشتراک
profile

Zeus ‌

متخصص الکترونیک

وبسایت: https://sisoog.com

زئوس هستم ساکن المپ

مقالات بیشتر
slide

پالت | بازار خرید و فروش قطعات الکترونیک

قطعات اضافه و بدون استفاده همیشه یکی از سرباره‌‌های شرکتها و طراحان حوزه برق و الکترونیک بوده و هست. پالت سامانه‌ای است که بصورت تخصصی اجازه خرید و فروش قطعات مازاد الکترونیک را فراهم می‌کند. فروش در پالت
family

آیسی | موتور جستجوی قطعات الکترونیک

سامانه آی سی سیسوگ (Isee) قابلیتی جدید و کاربردی از سیسوگ است. در این سامانه سعی شده است که جستجو، انتخاب و خرید مناسب تر قطعات برای کاربران تسهیل شود. وقتی شما در این سامانه، قطعه الکترونیکی را جستجو می‌کنید؛ آی سی به سرعت نتایج جستجوی شما در اکثر فروشگاه‌های آنلاین در حوزه قطعات الکترونیک را نمایش می‌دهد. جستجو در آیسی
family

سیسوگ‌شاپ | فروشگاه محصولات Quectel

فروشگاه سیسوگ مجموعه ای متمرکز بر تکنولوژی های مبتنی بر IOT و ماژول های M2M نظیر GSM، GPS، LTE، NB-IOT، WiFi، BT و ... جایی که با تعامل فنی و سازنده، بهترین راهکارها انتخاب می شوند. برو به فروشگاه سیسوگ
family

سیسوگ فروم | محلی برای پاسخ پرسش‌های شما

دغدغه همیشگی فعالان تخصصی هر حوزه وجود بستری برای گفتگو و پرسش و پاسخ است. سیسوگ فروم یک انجمن آنلاین است که بصورت تخصصی امکان بحث، گفتگو و پرسش و پاسخ در حوزه الکترونیک را فراهم می‌کند. پرسش در سیسوگ فرم
family

سیکار | اولین مرجع متن باز ECU در ایران

بررسی و ارائه اطلاعات مربوط به ECU (واحد کنترل الکترونیکی) و نرم‌افزارهای متن باز مرتبط با آن برو به سیکار
become a writer

نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله
become a writer

نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله
خانواده سیسوگ
سیسوگ‌شاپ

فروشگاه محصولات Quectel

پالت
سیسوگ فروم

محلی برای پاسخ پرسش‌های شما

سیسوگ جابز
سیسوگ
سیسوگ فروم
سی‌کار

اولین مرجع متن باز ECU در ایران

سیسوگ مگ
آی‌سی

موتور جستجوی قطعات الکترونیکی

سیسوگ آکادمی
پالت

بازار خرید و فروش قطعات الکترونیک

دیدگاه ها

become a writer

نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله
become a writer

نویسنده شو !

سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.

ارسال مقاله