'세마포어'에 해당되는 글 2건

  1. 2012.01.07 세마포어를 이용한 Deadlock 탈출과 Synchronization
  2. 2012.01.07 상호배제 (Mutual Exclusion) (2)

세마세마 소리만 듣다보니 머리가 아푸시지요? ㅋㅋ

(리니지 본던 3층에 카르파 3인방중에 세마가 있지 않았나? ㅋㅋㅋ 세마의 모자 ㅋㅋㅋ)

세마포어를 이용하는 용도 여러개중에

카운팅 세마포어나 세마포어 은닉 이런 부분은 일단 생략하고 넘어가도록 할게요 ㅋㅋ

대신에 Deadlock 현상의 탈출과 세마포어를 이용한 랑데뷰 (동기화) 에 대해 소개하려 합니다.

(1) Deadlock (교착상태)

Deadly embrace 라고도 불리우는 교착상태는 두 태스크가 각자 다른 태스크에서 쓰고있는 자원을 무한정 기다리는 상태를 말합니다.

재미난 상황인데요 ㅋㅋ 예들 들어보지요 ㅋㅋ

테스크 1, 2번이 있습니다. 얘네들은 각각 리소스 1,2 두개가 모두 있어야 돌수가 있어요 ㅋ

테스크 1번은 리소스 1을 소유했습니다 ㅋㅋ
이때 테스크 2번은 리소스 2를 소유 했다고 생각해 보세요 ㅋ

그러면? 테스크 1번은 리소스 2번을 필요로 하고 이때 테스크 2번은 리소를 1번을 필요로 하겟네요? ㅋㅋ

아 이렇게 난감할때가 ㅋㅋ 어떻게 일이 진행 될 기미를 보이질 않습니다 ㅋ

테스크 1과 테스크 2 모두 더이상 진행이 불가해 지는것이지요

이런 상태를 Deadlock 이라고 부릅니다.

해결 방안은 아래와 같아요

(1) 프로세스를 진행하기 전에 필요한 모든 자원의 세마포어를 획득하도록 한다.
(2) 순서대로 자원을 획득하고 역순으로 자원을 양도한다.

대부분의 커널은 세마포어의 타임아웃을 지원합니다 ㅋ 일정 시간이 지났음에도 불구하고 필요한 세마가 모두 획득이 되질 않는다면 가지고 있는 세마를 모두 놓아 놓고 다시 경쟁을 붙이는 것이지요~

이런 식으로 해결 할수 있답니다~

(2) Synchronization (동기화)

세마포어를 플레그 처럼 사용하는 것이지요 ~ ㅋㅋ ISR 와 태슼, 혹은 태스크와 태스크를 동기화 할 수 있습니다 ㅋ

바로 Psudo Code 를 보여드리도록 하지요 ~

Task1()
{
task 2에게 신호를 보낸다
task 2로부터 신호를 기다린다
작업을 계속한다.
}

Task2()
{
task 1에게 신호를 보낸다
task 1 로 부터 신호를 기다린다.
작업을 계속한다.
}


이렇게 하면 Task 1과 Task 2 를 동기화 할 수 있지요? ㅋㅋ

그렇다고 진짜 동시에 도는 것은 절대로 아닙니다 ㅋㅋ

뇌를 장착할수 있는 곳은 1군데 밖에 없다고 하였지요? ㅋㅋ

라운드 로빈 도는것처럼 요 테스크 한번 조테스크 한번 사이좋게 빠르게 돌면 크게 보면 동기화해서
도는것처럼 보이자나요 ㅋㅋㅋ

정말로 페러럴 프로세싱을 원한다면 FPGA 쪽으로 가셔야지용 ㅋㅋㅋ

그럼 제가 직접 구현한 동기화 코드를 보실깝숑??

__task void task1(void)
{
 
 while(1)
 {
 
 os_sem_send(tsema1);
 os_sem_wait(tsema2,0x0F00);
 
 test_sem1++;
 }
}

__task void task2(void)
{
 
 while(1)
 {
 os_sem_send(tsema2);
 os_sem_wait(tsema1,0x0F00);
 test_sem2++;
 
 }
}

