Linux System Programing

[리눅스 시스템 프로그래밍_Day5]세마포어, 뮤텍스

Whatman 2018. 12. 14. 17:42

세마포어와 뮤텍스


*동기화 : 두 개 이상의 프로세스가 동일한 자원에 접근할 때 잘못된 연산을 없애고 일관성을 보장한다.


*세마포어

//    sem_test_a.c    // 


#include <stdio.h>

#include <semaphore.h>

#include <pthread.h>


sem_t        sem;  /*TODO: semaphore variable - sem */

pthread_t   task;


void Thread( void ) {

    int i = 0;

    int val;

  

    while(1) {

        i++;


        sem_wait( &sem ); /* TODO: take semaphore */


        sem_getvalue( &sem, &val ); /* get sem value to val */

        printf( "wakeup %d: value = %d\n", i ,val );

        

        if ( i > 5 ) break;

    }

}

//----------------------------------------

void main( void )

{

    int i = 0, j, val;


    sem_init( &sem, 0, 3 ); /* TODO: init unnamed semaphore */


    pthread_create( &task, NULL, (void*(*)(void*))Thread, NULL );

    

    while(1) {

        sleep(1);

        i++;


        printf( "sem post %d\n", i );

        sem_post( &sem ); /* TODO: give semaphore */


        sem_getvalue( &sem, &val ); /* get sem value to val */

        printf( "sem value = %d\n", val );


        if ( i > 5 ) break;

        

    }

}




# cc sem_test_a.c -lpthread

# ./a.out 


wakeup 1: value = 2

wakeup 2: value = 1

wakeup 3: value = 0

sem post 1

sem value = 1

wakeup 4: value = 0

sem post 2

sem value = 1

wakeup 5: value = 0

sem post 3

sem value = 1

wakeup 6: value = 0

sem post 4

sem value = 1

sem post 5

sem value = 2

sem post 6

sem value = 3


/*

현재 6번의 테스크가 실행되게 되어있다.


세마포어는 count가 0이되면 스레드는 block이 된다 (사용 불가능)    ==> sem_wait( &sem ); 가 block이 된다

wakeup 1: value = 2

wakeup 2: value = 1

wakeup 3: value = 0

부분에서 모두 사용 하였고


sem post 1       

sem value = 1

//이때는 반환을 하는 것을 출력하였는데 count가 증가한다 즉, 대기큐에 있는 프로세스들을 깨워 ready 큐로 이동한다. 그래서 count가 증가하여 value도 증가해서 1


wakeup 4: value = 0    //이때 또 task를 실행함으로써 count는 감소

sem post 2

sem value = 1

wakeup 5: value = 0

sem post 3

sem value = 1

wakeup 6: value = 0    //까지 반복한다.


sem post 5

sem value = 2

sem post 6

sem value = 3

//모든 테스크가 끝났을때를 보면 초기값인 value가 3까지 증가한다.



만약 main에서 while의 수가 늘어나면 세마포어는 생성되어진다.

*/






*뮤텍스 

잠김, 풀림으로 테스크 동기화 세마포어처럼 동작하나 소유권, 재귀적 접근, 테스크 삭제 보호,

우선 순위 역전 회피 프로토콜 등을 지원한다(생성시 옵션에 의해서 생성)


//    mutex_test_a.c    // 


#include <semaphore.h>

#include <pthread.h>

#include <sys/types.h>

#include <stdio.h>


/* TODO: define mutex variable and initialize */ 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


int val;

int arg1 = 0, arg2 = 1;


void *Thread( void* arg ) 

{

    int i, j;

    

    for( i = 0; ; i++ ) {

        /* TODO: lock   the mutex */

        pthread_mutex_lock( &mutex );


        val = *(int*)arg;

        printf( "thread %d: %dth iteration: val = %d\n", *(int*)arg, i, val);


        /* TODO: unlock the mutex */

        pthread_mutex_unlock( &mutex );


        sleep(1);

    }

pthread_exit(0);

}


int main( void ) {

    pthread_t  thread1, thread2;

    pthread_attr_t attr;

    

    pthread_attr_init( &attr );

    

    pthread_create( &thread1, &attr, (void*(*)(void*))Thread, &arg1 );

    pthread_create( &thread2, &attr, (void*(*)(void*))Thread, &arg2 );

    

    pthread_exit(0);


}




# cc mutex_test_a.c -lpthread

# ./a.out 

thread 1: 0th iteration: val = 1

thread 0: 0th iteration: val = 0

thread 1: 1th iteration: val = 1

thread 0: 1th iteration: val = 0

thread 1: 2th iteration: val = 1

thread 0: 2th iteration: val = 0

thread 1: 3th iteration: val = 1

thread 0: 3th iteration: val = 0

thread 1: 4th iteration: val = 1

thread 0: 4th iteration: val = 0

thread 1: 5th iteration: val = 1

thread 0: 5th iteration: val = 0

thread 0: 6th iteration: val = 0

thread 1: 6th iteration: val = 1







//    mutex_cond_a.c       //        Condition variable

 

#include <stdio.h>

#include <pthread.h>


pthread_t  thread;


pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t   cond  = PTHREAD_COND_INITIALIZER;


int count = 0;


void* Thread ( void* arg ) {

    

    pthread_mutex_lock ( &mutex ); 

    

    while ( count < 5 ) {

        printf( "count = %d: wait...\n", count );


/*TODO: wait for condition variable signal  */

        pthread_cond_wait ( &cond, &mutex );

    }

    printf( "count = %d: done...\n", count );

    

    pthread_mutex_unlock ( &mutex );


    pthread_exit(0);

}


void main ( void ) {

    int i;



    pthread_create( &thread, NULL, (void*(*)(void*))Thread, NULL );

    

    for ( i = 0; i < 10; i++ ) {

        sleep(1);

        pthread_mutex_lock  ( &mutex );


        count++;


        /* TODO: signal condition variable 'cond' */ 

if (1) // check condition

pthread_cond_signal( &cond );


        printf( "condition signal %d\n", i );


        pthread_mutex_unlock( &mutex );

    }


    pthread_exit(0);

}




# ./a.out 

count = 0: wait...

condition signal 0

count = 1: wait...

condition signal 1

count = 2: wait...

condition signal 2

count = 3: wait...

condition signal 3

count = 4: wait...

condition signal 4

count = 5: done...

condition signal 5

condition signal 6

condition signal 7

condition signal 8

condition signal 9