وبلاگ میثم پاسداری هریس

۱ مطلب با کلمه‌ی کلیدی «سمافور در زبان c» ثبت شده است

  • ۳
  • ۰

در این بخش سوالی از مبحث همگام سازی Synchronization را که با استفاده از ابزار سمافور (Semaphore) به صورت عملی قابل حل است،  آورده ام. 

چند نخی در سیستم عامل

سوال) برنامه ای دارای دو Thread است که 10 عدد را در یک متغیر می نویسند، یکی از Thread ها می نویسد و Thread دیگر عدد نوشته شده را می خواند. چه مشکلی می تواند رخ بدهد و به چه شکلی می توان آن را برطرف کرد؟

پاسخ)  

قبل از حل بهتر است یک سری مفروضات را از روی سوال تشخیص دهیم و جدا کنیم:

تعاریف:

حافظه مشترک (Shared Memory): هر دوی Thread ها با متغیر مشترک در کد سر و کار دارند(همانطور که در شکل مشخص است بخش Data بین Thread ها در محیط Multi Threading مشترک است) به همین دلیل متغیر برنامه، حافظه مشترک در این مسئله است.

ناحیه بحرانی (Critical Section): قسمتی از کد که در آنجا حافظه مشترک مورد دسترسی قرار می گیرد.

مشکل:

 انحصار متقابل (Mutual Exclusion): اگر یکی از Thread ها در ناحیه بحرانی باشد، Thread دیگری نباید وارد ناحیه بحرانی شود در حالیکه در این سوال این مورد می تواند اتفاق بیافتد یعنی هر دو Thread در یک مقطع از زمان در ناحیه بحرانی باشند و حافظه مشترک را بخوانند یا بنویسند!

راه حل:

یکی از راه هایی که می توان مشکل انحصار متقابل را در این مسئله حل کرد، استفاده از سمافور هاست (در اینجا سمافورهایی که POSIX در اختیار ما گذاشته).

نکته: POSIX مخفف عبارت Portable Operating System Interface است و کتابخانه ایست که توسط IEEE معرفی شده و در حال حاضر بر روی لینوکس وجود دارد.

سورس کد زیر به زبان C، راه حل پیشنهادی من برای حل این مسئله به صورت عملی در محیط لینوکس می باشد.


بخش1) فراخوانی Herader Fileها، تعریف متغیر ها، تعریف سمافور ها و ایجاد Thread ها

فراخوانی ها و بدنه برنامه

بخش2) روال مربوط به نوشتن (Writer) که توسط thread_a اجرا می شود.

ٌٌ

(1): در این قسمت که ورود به ناحیه بحرانی (Entry Section) است، سمافور writesem ، منتظر می ماند، و این انتظار تا زمانی که سیگنالی (post ای) از طرف readsem بیاید، طول می کشد؛ یعنی بعد از خوانده شدن حافظه مشترک، نوشتن در حافظه صورت می گیرد. 

(2): در این قسمت به سمافور readsem اطلاع می دهد که داده نوشته شد و می توانی آن را از حافظه مشترک بخوانی.


بخش3) روال مربوط به خواندن (Reader) که توسط thread_b اجرا می شود.

Writer Thread

(3): در این قسمت اگر خواننده دیگری بیاید، منتظر می ماند تا زمانی که خواننده فعلی مقداری را بخواند و بعد از آن سیگنال دهد.

(4): در این قسمت هم بخش خروج از نایحه بحرانی (Exit Section) است، سمافور نویسنده سیگنال می دهد که عمل خواندن انجام شد و می توانی بنویسی.


نکته 1) Mutex سمافوری باینری است که ورود Thread ها به ناحیه بحرانی را اصطلاحا سریالی (Serialized) می کند، در این برنامه، سمافور های مورد استفاده از نوع Mutex می باشند که با تابع sem_init مشخص شده است.

نکته 2) برای کامپایل Source Code در محیط لینوکس، دستور زیر را در Terminal اجرا کنید:

gcc -o sem-compiled sem.c -Wall -Werror -lpthread

نکته 3) مسئله مورد بحث، شبیه مسئله معروف Readers & Writers می باشد.


لینک 1)  دانلود Source Code برنامه در زبان C

لینک 2)  نمونه خروجی برنامه، با استفاده از سمافور ها

لینک 3)  یک نمونه از خروجی برنامه، بدون استفاده از سمافور ها

    • میثم پاسداری