ucos2 스터디 - 2

2018. 1. 11. 19:30
오늘분 정리하였습니다.

 

1.

 - 재진입성(reenterant)이란

데이터를 손상하지 않고 병렬로 동작(자기 자신을 다시 부르거나, 다른 곳에서 자기자신을 불러도)할 수 있는 것을 의미한다.

 

 - 재진입 가능 함수란

테스크에서 함수가 동작중에 함수 자신을 다시 호출경우,

혹은 함수가 동작중에 인터럽트나 커널에 의해 다른 테스크가 동작하고, 이 태스크가 같은 함수를 호출하였을경우,

각 함수들은 서로의 과정에 영향을 미치지않는다(독립적이다, 데이터의 손실이 없다)

 

 - 재진입이 가능하기 위한 조건

정적(혹은 전역) 변수를 사용하면 안 된다.
정적(혹은 전역) 변수의 주소를 반환하면 안 된다.
호출자가 호출 시 제공한 매개변수만으로 동작해야 한다.
싱글턴 객체의 잠금에 의존하면 안 된다.
다른 비-재진입 함수를 호출하면 안 된다.

=>즉, 지역변수와 매개변수만으로 구성하고, 공유자원을 사용할 경우에는 세마포어를 사용한다(인터럽트를 비활성화하는 방식도 있긴하다..)

 

참조

http://sjava.net/tag/reentrant/

https://ko.wikipedia.org/wiki/%EC%9E%AC%EC%A7%84%EC%9E%85%EC%84%B1

https://code.i-harness.com/ko/q/2ab5af

http://masondev.tk/12

 

 

2. 라운드 로빈 스케줄링(round-robin scheduling, RR)

 - 2개 이상의 태스크(여기서는 프로세스)가 같은 우선순위를 가지고 있을 때, 커널이 퀀텀(quanyum)간격 동안 태스크를 돌아가면서 실행하는 방식.

 - 보통 시간 단위는 10 ms ~ 100 ms 정도이다. 시간 단위동안 수행한 프로세스는 준비 큐의 끝으로 밀려나게 된다.
 - 커널은 다음과 같은 조건을 만족할 때 순서를 기다리는 다른 태스크를 실행한다.

    주어진 시간(퀀텀)이 끝날때

    현재 태스크가 주어진 시간동안 할 일이 아무것도 없을 때

    현재 태스크가 주어진 시간간격 전에 끝났을 때

=> ucos는 RR을 지원하지 않는다.

 

참조: https://ko.wikipedia.org/wiki/%EB%9D%BC%EC%9A%B4%EB%93%9C_%EB%A1%9C%EB%B9%88_%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81

 

 

3. 태스크 우선순위(task priority)

 - 각 태스크는 우선순위가 배정되어 있으며, 중요한 태스크일 수록 더 높은 우선순위를 배정한다. 커널을 사용할 때는 프로그래머 스스로 적절한 우선순위를 매길 수 있어야 한다.

 - 정적우선순위(static)

    태스크가 실행되고 있을때 태스크의 우선순위를 변경할 수 없는 경우

 - 동적우선순위(dynamic)

    태스크가 실행되고 있을때 태스크의 우선순위를 변경할 수 있는 경우, ex: 뮤텍스

 - 우선순위전도(priority inversions)

    우선 순위 역전 현상이라고도 부른다.

   

 

    이러한 우선순위 전도는 대부분 rtos를 사용할때 발생하며, 태스크의 우선순위를 변경하는 것으로 해결할 수 있다.

     보통 상호배제 세마포어(뮤텍스, mutex)를 사용하여 이 문제를 해결한다.(5. 상호배제 참조)

 

 

4. 태스크 우선순위 배정

 - 태스크의 우선순위를 배정하는 것은 간단한 일이 아님
 - RMS(Rate Monotonic Scheduling)

    태스크의 우선순위 배정 방식중의 하나로서, 태스크의 실행빈도를 기준으로 우선순위를 배정.
    실행빈도가 가장 높은 태스크가 가장 높은 우선순위를 갖는다.

    단, 최상위 우선순위를 갖는 태스크가 가장 중요한 태스크가 아닐 수 있다는 문제점이 있다.

    책 49.p 표2.1을 보면 태스크 수가 무한개 있을때 각 태스크의 cpu사용율이 0.693(ln2)이다.

    즉, rms방식으로 시스템을 디자인할 때 각 태스크의 cpu점유율이 0.693이하가 되게 설계해야한다.

 

 

 

