Эгзэгтэй муж

Олон програм зэрэг хамтран ажиллах үед тэдгээрийн дунд ашиглагдаж буй мэдээлэл, төхөөрөмж зэрэгт нэг дор олон хандалт үүсгэхгүй байх үүднээс эгзэгтэй мужийн асуудал яригддаг. Өөрөөр хэлбэл процессууд дундаа ашигладаг функц, хүснэгт зэрэгт хандсан тухайн процессын өөрийнх нь кодын хэсгийг эгзэгтэй муж гэнэ. Тухайн эгзэгтэй муж нь тодорхой хугацаанд нээгдэж, хаагдах ба түүнд хандахыг хүссэн процесс, таск зэрэг нь хүсэлт үлдээн хэсэг хугацаанд хүлээлтийн горимд ордог. Иймээс процесс эсвэл таск нь эгзэгтэй мужид орж гарч байгааг зохицуулах механизмууд бий болжээ. Жишээ нь Семафор.

## Эгзэгтэй мужийн асуудал
N тооны процессоос тогтсон систем байна гэж төсөөл. {P0, P1, P2.... Pn-1 г.м} Процесс бүрт эгзэгтэй муж гэж байх ба тэр хэсэг нь уг процессуудын дундын эзэмшлийн хувьсагч, хүснэгт, аль эсвэл өгөгдлийг өөрчилдөг гэж үзье. Зэрэг хандалт хийгдэх үед маш том асуудал үүсэх учраас үйлдлийн системийн гол үүрэг бол эгзэгтэй мужид нэг дор нэгээс олон процесс оруулахгүй байх явдал. Энэ асуудлыг шийдэхийн тулд процессуудыг хамтран ажилуулж чадахуйц нь зохицуулах механизм боловсруулах хэрэгтэй. Процесс болгон эгзэгтэй муж руу орохын өмнө хүсэлт явуулдаг байх ёстой. Механизмын энэ хэсгийг хэрэгжүүлж буй кодыг оролтын хэсэг гэнэ. Хүсэлт явуулж зөвшөөрөл авсны үндсэн дээр эгзэгтэй мужид нэвтэрсэн процесс гаралтын кодын хэсэгт дуусна. Үлдсэн бусад кодыг үлдэгдэл хэсэг гэнэ.
## Онол(ерөнхий)
Процесс болгон эгзэгтэй муж руу орохын өмнө хүсэлт явуулдаг байх ёстой. Механизмын энэ хэсгийг хэрэгжүүлж буй кодыг оролтын хэсэг гэнэ. Хүсэлт явуулж зөвшөөрөл авсны үндсэн дээр эгзэгтэй мужид нэвтэрсэн процесс гаралтын кодын хэсэгт дуусна. Үлдсэн бусад кодыг үлдэгдэл хэсэг гэнэ.
Зэрэг хандалт хийгдэх үед маш том асуудал үүсэх учраас үйлдлийн системийн гол үүрэг бол эгзэгтэй мужид нэг дор нэгээс олон процесс оруулахгүй байх явдал. Энэ асуудлыг шийдэхийн тулд процессуудыг хамтран ажилуулж чадахуйц нь зохицуулах механизм боловсруулах хэрэгтэй. Процесс болгон эгзэгтэй муж руу орохын өмнө хүсэлт явуулдаг байх ёстой. Механизмын энэ хэсгийг хэрэгжүүлж буй кодыг оролтын хэсэг гэнэ.

Эгзэгтэй мужийн асуудлыг шийдэхийн тулд дараах шаардлагуудыг хангасан байх шаардлагатай.
1. Давхар нэвтрэлтийг хорих (Mutual exclusion)
Хэрэв нэг процесс эгзэгтэй мужид нэвтэрсэн бол өөр процесс үл нэвтрүүлэх
2. Явцыг дэмжих (progress)
Өөр ямар ч процессд эгзэгтэй муж үүсээгүй байхад процесс түүнийг хүлээх ёсгүй.
3. Дамжсан хүлээлт (bounded waiting)
Процесс тодорхой хугацаанд л эгзэгтэй мужид байх ёстой.

## Эгзэгтэй муж талаар ойлголт
**Process A:** 
```c
// Process A
 .
 .
 b = x+5;                 // instruction executes at time = Tx
 .
```
**Process B:** 
```c
// Process B
.
.
x = 3+z;                 // instruction executes at time = Tx
.
```

## Аппликэйшн түвшний эгзэгтэй муж
Аппликэйшн түвшний эгзэгтэй муж нь ихэвчлэн санах ойн тухайн хэсгийг аль процесс эзллэх тухайд яригддаг. 

**POSIX pthread санд эгзэгтэй мужийг шийдэх жишээ код**

```c
/* C/C++ Жишээ, Unix/Linux */
#include 

/* Энэ бол эгзэгтэй муж объект (тогтмолоор өгөгдсөн). */
static pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;

void f()
{
    /* Эгзэгтэй мужид орох хэсэг -- Бусад процессүүд цоожлогдоно */
    pthread_mutex_lock( &cs_mutex );
 
    /* Энэ хэсэгт бусад процессуудаас хамааралгүй аюулгүй тооцоолол хийгдэнэ! */

    /*Эгзэгтэй мужаас гарах хэсэг -- бусад процессүүд эгзэгтэйи мужид орох эрхтэй болно. pthread_mutex_lock()  */
    pthread_mutex_unlock( &cs_mutex );
}

int main()
{
    f();

    return 0;
}
```

**Win32 API санд эгзэгтэй мужийг шийдэх жишээ код**