__task void Init(void)
{
 os_sem_init(tsema1,0);
 os_sem_init(tsema2,0);

 T_task1 = os_tsk_create(task1,10);
 T_task2 = os_tsk_create(task2,10);

 os_tsk_delete_self();
}

자 얼추 코드는 이렇습니다

위에서 설명한 것과 똑같이 짜놨지요??

예상대로라면 test_sem1 과 test_sem2 라는 변수가 사이좋게 1씩 차이나면서 올라가야합니다 ㅋㅋ

그럼 어디 그런지 함 보시죵

어때요 ㅋㅋ 싱크가 맞지용? ㅋㅋㅋ

이걸 다른말로 랑데뷰 라고도 부른답니다 ~ ㅋㅋ

한번씩들 해보셔요 ㅋㅋ

Posted by J.Bear

여러가지 태스크들이 서로 정보를 주고 받을수 있는 방법 중에 가장 쉬운 방법은 무엇일까요??

바로 공유 데이터를 이용하는 것입니다. 더욱 직관적으로 표현하자면 "전역변수" 를 사용하는 것이지요 ㅋㅋ

그럼 공유자원이란 무엇인가???

말그대로 여러가지 태스크에서 공동으로 사용, 접근할수 있는 모든 것입니다~

전역변수가 될수도 있고, Public 형의 함수나 클래스가 될수도 있고, 프린터와 같은 I/O 가 될수도 있죠.

여러 테스크들이 데이터와 자원을 공유하는 것은 좋은 일이지만, 그 과정에서 테스크 사이의 경쟁이나 다른 이유에 의해서 데이터가 손실되는 상황을 막아야 합니다.

모든 테스크가 접근하여 공유자원을 사용할수 있게 하지만, 한번에 하나씩만 사용할수 있도록 하겠다! 라는 개념이 바로 상호배제 (Mutual Exclusion) 입니다.

상호 배제를 구현하는 방법은 크게 4가지가 있습니다.

(1) 인터럽스 활성화 / 비 활성화 (Interrupt Enable / Disable)
(2) Test - And - Set (TAS) 수행
(3) 스케쥴러 비활성화 (Scheduler Lock / Unlock)
(4) 세마포어의 이용 (Semaphore) (혹은 뮤텍스 (Mutex) 의 이용)

아나 많기도 엄청나게 많네 ㅋㅋ 이런 거지같은게 ㅋㅋㅋ

한번에 쓸려면 엄청난 양이겠죠? ㅋㅋㅋ

(4) 번의 세마포어는 조금 더 쓰임새가 다양한 기능이므로 뒤에서 따로 자세히 다루도록 하고, 이번에는 세마포어가 무엇인지, 어떻게 상호배제에 이용하는지 정도만 간단하게 알아보겠습니다.

흠.. 벌써부터 양이 많아질것 같이 쫄리넹. 하지만 나도 졸업고사를 보긴해야하니 한번 정리한다 생각하고 기술해볼까나 ㅋㅋ

(1) 인터럽트 활성화 / 비활성화 (Interrupt Enable / Disable)

: 왠지 익숙하시죠?? 아니라구요???  머야 ! 장난하는거야? ㅋㅋㅋ 앞에 강의에서 살짝 언급드렸는데요 ㅋ
크.리.티.컬.섹.션 할때요! ㅋㅋㅋ USART TX Function 까지 예를 들어가면서  ㅠㅠㅠㅠㅠ

이럴때 배신감 느낀다 ㅋㅋㅋ 나 중,고등학교때 선생님들이 이런 기분이였을꺼야 ㅋㅋㅋ

이 방법은 상호 배제를 실행 할 수 있는 가장 손쉬운 방법중에 하나입니다.

왜일까요??? 스케쥴러를 이해하신 분들은 이해가 가실 것입니다. 동작하고 있는 테스크에서 CPU 점유율을 테스크자신의 의지가 아닌 외부의 힘에 의해 가져오려면 필수적으로 필요한것이 ISR (Interrupt Suervice Routine) 이라고 했습니다. 그것이 틱 인터럽트이던, 외부 인터럽트이던 무조건 인터럽트로 뛰어야만이 CPU 점유율이 스케쥴러로 넘어가고, 커널의 종류가 어떤 것인가에 따라 어느 Task 로 CPU 점유율을 넘겨줄 것인지가 결정되는 것이지요.

그렇다면~