5. 상호배제(mutual exclusion)

 - 태스크간의 경쟁(contention)과 공유 자원의 데이터가 손상되는 현상을 막기 위해, 태스크가 공유자원에 대해 독점적인 접근권한을 가질 수 있게 하는 방식

 - 상호배제를 위한 방법

    ① 인터럽트 비활성화(=크리티컬 섹션)

    ② Test-And-Set(TAS) 수행 - 운영체제가 없을 경우 직접적으로 제어하는 방식

    ③ 스케줄링 비활성화 - 시스템의 위험성이 증가하여 거의 사용하지 않는다

    ④ 세마포어 사용  - 공유자원에 맞춰 접근 권한의 갯수를 제한하는 방식

    ⑤ 상호배제 세마포어(뮤텍스, mutex, 바이너리 세마포어이다) 사용 - 우선순위전도 문제를 해결하기 위해 사용하는 방식

     - 우선 순위 상속 프로토콜

        세마포어를 획득한 테스크의 우선순위를 일시적으로 세마포어를 요청하는 다른 상위 태스크의 우선순위로 올려주는 방식

        (커널이 우선순위 상속을 윈한 기능을 제공해야한다. 즉, 커널이 우선순위가 같은 여러개의 태스크를 지원해야한다.) 

     - 우선 순위 상한 프로토콜

        세마포어에 우선순위를 부여하여, 세마포어를 획득한 테스크의 우선순위를 일시적으로  세마포어의 우선순위로 올려주는 방식

 

     =>ucos에서는 47.p에서는 커널이 우선 순위 상속을 위한 기능을 제공한다고 되어 있으며, 179.p에서는 우선 순위 상속을 위한 기능이 제공되지 않으며, 대신 우선 순위 상한 프로토콜을 사용하여 해결한다고 되어있다.(즉, 모순되어 있다. 어떤것이 맞을까?)

     =>친구에게 물어보니 우선 순위 상한 프로토콜을 지원한다고 한다.

 

 

6. 세마포어(semaphore)

 - 세마포어는 코드를 계혹 실행하기 위해서 획득해야하는 '열쇠'이다.

 - 세마포어는 바이너리 세마포어와 카운팅 세마포어가 있다.

 - 세마포어는 2가지 방식(동기화, 공유자원 관리)으로 사용할 수 있다.

 - 동기화 방식은 바이너리 세마포어를, 공유자원 관리에는 바이너리나 카운팅세마포어를 사용한다

 - 동기화 방식 설명: 아래 '8. 동기화'를 참조

 - 공유자원 관리 설명

    세마포어를 공유자원에서 허용가능한 접근갯수 만큼 초기화한다(즉, 세마포어=주어진 임의의 양수)

    테스크가 공유자원을 이용하기위해 세마포어를 획득하는데, 이때 세마포어 값을 감소시킨다(세마포어--;)

    태스크가 공유자원을 다 이용하고 반납할 때 세마포어를 증가시킨다(세마포어++;)

    세마포어가 0이되면 태스크는 os에 의해 지정된 타임아웃시간 만큼 기다리며, 세마포어를 획득하지 못하게되면, 다른 태스크가 세마포어를 반환할 때까지 대기상태로 기다리게 된다.(정확히는 세마포어를 획득하기를 기다리는 wait함수가 있고, 지정된 타임아웃이 지나면 이 함수는 타임아웃에러를 반환하게 된다.)

 

 - 세마포어 캡슐화(=세마포어 은닉)

    태스크가 자원에 접근할 때 실제로 세마포어를 획득해야한다는 사실을 모르게 설계하는 방법

    태스크는 장치에 접근하기 위해 함수를 호출하고, 이 함수내부에는 세마포어를 획득할 수 있는 내용이 코딩되어 있다.

 - 세마포어를 이용한 버퍼관리법

    카운팅 세마포어를 버퍼풀(buffer pool) 관리에 사용한다.

    버퍼의 갯수에 맞게 세마포어 갯수를 설정하고, 태스크는 버퍼할당 함수를 요청하게 된다.

    함수 내부에는 세마포어를 감소시키는 내용이 있고, 태스크는 버퍼 1개를 사용할 수 있게 된다.

    태스크가 더 이상 버퍼가 필요히지 않으면 버퍼를 반환하는 함수를 호출하고, 이 내부에는 세마포어를 증가하는 내용이 있다.

 

 

7. 교착상태(dead lock)

 - 각 태스크가 공유자원을 2개이상 필요로 할때, 각 태스크는 서로 다른 공유자원을 보유하고 있으며 서로가 가지고 있는 공유자원을 소유하기 위해 대기하는상태이다. 즉 서로 맞물리는 상태를 의미한다.

 - 교착상태를 피하기 위한 방법

    프로세스를 진행하기 전에 필요한 모든 자원을 획득하고 태스크를 진행한다(대신 효율이 떨어진다)

    순서대로 자원을 획득한다(공유자원 A, B가 있으면 모든태스크는 A, B순으로 공유자원을 획득해야한다.)

    역순으로 자원을 양도한다

    세마포어에 타임아웃을 지정한다(대부분의 커널은 이를 허용한다.)

 

 