```c
/* C/C++ жишээ, Windows */
#include 

static CRITICAL_SECTION cs; /* Эгзэгтэй муж объект үүссэний дараа санах ойд зөөж шилжүүлэх боломжгүй */
                            /* объект хандалтат хэл дээр тогтмолоор зарлахгүй байж болно */ 
void f()
{
    /* Эгзэгтэй мужид орох хэсэг -- Бусад процессүүд цоожлогдоно */
    EnterCriticalSection(&cs);

     /* Энэ хэсэгт бусад процессуудаас хамааралгүй аюулгүй тооцоолол хийгдэнэ! */

   /*Эгзэгтэй мужаас гарах хэсэг -- бусад процессүүд эгзэгтэйи мужид орох эрхтэй болно. pthread_mutex_lock()  */
    LeaveCriticalSection(&cs);
}

int main()
{
    /* Олон процесс ашиглах үйлдэл хийгдэхээс өмнө эгзэгтэй муж объект үүсгэнэ */
    InitializeCriticalSection(&cs);

    f(); 

    /* Дуусмагц объектыг арилгана */
    DeleteCriticalSection(&cs);

    return 0;
}
```

## Кернелийн түвшиний эгзэгтэй муж 
Кернелийн түвшинд эгзэгтэй муж нь процессууд болон хуулбар процессууд хоорондоо зөрчилдөлгүй ажиллах боломжыг хангаж өгдөг.

Зарим үйлдлийн систем нэг зэрэг олон эгзэгтэй муж /холбоотой процессууд бүрт нэг/ үүсгэж ажилладаг. 

Диспетчер нь процессуудыг хооронд нь зохицуулах ба эгзэгтэй мужид байгаа процессыг дараа биелүүлэхээр түр зогсоох эсвэл эгзэгтэй мужаас гартал нь хүлээсний дараа дараагын процессд эгзэгтэй муж олгох зэргийг хариуцна.

## Эгзэгтэй мужийн төвшин
Кернелийн түвшинд эгзэгтэй муж нь процессууд болон хуулбар процессууд хоорондоо зөрчилдөлгүй ажиллах боломжыг хангаж өгдөг.
Зарим үйлдлийн систем нэг зэрэг олон эгзэгтэй муж /холбоотой процессууд бүрт нэг/ үүсгэж ажилладаг.

Диспетчер нь процессуудыг хооронд нь зохицуулах ба эгзэгтэй мужид байгаа процессыг дараа биелүүлэхээр түр зогсоох эсвэл эгзэгтэй мужаас гартал нь хүлээсний дараа дараагын процессд эгзэгтэй муж олгох зэргийг хариуцна.
Кернелийн төвшин гэж байдаг бөгөөд кернелийн түвшний эгзэгтэй муж нь процессууд болон хуулбар процессууд хоорондоо зөрчилдөлгүй ажиллах боломжыг хангаж өгдөг.Зарим үйлдлийн систем нэг зэрэг олон эгзэгтэй муж /холбоотой процессууд бүрт нэг/ үүсгэж ажилладаг.
Диспетчер нь процессуудыг хооронд нь зохицуулах ба эгзэгтэй мужид байгаа процессыг дараа биелүүлэхээр түр зогсоох эсвэл эгзэгтэй мужаас гартал нь хүлээсний дараа дараагын процессд эгзэгтэй муж олгох зэргийг хариуцна.
Гүйцэтгэлийн өргөжүүлэлт нь бүх чухал хэсгүүд нь гарах үед хүлээгдэж тасалдлуудыг гүйцэтгэх болон хуваарилагчийн бүх чухал хэсгүүд нь гарах ажиллуулах боломжийг олгодог.
Чухал хэсэг нь урт хугацааны түгжих бааз болгон ашиглаж болохгүй.Mиймээс энэ нь хангалттай хуваарилагч-аас гарч ямар ч тасалдлууд ч гарсан техник хангамж гүйцэтгэсэн байх ёстой.

## Эгзэгтэй муж өгөгдлийн бүтэц онцлох хэсэг
Зэрэгцээ програмчлал онд код сэдвээр хуваагддаг.Процесс болгон эгзэгтэй муж руу орохын өмнө хүсэлт явуулдаг байх ёстой. Механизмын энэ хэсгийг хэрэгжүүлж буй кодыг оролтын хэсэг гэнэ. Хүсэлт явуулж зөвшөөрөл авсны үндсэн дээр эгзэгтэй мужид нэвтэрсэн процесс гаралтын кодын хэсэгт дуусна. Үлдсэн бусад кодыг үлдэгдэл хэсэг гэнэ.
Эгзэгтэй мужийн асуудлыг шийдэхийн тулд дараах шаардлагуудыг хангасан байх шаардлагатай. 1. Давхар нэвтрэлтийг хорих (Mutual exclusion) Хэрэв нэг процесс эгзэгтэй мужид нэвтэрсэн бол өөр процесс үл нэвтрүүлэх 2. Явцыг дэмжих (progress) Өөр ямар ч процессд эгзэгтэй муж үүсээгүй байхад процесс түүнийг хүлээх ёсгүй. 3. Дамжсан хүлээлт (bounded waiting) Процесс тодорхой хугацаанд л эгзэгтэй мужид байх ёстой.Зэрэгцээгээр хооронд хувааж чадахгүй байгаа өгөгдлийгхэрэгжүүлэх хувьсагч нь улмаар маш хэцүү байдаг байх.Элементийг хайж утас зүгээр л тодорхой хугацааны дараа түүнийг устгаж болно.  Код нь хүлээгдэж буй үр дүнг үзүүлдэг болохыг баталгаажуулдаг

## Эх сурвалж 
*Critical Section documentation on the MSDN Library
*Tutorial on Critical Sections

Ангилал:Үйлдлийн системийн онол
Ангилал:Зэрэгцээ тооцоолол