همون طور که می دونید میکرو کنترلر در واقع یک میکروپروسسور به همراه حافظه ی RAM و ROM و تعدادی IO هست. پس مقایسه ای که می خوام انجام بدم خیلی هم مقایسه ی بدی نیست. (برای درک بهتر مطلب می تونه مفید واقع بشه).
بیایید و خودتون رو بذارید جای سخت افزار محاسبه گر یعنی CPU. خوب شما یک واحد حساب و کتاب دارید و البته چندتا واحد کمکی دیگه مثل واحد کنترل و ... . همون طور که در درس هایی مثل مدار منطقی و معماری کامپیوتر دیدید، برای سنکرون کردن واحدهای مختلف پردازنده از یک واحد تولید کلاک استفاده می شود. یعنی قطعا شما یک مولد موج مربعی دارید که در مثلا لبه ی بالا رونده ی هر پالس اون یک سیکل عملیاتی CPU اتفاق می افته! حالا سوالی که پیش می یاد این هست که وقتی شما پردازنده رو روشن می کنید قطار پالستون قطع و وصل می شه یا نه؟ مسلما پاسخ این هست که خیر! یعنی از لحظه ی شروع به کار پردازنده قطار پالس رو داریم. پس عملا وقتی شما پردازنده ی خودتون رو روشن می کنید در یک حلقه ی بی نهایت مدام در حال کار هست. حالا اگر دستوری برای محاسبه داشته باشه اون دستور رو اجرا می کنه و اگر دستوری نباشه NOop می زنه (NO Operation) اما دقت کنید که سیکل اجرایی سی پی یو طی می شه. پس ((همیشه سی پی یو در یک حلقه ی بی نهایت در حال اجرا است. این شما هستید که باید وسط این گردش بی هدف سی پی یو ازش استفاده ی مفید بگیرید.)) این درست مثل سوختن خورشید هست که داره انرژی رو تولید می کنه حالا این دیگه هنر ما هست که چقدر ازش استفاده کنیم.
اما بریم سراغ نکته ی گیج کننده ای که باعث می شه بعضی ها با حلقه ی بی نهایت به راحتی کنار نیایند!!!!
به احتمال زیاد همه ی شما برنامه ای نوشتید که بیوفته توی حلقه ی بی نهایت. (اگر ننوشتید غضه نخورید کد زیر رو کامپایل کنید!!!)
void main() { while(true) ; }
اگر کد بالا رو اجرا کنید سریعا متوجه می شید که سی پی یو کامپیوترتون خیلی بهش فشار میاد. اگر task manager رو ببینید می بینید که cup usage صد در صد شده و تقریبا سیستم کند شده یا حتی هنگ کرده! پس منطقا شما مجازید این طور فکر کنید که حلقه ی بی نهایت یعنی یک کار بد! یعنی یک ایده ی احمقانه!!!
اما واقعیت این هست که این حلقه ی بی نهایت با اون یکی فرق می کنه!!! حلقه ی بی نهایتی که من دارم ازش صحبت می کنم بیرونی ترین حلقه ی کاری سی پی هست که همه ی کارها را مدیریت می کنه ولی این یکی که شما نوشتید (کد بالایی) یک حلقه ی داخلی هست که سی پی رو توی یک ذره جا گیر انداخته!!!
بذارید برگردیم به کد میکرو! خیلی کمک می کنه!!!! کد ما به صورت زیر بود.
void main (void) { while(1) { if ( some_condition) func1(); else if (some_condition) func2(); else func3(); } }
می بینید که میکرو کنترلر ما در یک حلقه ی بی نهایت قرار داره و مدام شروطی رو چک می کنه. هر وقت یکی از شروط ارضا بشه کار خاصی توسط یکی از توابع اجرا می شه. بعد از اینکه اجرای این تابع تموم شد دوباره حلقه تکرار می شه و شروط بررسی می شوند و ...
خوب حالا فرض کنید که به نحوی درایم micro usage سه تابع فوق را می سنجیم و در جایی نشون می دیم. طبیعی است که تعداد دستوراتی که هر یک از توابع فوق در یک بازه ی زمانی اجرا می کنند سهم آن ها از مصرف micro رو می ده. مثلا اگر در 100 میلی ثانیه سیکل اجرایی میکرو رو مانیتور کنیم و ببینیم که مثلا 2000 تا دستور برای تابع اول، 10000 تا برای تابع دوم و 3000 تا برای تابع سوم هست نتیجه می گیریم که micro usage سه تابع به ترتیب برابر با 13، 67 و 20 درصد خواهد بود.
حالا اگر یک آدم ناشی پیاده سازی تابع سوم را به صورت زیر بازنویسی کند چه اتفاقی می افتد؟
void func3() { while(1) ; }
طبیعی است که میکرو در یک loop به درد نخور بی نهایت گیر می افته و عملا micro usage یا همون cpu usage خودمون برای تابع سومی 100 درصد و برای اون دو تای دیگه صفر می شه!!!!
در سیستم عامل کلیت بحث رو میشه به همین سادگی که خدمتتون عرض کردم در نظر گرفت ولی در واقعیت الگوریتم های مفصل تری برای scheduling سی پی یو وجود داره. اما برای فهم مطلب به نظرم مثالی که عرض کردم بد نبوده و امیدوارم مفید واقع بشه.
یک بحث دیگه هم می مونه که من فعلا از پرداختن به اون خودداری می کنم زیرا فقط باعث پیچیده تر شدن کلام می شه. سعی می کنم در یک فرصت دیگه به اون بپردازم. (بحث Interupt ها یا همون وقفه ها)
در کل پیشنهاد می کنم که سعی کنید مطالب بنیادین رو در قالب ساده ترین مدل ها برای خودتون تحلیل کنید. تجربه نشون داده که ما آدم ها موقعی که پیچیده فکر می کنیم گند می زنیم.