در سلسله آموزش های تحلیل و بررسی سیستم عامل FreeRTOS، قسمت چهارم به یکی از مهم ترین مفاهیم سیستم عامل، Semaphore سمافور می پردازیم. در قسمت پیشین به صورت پایه ای وساده، اجرای دو برنامه بر روی برد آردوینو را مشاهده نمودیم. همانطور که از قسمت پیشین به یاد داریم، سیستم عامل FreeRTOS می تواند به اجرای چندین برنامه بر روی یک پردازنده AVR در بردهای آردوینو بپردازد. یک سیستم عامل تنها مدیریت اجرای چند برنامه را بر عهده ندارد. چراکه علاوه بر این منابع مختلف نظیر حافظه توسط سیستم عامل باید مدیریت شوند. زمانیکه چندین برنامه قصد دسترسی به یک نقطه مشترک از حافظه را دارند، سیستم عامل وظیفه مدیریت درخواست های دو برنامه را برعهده می گیرد.
یکی از مفاهیم مهم و پایه ای در سیستم عامل، بحث Semaphore سمافور است. سمافور قابلیتی است که به کمک آن، سیستم عامل می تواند درخواست های مشترک از منابع را توسط Task های مختلف را مدیریت کند. در این آموزش قصد داریم تا به سمافور را در سیستم عامل FreeRTOS بررسی کنیم. ابتدا به بررسی مفاهیم پایه سمافور و کاربرد آن می پردازیم. سپس در ادامه مطابق آموزش های پیشین، دستورات پایه و برنامه را مشاهده خواهیم نمود. بنابراین در ادامه آموزش، با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک، همراه باشید.
دسترسی به منابع مشترک در سیستم عامل
یکی از مشکلاتی که در اجرای سیستم عامل ها پیش می آید، دسترسی همزمان چند برنامه(Task) به یک نقطه مشترک از حافظه است. البته این دسترسی همزمان علاوه بر حافظه می تواند شامل سایر منابع مانند پورت های سریال نیز شود. برای روشن تر شدن موضوع، فرض کنید یک متغیر global دارید. از آنجاییکه این متغیر گلوبال است، دو برنامه(Task) می توانند به طور همزمان به مقدار این متغیر دسترسی داشته و یا مقدار آن را دستکاری کنند.
در اینجا همزمان شدن دسترسی به حافظه سبب ساز ایجاد مشکلاتی خواهد شد. این مشکل دسترسی یک Task به متغیر در زمانیست که Task دیگر آن را از پیش در اختیار داشته باشد. به عبارت دیگر، فرض کنید یک Task مشغول انجام کار روی یک متغیر است. از طرف دیگر، Task دیگر هم قصد دسترسی به متغیر دارد. از آنجاییکه یک Task مشغول کار بر روی یک متغیر بوده و Task دیگر هم در همان لحظه بخواهد مقدار متغیر را تغییر دهد، این موضوع سبب ایجاد تداخل و خراب شدن مقدار نهایی متغیر خواهد شد.
این مورد تنها مختص به حافظه نیست؛ بلکه در سایر منابع CPU ممکن است چنین تداخلی پیش بیاید. به عنوان مثال فرض کنید یک برنامه قصد به نوشتن داده روی سریال مانیتور دارد. در طرف دیگر، برنامه دیگری می خواهد فرامین دریافتی از کاربر را از طریق سریال مانیتور دریافت کند. در اینجا در صورتیکه همزمان دو برنامه بخواهند قصد استفاده از سریال مانیتور را داشته باشند، موضوع پیچیده شده و تداخل پیش خواهد آمد. جهت جلوگیری از این موضوع، باید مکانیزمی طراحی شود که از این تداخل جلوگیری شده و در اصطلاح مورد Thread Safe باشد. این مورد توسط سمافور قابل حل خواهد بود. در قسمت بعد به این موضوع می پردازیم.
تعریف Semaphore سمافور در RTOS
همانطور که در قسمت پیشین بیان شد، زمانیکه دو Task قصد دسترسی همزمان به یک ناحیه مشترک از حافظه و یا منبع دیگری نظیر پورت سریال را داشته باشند، تداخل پیش خواهد آمد. جهت جلوگیری از این تداخل، از مفهومی به نام Semaphore سمافور در سیستم عامل استفاده می شود. سمافور همانند یک برچسب، مشغول و یا آزاد بودن یک منبع را تعیین می کند. زمانیکه یک قسمت از پردازنده نظیر حافظه یا پورت های ارتباطی توسط یک Task در حال استفاده است، سمافور برچسب مشغول روی آن قرار می دهد. در این حالت اگر Task دیگری قصد استفاده از منبع را داشته باشد، با مشاهده برچسب متوجه اشغال بودن آن شده و دیگر به آن منبع امکان دسترسی نخواهد داشت.
با توجه به مطالب بیان شده، سمافورها وظیفه کنترل دسترسی به منابع را دارند. در صورتیکه یک منبع مشغول بوده و منبع دیگری هم قصد استفاده از آن را داشته باشد، سمافور جریان را کنترل می کند. در قسمت بعدی با دستورات سمافور در سطح سیستم عامل آشنا خواهیم شد.
دستورات پایه ای تعریف سمافور در FreeRTOS
پس از بررسی مفهوم Semaphore سمافور، نوبت به دستورات آن می رسد. همانطور که مطابق تعریف سمافور دریافتیم، زمانیکه یک Task مشغول کار با یک منبع باشد، Task دیگر نمی تواند آن منبع را تا اتمام کار Task پیشین در اختیار بگیرد. برای این مورد، ابتدا باید کتابخانه سمافور مطابق دستور زیر فراخوانی شود.
#include <semphr.h>
پس از این مورد، باید از کلاس کتابخانه سمافور یک نمونه شی تعریف کنیم. این مورد به صورت زیر اجرا می گردد.
SemaphoreHandle_t mutex
پس از مورد فوق، درون تابع setup تابع سازنده کلاس کتابخانه به شکل زیر فراخوانی می گردد.
mutex = xSemaphoreCreateMutex()
در ادامه موارد فوق، هرگاه که بخواهیم وضعیت یک منبع را از لحاظ آزاد و یا اشغال بودن کنترل کنیم، از تابع زیر استفاده می کنیم.
xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait )
به کمک تابع فوق می توانیم از طریق سمافور وضعیت منبع را کنترل نماییم. در تابع فوق دو ورودی از چپ به راست به شکل زیر تعریف می شوند.
۱- متغیر تعریف شده از کلاس کتابخانه
۲-مدت زمان برای انتظار جهت آزاد شدن منبع
در صورتیکه منبع آزاد باشد، خروجی تابع برابر با pdTRUE خواهد شد. در قسمت بعد با ارایه مثال، موضوع بیشتر روشن خواهد شد.
اجرا و بررسی یک نمونه برنامه سمافور
پس از بررسی دستورات مربوط به سمافور، نوبت به اجرای یک نمونه برنامه می رسد. برای این مورد از منوی File->Examples->Free RTOS->Mutex را انتخاب و اجرا کنید. در این برنامه یک متغیر عمومی با نام globalCount تعریف شده است. مقدار این متغیر توسط Task تغییر می کند. در این برنامه دو Task تعریف شده است. البته توجه داشته باشید که در این برنامه یک تابع تعریف شده و در هر دو تابع xTaskCreate ، این تابع به عنوان Task معرفی می شود. در حقیقت انگار که دو Task قصد دستکاری متغیر را دارند، در این جا تابع xSemaphoreTake وضعیت را کنترل کرده و اجازه دسترسی به حافظه را جهت تغییر متغیر، صادر می کند.
لوازم مورد نیاز
لینک خرید انواع برد آردوینو، کلیک کنید
جمع بندی
در مجموعه آموزش های سیستم عامل FreeRTOS مخصوص برد آردوینو، این قسمت را به سمافور اختصاص دادیم. سمافور یکی از مهم ترین و پایه ای ترین مفاهیم در سیستم عامل محسوب می شود. به کمک این مفهوم می توان از دسترسی همزمان چندین برنامه به یک منبع و ایجاد اختلال جلوگیری نمود. در این آموزش به بررسی مفهوم سمافور پرداختیم. پس از بررسی مفاهیم پایه، دستورات اساسی آن در سیستم عامل بررسی گردید. پس از این با بررسی یک نمونه برنامه، مفهوم سمافور و استفاده از آن در برنامه ها مشاهده گردید.
چنانچه در مفاهیم این آموزش با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریعترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در مطالب مندرج وجود دارد میتوانید از همین طریق اطلاع رسانی کنید.