8. 동기화(synchronization)

 - 동기화란: 멀티 스레드 환경의 운영체제에서는 여러개의 작업이 동시에 수행될 수 있으며 여러 작업의 순서와 공유자원을 사용하는데 교착상태를 방지하기위해 시간과 공간에 대해 제어하는 것

 - 프로세스 동기화란:

    ① 둘이상의 프로세스가 상호작용을 하는 과정에서 문제가 없도록 체계적인 연동을 하는 것
    (즉, 태스크에게 공유 자원같은 한정적 자원에 대한 독점적 권한이나 순서를 조정하는 것을 의미한다)

    ② 두 태스크를 동시에(혹은 연속으로) 실행시키기위해 사용하는 방식

    ③ ISR신호가 발생 후 연속으로 태스크를 실행시키기 위해 사용하는 방식(ISR을 더욱 짧게 설계할 수 있다)

 - 세마포어를 공유자원의 획득권으로 사용하는게 아닌, 이벤트의 발생을 알려주는 깃발로서 사용하는 방식

 - 세마포어를 써서 ISR 또는 다른 태스크와 함께 동기화(동시에 실행)할 수 있다.

 - 일방집결: 태스크는 세마포어를 기다리고, ISR이나 다른 태스크에서 세마포어를 반환하면 태스크가 마저 실행한다.

 - 양방집결: 태스크가 2개있고, 각 태스크는 상대방 태스크에서 반환하는 세마포어를 기다리며 대기하게된다.(즉, 2개의 세마포어를 이용해 서로 맞물려 실행하도록 하는 방식.)

 - ISR은 특성상 태스크 임무가 끝날때 까지 대기할 수 없으므로, 양방집결을 사용할 수 없다.

 - 세마포어를 이용한 동기화방식 설명

    task a와 task b가 있다고 가정한다.

    바이너리 세마포어를 0으로 초기화한다.

    task b가 실행되어 세마포어를 기다린다(0으로 초기화되어 있으니)

    task a가 실행하게 되면, 실행 도중 세마포어를 반환한다.(세마포어를 가져가지는 않았지만, +1로 늘려준다)

    이어서 isr이 실행되어 task b를 깨우고, task b가 세마포어를 획득하며 마저 실행하게 된다.

 

 

9. 이벤트 플래그(event flags)

 - 동기화의 확장 개념으로, 태스크를 여러 개의 이벤트 발생에 대해 동기화할 필요가 있을 때 사용한다.

 - 분리동기화(disjunctive synchronization, logical OR): 태스크가 여러개의 이벤트중 임의의 이벤트 하나만 발생할 때 동기화 하는 방식

 - 결합동기화(conjunctive synchronization, logical AND): 태스크가 모든이벤트가 발생했을 경우에 동기화 하는 방식

 

   

       

 - 태스크나 ISR은 8비트 혹은 그 이상의 크기를 가지는 공통이벤트(플래그 변수, 이벤트그룹)를 이용해 여러 개의 태스크를 자신에게 동기화 시킬 수 있다

 - 공동 이벤트를 사용하여 여러 태스크에게 신호를 보낼수 있고, 특정 조건이 만족하게되면 여러개의 태스크로 세마포어를 반환하고, 기다리던 태스크가 다시 실행될 수 있다.

 - 커널은 이벤트 플래그를 지원하기 위해 켜고(set), 끄고(clear), 기다리는(wait) 서비스를 제공한다

 

 

10. 메세지 메일박스(message mailbox)

 - 한개의 메세지만 저장이 가능하다. 즉, 메세지 1개를 받아 공간이 다 차게되면 더 이상 메세지를 보낼 수 없다.

 

 

11. 메세지 큐(message queues)

 - 여러개의 메세지를 저장할 수 있다.

 

메일박스와 메세지큐 참조: http://recipes.egloos.com/tag/RTOS/page/1

 

※ 임베디드 시스템에 따른 차이

펌웨어의 프로그램, 리눅스의 프로세스, RTOS의 Task는 서로 비슷한 동작을 하는 개념이라고 생각할 수 있다.

그리고 Task란 컴퓨터가 처리하는 작업의 단위이며, 옛날에는 프로세스가 작업의 단위였고, 스레드 기술 개발이후 스레드가 작업의 단위가 되었다.(즉 Task=스레드)

 

리눅스에서 프로세스와 스레드(=Task)는 다르다. 마찬가지로 RTOS의 스레드(=Task)와 리눅스의 스레드는 다르다.

대표적인 차이는 다음과 같다.

리눅스의 프로세스와 RTOS의 Task(=스레드)는 커널을 통해 서로간 통신을 하지만(ex: 메세지큐, 메일박스), 리눅스의 스레드(=Task)는 프로세스 내부에 존재하며(스레드가 모여 프로세스가 된다) stack을 제외한 나머지 섹션을 공유하기 때문에 커널의 도움없이 서로간 통신이 가능한다.

 

 

 

'Study > RTOS' 카테고리의 다른 글

ucos2 스터디 - 1  (0) 2018.01.11

+ Recent posts