공유자원을 Access 하고 있는 동안에 인터럽트를 꺼버리고, 이용이 다 끝난 이후에 인터럽트를 다시 켠다면요???

ㅋㅋㅋ 이제 감이 오시지요?? 다른 Task 나 ISR 에 의해서 공유자원이 동시에 경쟁되는 일을 원초적으로 있을수가 없습니다.

꼭 RTOS 기반이 아니라, 전경/배경 시스템에서도 마찬가지입니다. 배경 프로세스에서 공유자원을 접근하려 할때 의도치 않은 인터럽트에 의해 데이터가 변경된다면??? 배경 시스템 입장에서는 오염된 데이터를 얻게 되는 것이지요~

간단한 Psudo Code 는 아래와 같습니다.

 인터럽트 비활성화
 리소스 액세스 (공유자원 읽기 / 쓰기);
 인터럽트 활성화


여기서 주의해야할 점이 하나 있습니다.

인터럽트의 비활성화 기간이 너무 길면 시스템의 응답성에 영향을 줄수 있으므로 주의해야 합니다.  즉, 변수의 복사나 시간이 많이 걸리는 작업이라면 이 방법을 사용하는것을 다시 한번 생각해 보셔야 합나다.

좋은 커널은 얼마의 시간동안 인터럽트 비활성화를 할 수 있는지에 대해 정보를 제공합니다. 프로그램 할때 꼭 신경쓰시기 바랍니다.

(2) Test - And -Set (TAS)

약간 생소하지요??

커널을 사용할때는 거의 사용하지 않습니다~ 왜냐구요?? 세마포어가 있으니까요 ㅋㅋ

바꿔서 생각해보면, 전경 배경 시스템에서 전역변수를 이용해서 세마포어 같은것을 하나 만들어놓고 사용하는 것이랍니다. ㅋㅋ

그냥 프로그램 하는 자기 자신과의 약속이지요~

"함수가 자원을 액세스 하기 전에는 꼭 정해놓은 전역변수를 점검하고 그 변수의 값이 0일때만 그 자원에 엑세스 하겠다. 1일때는 절대로 접근을 시도조차 하지 않겠다"

ㅋㅋㅋㅋ

자기들만의 리그를 뛰고 있는거지요  머 ㅋㅋㅋ 프로그램하다보면 저런 비슷한거 많이 찾아볼수 있습니다 ㅋㅋㅋ

TAS 를 사용할때는 TAS 오퍼레이션이 인터럽트에 의해 선점이 되면 안되겠지요?? 그말인 즉슨, 꼭 수행하기 전에 인터럽트를 비활성화 해야한다는 소리입니당. ㅋㅋㅋ

여기서도 간단히 Psudo Code 를 써보면요

if ( 액세스 변수가 0 이면 )
{
변수를 1로 세팅한다.
인터럽트를 활성화 한다.
자원을 액세스 해서 사용한다.
인터럽트를 비활성화 환다.
액세스 변수를 0으로 세팅한다.
인터럽트를 활성화 시켜놓는다.
}
else
{
인터럽트 활성화 시킨다.    // 즉 자원에 액세스를 할수없다. 나중에 다시 시도한다.
}


정도가 되겠군요 ㅋㅋ

(3) 스케쥴러 비활성화

뭐 다들 비슷한 개념입니다.

비 선점형 커널에는 크게 관계없는 방법이겠네요 ~

이 방법을 사용하기 위해서는 전제 조건이 하나 필요합니다.

" ISR 과는 공유자원을 공유하지 않는다."

이 전제조건을 만족해야만 스케쥴러를 비활성화 시키는 것으로 우리가 의도하는 바를 이룰수 있죠.

개념은 이렇습니다.

"ISR 로 뛸 테면 뛰어라. 어차피 ISR 과는 공유자원을 공유하지 않으니까 ISR 이 공유자원을 훼손할 일은 없고, ISR 이 끝나고 나서 일하고 있던 테스크로 무조건 다시 CPU 점유권을 넘겨줘 버릴테니까 !!!! "

ㅋㅋㅋ

어디서 많이 보던 개념 아닌가요???

그렇습니다!!! 비선점형 커널이 하는 짓거리 지요?? ㅋㅋ

이 방법도 이론적으로 잘 동작하기는 합니다. ㅋㅋ

하지만 사용하고 있는 커널이 선점형 커널이라면, 구지 다른 좋은 방법이 많은데요 Mutual Exclusion 을 구현하기 위해 커널 고유의 특성을 변경할 필요는 없지 않을까요?/ ㅋㅋㅋ

그래서 이 방법은 부득이한 상황이 아니면 사용하지 않는것이 좋습니다 ㅋㅋ

사실 Scheduler Lock / Unlock OS 관련 함수를 저는 본적이 없군용 ㅋㅋㅋㅋ

여튼 여기도 Psudo Code

스케쥴러 락
공유자원 엑세스
스케쥴러 언락


ㅋㅋㅋㅋㅋ 단순하군 ㅋㅋㅋㅋ (이렇게 쓰면 프로그래밍 해주는 컴파일러를 만들면 대박일텐데요 ㅋㅋ 그죠?? ㅋ )

(4) 세마포어의 이용

 아  ㅋㅋㅋ 쓰다보니 거의 다 왔군요 ㅋㅋ 세마포어 ~

1960년 중반에 Edgser Diikstra 에 의해 발명 되었답니다 ㅋㅋㅋ (이름이 왜 저따위냐 ㅋㅋ)



대부분의 멀티태스킹 커널이 제공하는 프로토콜 메커니즘 이구요 꼭 상호 배제를 위해서만 사용되는 것은 아닙니다.

ㄱ) 공유자원 간의 액세스 제어 (Mutual Exclusion)
ㄴ) 이벤트의 발생을 알려줌 (Signaling)
ㄷ) 두 태스크 간의 동작을 동귀화 시킴 (Synchronization / Rendezvous)

정도로 볼 수 있겠군요 ㅋㅋ

일단 여기서는 ㄱ) 의 상황에 대해서만 간단하게 언급해볼깝숑 ㅋㅋㅋ

세마포어는 어떤 자원에 접근하기 위한 '열쇠' 와도 같은 개념입니다.

이 열쇠를 1개만 만들어 놓으면 "Binary Semaphor" 혹은 "Mutex" 라고 부르구요

열쇠는 좀 복사를 많이 해 놔서 여러개 만들어 놓으면 "Counting Semaphore" 라고 부릅니다.

우리는 ㄱ) 의 상황을 논의해야하니까 Binary Semaphore 를 사용해야 겠네요?? ㅋㅋ

세마포어는 생성되고 나면 Send , Waiting 의 두가지 작업을 할 수 있습니다.
혹은 Post, Pend 라고 부르기도 하지요 ~ 뭐 같은 개념이니까요 ㅋㅋ

Send 를 하면 세마포어의 숫자는 + 하게 됩니다. Wait (Pend) 해서 세마포어를 받게 되면 숫자는 - 하게 되지요 ㅋㅋ

이 숫자가 코드를 돌릴수 있는 횟수와 정확하게 일치 합니다.

즉, 키를 하나만 만들어 놓는다면??  한번에 한놈씩만 공유자원에 접근할수 있겠지요???

시작이 1개였는데 ㅋㅋㅋ 5놈이 기다리고 있던 10놈이 기다리고 있던 제일 먼저 어떤놈이 키를 가져가 버리면
세마포어 숫자가 0으로 바껴서 나머지놈들은 끝없이 기다려야만 하는 상황이거든요 ㅋㅋ

사용하던놈이 자원을 다 쓰고 Send (Post) 해야 갯수가 1로 늘어나고 다음놈이 가져다 쓸수 있는 상화ㅘㅇ이 되는 것입니다.

세마포어의 생성은 되어있는 상태가 가정하고 Psudo Code 를 작성해 보지요

세마포어 Wait (Pend)
공유자원 엑세스
세마포어 Send(Post)

간단하지요? ㅋㅋㅋ
일단 이렇게 단순하게 생각하시고 나머지 개념들은 뒤에서 다시 추가하도록 하셔요 ㅋㅋ

한번에 너무 많이 알려면 머리가 아푸니까요 ㅋㅋㅋ (대가리가 뽀개지니까요 라고 자연스럽게 썼다가 포스팅의 질을위해 급 바껐습니다 ㅋㅋㅋ)

그럼 빠이
Posted by J.Bear