비선 점형 OS의 이점은 무엇입니까? 그리고 이러한 혜택의 가격은?


14

Bared Metal MCU의 경우 백그라운드 루프와 타이머 인터럽트 아키텍처를 갖춘 수제 코드와 비교하여 비 선점 형 OS의 이점은 무엇입니까? 이러한 이점 중에서 백그라운드 루프 아키텍처와 함께 수제 코드를 사용하는 대신 프로젝트가 비 선점 OS를 채택하기에 충분히 매력적입니까?
.

질문에 대한 설명 :

모든 사람들이 내 질문에 답해 주셔서 감사합니다. 답이 거의 다 왔다고 생각합니다. 이 설명을 내 질문에 여기에 추가하면 내 고려 사항이 표시되며 질문 범위를 좁히거나 더 정확하게 만들 수 있습니다.

내가하려는 것은 일반적으로 프로젝트에 가장 적합한 RTOS를 선택하는 방법을 이해하는 것입니다.
이를 달성하기 위해서는 모든 응용 분야에 최고의 RTOS가 없기 때문에 기본 개념에 대한 이해와 다양한 종류의 RTOS 및 해당 가격의 가장 매력적인 이점에 대한 이해가 도움이됩니다.
몇 년 전에 OS에 관한 책을 읽었지만 더 이상 책을 가지고 있지 않습니다. 여기에 내 질문을 게시하기 전에 인터넷에서 검색했으며이 정보가 가장 도움이되었다는 것을 발견했습니다. http://www.ustudy.in/node/5456 .
다른 RTOS 웹 사이트의 소개, 선점 예약과 비 선점 예약을 비교하는 기사 등과 같은 유용한 정보가 많이 있습니다.
그러나 비 선점 형 RTOS를 선택할 때와 타이머 인터럽트 및 백그라운드 루프를 사용하여 자신의 코드를 작성하는 것이 더 좋은시기에 언급 된 주제를 찾지 못했습니다.
나는 내 자신의 답변을 가지고 있지만 그에 만족하지 않습니다.
특히 경험이 많은 사람들의 답변이나 견해를 알고 싶습니다.

지금까지 나의 이해
는 OS를 사용하거나 사용하지 않더라도 특정 종류의 스케줄링 코드가 항상 필요하다는 것입니다.

    in the timer interrupt which occurs every 10ms  
    if(it's 10ms)  
    {  
      call function A / execute task A;  
    }  
    if(it's 50ms)  
    {  
      call function B / execute task B;  
    }  

이점 1 :
비선 점형 OS는 스케줄링 코드의 방식 / 프로그래밍 스타일을 지정하여 엔지니어가 이전에 동일한 프로젝트에 없었더라도 동일한 뷰를 공유 할 수 있습니다. 그런 다음 개념 작업에 대한 동일한 견해를 통해 엔지니어는 다양한 작업을 수행하고 테스트하고 가능한 한 독립적으로 프로파일 링 할 수 있습니다.
그러나 우리는 이것으로부터 얼마나 많은 것을 얻을 수 있습니까? 엔지니어가 동일한 프로젝트에서 작업하는 경우 비 선점 형 OS를 사용하지 않고도 동일한 뷰를 공유 할 수 있습니다.
한 엔지니어가 다른 프로젝트 또는 회사 출신 인 경우 이전에 OS를 알고 있으면 이점을 얻을 수 있습니다. 그러나 그가 그렇게하지 않았다면, 새로운 OS 나 새로운 코드를 배우는 데 큰 차이가없는 것 같습니다.

이점 2 :
OS 코드가 제대로 테스트 되었으면 디버깅 시간을 절약 할 수 있습니다. 이것은 정말 좋은 혜택입니다.
그러나 응용 프로그램에 약 5 개의 작업이있는 경우 타이머 인터럽트 및 백그라운드 루프를 사용하여 자신의 코드를 작성하는 것이 실제로 지저분하지 않다고 생각합니다.

여기서 비 선점 OS는 비 선점 스케줄러가있는 상업용 / 무료 / 레거시 OS라고합니다.
:이 질문을 게시 할 때, 나는 주로 같은 특정 운영체제의 생각
- (웹 사이트에 의해 주장 작은 비 선점 RTOS) (1) KISS 커널이
http://www.frontiernet.net/~rhode/kisskern.html
(2) uSmartX (경량 RTOS-웹 사이트에서 주장)
(3) FreeRTOS (선점 적 RTOS이지만 이해하는 것처럼 비 선점 적 RTOS로 구성 할 수도 있음)
(4) uC / OS (FreeRTOS와 유사)
(5 ) 일부 회사의 레거시 OS / 스케줄러 코드 (일반적으로 회사에서 내부적으로 제작 및 유지 관리)
(새 StackOverflow 계정의 제한으로 인해 더 많은 링크를 추가 할 수 없음)

내가 이해하는 것처럼 비 선점 형 OS는 다음 코드의 모음입니다.
(1) 비 선점 전략을 사용하는 스케줄러.
(2) 작업 간 통신, 뮤텍스, 동기화 및 시간 제어를위한 시설.
(3) 메모리 관리.
(4) 기타 유용한 시설 / 파일 시스템, 네트워크 스택, GUI 등과 같은 라이브러리 (FreeRTOS 및 uc에 / OS는 다음을 제공하지만, 나는 확실히 스케줄러가 아닌 선제로 구성되어 그들은 여전히 작동하는지 모르겠어요)
의 일부를 항상 거기에있는 것은 아닙니다. 그러나 스케줄러는 필수입니다.


그것은 간단히 말해서. 멀티 스레드해야하는 워크로드가 있고 오버 헤드를 감당할 수있는 경우 스레딩 OS를 사용하십시오. 그렇지 않으면 대부분의 경우 간단한 시간 또는 작업 기반 "스케줄러"로 충분합니다. 그리고 선제 적 또는 협력적인 멀티 태스킹이 최상의 지 알아 내기 위해 ... 오버 헤드와 멀티 태스킹에 대해 얼마나 많은 제어를 원하는지 생각합니다.
akohlsmith

답변:


13

이것은 다소 주제가 아닌 냄새가 나지만 다시 추적하려고합니다.

선점 형 멀티 태스킹이란 운영 체제 또는 커널이 현재 실행중인 스레드를 일시 중단하고 해당 예약 휴리스틱에 따라 다른 스레드로 전환 할 수 있음을 의미합니다. 대부분의 경우 스레드가 실행 중이면 시스템에 다른 일이 발생한다는 개념이 없으며 코드에서 의미하는 바는 커널이 스레드 중간에 스레드를 일시 중단하도록 결정할 때 신중하게 설계해야한다는 것입니다. 다단계 작동 (PWM 출력 변경, 새 ADC 채널 선택, I2C 주변 장치에서 상태 읽기 등)을 수행하고 다른 스레드가 잠시 동안 실행되도록하여이 두 스레드가 서로 간섭하지 않도록합니다.

임의의 예 : 다중 스레드 임베디드 시스템을 처음 사용하고 I2C ADC, SPI LCD 및 I2C EEPROM이있는 작은 시스템이 있다고 가정 해 봅시다. ADC에서 읽고 샘플을 EEPROM에 쓰는 스레드와 마지막 10 개 샘플을 읽고 평균화하여 SPI LCD에 표시하는 스레드 두 개를 사용하는 것이 좋습니다. 경험이없는 디자인은 다음과 같이 보일 것입니다 (매우 단순화 됨).

char i2c_read(int i2c_address, char databyte)
{
    turn_on_i2c_peripheral();
    wait_for_clock_to_stabilize();

    i2c_generate_start();
    i2c_set_data(i2c_address | I2C_READ);
    i2c_go();
    wait_for_ack();
    i2c_set_data(databyte);
    i2c_go();
    wait_for_ack();
    i2c_generate_start();
    i2c_get_byte();
    i2c_generate_nak();
    i2c_stop();
    turn_off_i2c_peripheral();
}

char i2c_write(int i2c_address, char databyte)
{
    turn_on_i2c_peripheral();
    wait_for_clock_to_stabilize();

    i2c_generate_start();
    i2c_set_data(i2c_address | I2C_WRITE);
    i2c_go();
    wait_for_ack();
    i2c_set_data(databyte);
    i2c_go();
    wait_for_ack();
    i2c_generate_start();
    i2c_get_byte();
    i2c_generate_nak();
    i2c_stop();
    turn_off_i2c_peripheral();
}

adc_thread()
{
    int value, sample_number;

    sample_number = 0;

    while (1) {
        value = i2c_read(ADC_ADDR);
        i2c_write(EE_ADDR, EE_ADDR_REG, sample_number);
        i2c_write(EE_ADDR, EE_DATA_REG, value);

        if (sample_number < 10) {
            ++sample_number;
        } else {
            sample_number = 0;
        }
    };
}

lcd_thread()
{
    int i, avg, sample, hundreds, tens, ones;

    while (1) {
        avg = 0;
        for (i=0; i<10; i++) {
            i2c_write(EE_ADDR, EE_ADDR_REG, i);
            sample = i2c_read(EE_ADDR, EE_DATA_REG);
            avg += sample;
        }

        /* calculate average */
        avg /= 10;

        /* convert to numeric digits for display */
        hundreds = avg / 100;
        tens = (avg % 100) / 10;
        ones = (avg % 10);

        spi_write(CS_LCD, LCD_CLEAR);
        spi_write(CS_LCD, '0' + hundreds);
        spi_write(CS_LCD, '0' + tens);
        spi_write(CS_LCD, '0' + ones);
    }
}

이것은 매우 조잡하고 빠른 예입니다. 이런 식으로 코딩하지 마십시오!

이제 선점 형 멀티 태스킹 OS는 이러한 스레드 중 하나를 코드의 모든 줄 (실제로 모든 어셈블리 명령에서)에서 일시 중단하고 다른 스레드가 실행되도록 시간을 줄 수 있음을 기억하십시오.

생각 해봐 OS adc_thread()가 실제 데이터를 쓰고 쓰기 위해 EE 주소 설정 사이 를 중단하기로 결정한 경우 어떻게 될지 상상해보십시오 .lcd_thread()필요한 데이터를 읽기 위해 I2C 주변 장치로 돌아가고, adc_thread()차례를 다시 실행할 때 EEPROM이 남은 상태와 같지 않습니다. 일이 전혀 잘되지 않을 것입니다. 더 나쁜 것은, 대부분의 시간에도 작동하지만 항상 그렇지는 않을 것입니다. 코드가 필요할 때 코드가 작동하지 않는 이유를 알아 내려고 미치게 될 것입니다!

가장 좋은 예입니다. OS가의 컨텍스트 i2c_write()에서 선점 adc_thread()하고 다시 실행을 시작할 수 있습니다.lcd_thread() . 일이 정말 더러워 질 수 있습니다.

선점 형 멀티 태스킹 환경에서 작동하는 코드를 작성할 때는 잠금 메커니즘 을 사용해야합니다 을 코드가 부적합한 시간에 일시 중단되어 모든 지옥이 풀리지 않도록해야합니다.

반면에 협동 멀티 태스킹은 각 스레드가 실행 시간을 포기할 때를 제어한다는 것을 의미합니다. 코딩은 더 간단하지만 모든 스레드를 실행하는 데 충분한 시간을 확보 할 수 있도록 코드를 신중하게 설계해야합니다. 고안된 또 다른 예 :

char getch()
{
    while (! (*uart_status & DATA_AVAILABLE)) {
        /* do nothing */
    }

    return *uart_data_reg;
}

void putch(char data)
{
    while (! (*uart_status & SHIFT_REG_EMPTY)) {
        /* do nothing */
    }

    *uart_data_reg = data;
}

void echo_thread()
{
    char data;

    while (1) {
        data = getch();
        putch(data);
        yield_cpu();
    }
}

void seconds_counter()
{
    int count = 0;

    while (1) {
        ++count;
        sleep_ms(1000);
        yield_cpu();
    }
}

이 코드는 생각하는 방식으로 작동하지 않거나 작동하는 것처럼 보이지만 에코 스레드의 데이터 속도가 증가하면 작동하지 않습니다. 다시 한 번 살펴 보도록하겠습니다.

echo_thread()바이트가 UART에 나타날 때까지 기다렸다가 가져 와서 쓸 공간이있을 때까지 기다렸다가 씁니다. 그 후에 다른 스레드가 실행될 차례를 제공합니다. seconds_counter()카운트를 증가시키고 1000ms 동안 기다린 다음 다른 스레드가 실행될 기회를 제공합니다. 그 동안 2 바이트가 UART에 들어 오면sleep() 가상 UART에 CPU가 다른 작업을 수행하는 동안 문자를 저장할 FIFO가 없기 때문에이를 보지 못할 수 있습니다.

이 매우 열악한 예제를 구현하는 올바른 방법 yield_cpu()은 바쁜 루프가있는 곳에 두는 것 입니다. 이렇게하면 문제가 해결되지만 다른 문제가 발생할 수 있습니다. 예를 들어 타이밍이 중요하고 예상보다 오래 걸리는 다른 스레드에 CPU를 양도하면 타이밍이 중단 될 수 있습니다. 선점 형 멀티 태스킹 OS는 모든 스레드가 올바르게 예약되도록 스레드를 강제로 일시 중단하므로이 문제가 발생하지 않습니다.

이제 이것이 타이머 및 백그라운드 루프와 어떤 관련이 있습니까? 타이머 및 백그라운드 루프는 위의 협동 멀티 태스킹 예제와 매우 유사합니다.

void timer_isr(void)
{
    ++ticks;
    if ((ticks % 10)) == 0) {
        ten_ms_flag = TRUE;
    }

    if ((ticks % 100) == 0) {
        onehundred_ms_flag = TRUE;
    }

    if ((ticks % 1000) == 0) {
        one_second_flag = TRUE;
    }
}

void main(void)
{
    /* initialization of timer ISR, etc. */

    while (1) {
        if (ten_ms_flag) {
            if (kbhit()) {
                putch(getch());
            }
            ten_ms_flag = FALSE;
        }

        if (onehundred_ms_flag) {
                    get_adc_data();
            onehundred_ms_flag = FALSE;
        }

        if (one_second_flag) {
            ++count;
                    update_lcd();
            one_second_flag = FALSE;
        }
    };
}

이것은 협동 스레딩 예제와 매우 비슷합니다. 이벤트를 설정하는 타이머와 이벤트를 찾고 기본 방식으로 작동하는 기본 루프가 있습니다. ADC와 LCD "스레드"가 서로 간섭하는 것에 대해 걱정할 필요가 없습니다. 하나는 다른 하나를 방해하지 않기 때문입니다. "스레드"가 너무 오래 걸리는 것에 대해 여전히 걱정해야합니다. 예를 들어 get_adc_data()30ms 가 걸리면 어떻게됩니까 ? 캐릭터를 확인하고 반향 할 수있는 세 가지 기회를 놓치게됩니다.

루프 + 타이머 구현은 종종 공동 작업 멀티 태스킹 마이크로 커널보다 구현하기가 훨씬 간단합니다. 코드를 현재 작업에보다 구체적으로 설계 할 수 있기 때문입니다. 각 서브 시스템이 특정 작업을 매우 구체적이고 예측 가능한 방식으로 수행 할 시간을주는 고정 시스템을 설계하는 것만 큼 멀티 태스킹은 아닙니다. 협력 적으로 멀티 태스킹 된 시스템조차도 각 스레드에 대해 일반적인 작업 구조를 가져야하며 다음 스레드 실행은 상당히 복잡한 스케줄링 기능에 의해 결정됩니다.

세 시스템 모두에 대한 잠금 메커니즘은 동일하지만 각 시스템에 필요한 오버 헤드는 상당히 다릅니다.

개인적으로 저는 거의 항상이 마지막 표준 인 루프 + 타이머 구현으로 코딩합니다. 스레딩은 매우 드물게 사용해야하는 것으로 나타났습니다. 쓰기 및 디버그가 더 복잡 할뿐만 아니라 더 많은 오버 헤드가 필요합니다 (선점 형 멀티 태스킹 마이크로 커널은 항상 어리석게 간단한 타이머 및 메인 루프 이벤트 추종자보다 클 것입니다).

스레드 작업을하는 사람이라면 누구나 알게 될 것입니다.

if you have a problem and use threads to solve it, yoeu ndup man with y pemro.bls

:-)


akohlsmith 자세한 예를 들어 답장을 보내 주셔서 감사합니다. 그러나 나는 당신이 왜 당신이 협동 멀티 태스킹보다는 단순한 타이머와 백그라운드 루프 아키텍처를 선택하는지 결론을 내릴 수 없습니다 . 내가 틀리지 마 다른 예약에 대한 유용한 정보를 많이 제공하는 회신에 감사드립니다. 나는 요점을 모른다.
hailang

좀 더 작업 해 주시겠습니까?
hailang

고마워요, akohlsmith. 나는 당신이 끝에 문장을 좋아합니다. 그것을 인식하는 데 잠시 시간이 걸렸습니다.) 대답의 시점으로 돌아 가면 거의 항상 루프 + 타이머 구현으로 코딩합니다. 그런 다음이 구현을 포기하고 비 선점 형 OS로 전환 한 경우 어떻게 했습니까?
hailang

다른 사람의 OS를 실행할 때 협동 및 선점 형 멀티 태스킹 시스템을 모두 사용했습니다. Linux, ThreadX, ucOS-ii 또는 QNX입니다. 이러한 상황 중 일부에서도 간단하고 효과적인 타이머 + 이벤트 루프를 사용했습니다 ( poll()즉시 생각 나게합니다).
akohlsmith

나는 임베디드 스레딩 또는 멀티 태스킹 팬이 아니지만 복잡한 시스템의 경우 유일한 제정신 옵션이라는 것을 알고 있습니다. 통조림 마이크로 운영 체제를 사용하면 작업을 신속하게 수행 할 수 있으며 종종 장치 드라이버도 제공합니다.
akohlsmith

6

멀티 태스킹은 많은 마이크로 컨트롤러 프로젝트에서 유용한 추상화가 될 수 있지만 대부분의 경우 진정한 선점 스케줄러는 너무 무겁고 불필요합니다. 저는 100 개가 넘는 마이크로 컨트롤러 프로젝트를 수행했습니다. 협동 작업을 여러 번 사용했지만 관련 수하물로 선제 작업을 전환하는 것은 지금까지 적절하지 않았습니다.

협력 적 과제에 따른 선제 적 과제의 문제점은 다음과 같습니다.

  1. 훨씬 더 무겁습니다. 선제적인 작업 스케줄러는 더 복잡하고 더 많은 코드 공간을 사용하며 더 많은주기를 사용합니다. 또한 하나 이상의 인터럽트가 필요합니다. 그것은 종종 응용 프로그램에 허용 할 수없는 부담입니다.

  2. 뮤텍스는 동시에 액세스 할 수있는 구조 주위에 필요합니다. 협력 시스템에서는 원 자성 작업이어야하는 중간에 TASK_YIELD를 호출하지 않습니다. 이것은 대기열, 공유 된 전역 상태에 영향을 미치며 많은 곳으로 축소됩니다.

일반적으로 CPU가이를 지원할 수있을 때 작업을 특정 작업에 전념하는 것이 합리적이며 작업이 충분한 히스토리 종속 조작으로 충분히 복잡하여 몇 개의 개별 이벤트로 나누는 것이 번거로울 수 있습니다. 이것은 일반적으로 통신 입력 스트림을 처리 할 때 발생합니다. 이러한 것은 일반적으로 이전의 일부 입력에 따라 크게 구동됩니다. 예를 들어, opcode 바이트가 있고 각 opcode마다 고유 한 데이터 바이트가있을 수 있습니다. 그런 다음 다른 바이트를 보내려는 느낌이들 때 이러한 바이트 문제가 발생합니다. 입력 스트림을 처리하는 별도의 작업을 사용하면 마치 나가고 다음 바이트를 가져 오는 것처럼 작업 코드에 표시되도록 할 수 있습니다.

전반적으로 작업은 상태 컨텍스트가 많을 때 유용합니다. 작업은 기본적으로 PC가 상태 변수 인 상태 머신입니다.

마이크로가해야 할 많은 일은 일련의 사건에 반응하는 것으로 표현 될 수 있습니다. 결과적으로 일반적으로 기본 이벤트 루프가 있습니다. 그러면 가능한 각 이벤트가 순서대로 확인 된 다음 맨 위로 이동하여 다시 수행됩니다. 이벤트를 처리하는 데 몇 사이클 이상이 걸리면 일반적으로 이벤트를 처리 한 후 이벤트 루프의 시작으로 돌아갑니다. 이는 사실상 이벤트가 목록에서 확인 된 위치에 따라 우선 순위가 암시됨을 의미합니다. 많은 간단한 시스템에서는 이것으로 충분합니다.

때로는 좀 더 복잡한 작업이 발생하기도합니다. 이것들은 종종 몇 가지 별도의해야 할 일로 나눌 수 있습니다. 이 경우 내부 플래그를 이벤트로 사용할 수 있습니다. 저급 PIC에서 이런 종류의 작업을 여러 번 수행했습니다.

위와 같은 기본 이벤트 구조가 있지만 UART를 통해 명령 스트림에 응답해야하는 경우 수신 된 UART 스트림을 처리하는 별도의 작업을 갖는 것이 유용합니다. 일부 마이크로 컨트롤러는 자체 호출 스택을 읽거나 쓸 수없는 PIC 16과 같이 멀티 태스킹을위한 하드웨어 리소스가 제한되어 있습니다. 이러한 경우 UART 명령 프로세서에 의사 작업이라고하는 것을 사용합니다. 기본 이벤트 루프는 여전히 다른 모든 것을 처리하지만 처리해야하는 이벤트 중 하나는 UART에서 새 바이트를 수신 한 것입니다. 이 경우이 의사 작업을 실행하는 루틴으로 이동합니다. UART 명령 모듈에는 작업 코드가 포함되어 있으며 작업의 실행 주소와 몇 개의 레지스터 값이 해당 모듈의 RAM에 저장됩니다. 이벤트 루프에서 점프 한 코드는 현재 레지스터를 저장하고 저장된 작업 레지스터를로드합니다. 작업 재시작 주소로 이동합니다. 태스크 코드는 역순으로 YIELD 매크로를 호출 한 후 결국 메인 이벤트 루프의 시작으로 되돌아갑니다. 어떤 경우에는 메인 이벤트 루프가 패스 당 의사 태스크를 한 번 실행하며 일반적으로 맨 아래에서 우선 순위가 낮은 이벤트가됩니다.

PIC 18 이상에서는 호출 스택을 펌웨어로 읽고 쓸 수 있기 때문에 진정한 공동 작업 시스템을 사용합니다. 이러한 시스템에서 재시작 주소, 몇 가지 다른 상태 및 데이터 스택 포인터는 각 작업의 메모리 버퍼에 보관됩니다. 다른 모든 작업을 한 번만 실행하려면 TASK_YIELD를 호출합니다. 그러면 현재 작업 상태가 저장되고 사용 가능한 다음 작업 목록이 표시되며 상태를로드 한 다음 실행됩니다.

이 아키텍처에서 메인 이벤트 루프는 루프의 맨 위에 TASK_YIELD를 호출하는 또 다른 작업입니다.

PIC에 대한 모든 멀티 태스킹 코드는 무료로 제공됩니다. 이를 확인하려면 http://www.embedinc.com/pic/dload.htm에 PIC Development Tools 릴리스를 설치 하십시오 . 8 비트 PIC의 경우 SOURCE> PIC 디렉토리에서 16 비트 PIC의 경우 SOURCE> DSPIC 디렉토리에서 이름이 "task"인 파일을 찾으십시오.


뮤텍스는 협력적인 멀티 태스킹 시스템에서 여전히 필요할 수 있지만 드문 경우입니다. 일반적인 예는 중요한 섹션에 액세스해야하는 ISR입니다. 이것은 더 나은 디자인이나 중요한 데이터에 적합한 데이터 컨테이너를 선택함으로써 거의 항상 피할 수 있습니다.
akohlsmith

@akoh : 예, SPI 버스 액세스와 같은 공유 리소스를 처리하기 위해 뮤텍스를 몇 차례 사용했습니다. 내 요점은 뮤텍스가 선점 시스템에있는 한 본질적으로 필요하지 않다는 것입니다. 나는 그들이 결코 협동 시스템에서 필요하지 않거나 결코 사용되지 않는다고 말하지 않았습니다. 또한, 협력 시스템의 뮤텍스는 단일 비트를 검사하는 TASK_YIELD 루프에서 회전하는 것처럼 간단 할 수 있습니다. 선제 적 시스템에서는 일반적으로 커널에 내장되어야합니다.
Olin Lathrop

@OlinLathrop : 뮤텍스와 관련하여 비 선점 형 시스템의 가장 큰 장점은 인터럽트와 직접 상호 작용 할 때 (본질적으로 선점 적) 또는 보호 된 자원을 보유해야 할 때만 필요하다는 것입니다 "수율"호출 사이에 소비하고자하는 시간을 초과하거나 "수상"수율 (예 : "데이터를 파일에 기록")과 같은 호출 주위에 보호 자원을 보유하려고합니다. "데이터 쓰기"호출 내에서 수익을 얻는 것이 문제가되는 경우가 있습니다.
supercat

... 즉시 쓸 수있는 데이터의 양을 확인하는 방법 및 일부 수량을 확보 할 수있는 방법 (수율이 높을 수 있음) (더러운 플래시 블록의 교정을 촉진하고 적절한 숫자가 회수 될 때까지 대기) .
supercat

안녕 Olin, 나는 당신의 대답이 너무 좋아. 그 정보는 내 질문을 훨씬 능가합니다. 실용적인 경험이 많이 포함되어 있습니다.
hailang

1

편집 : (아래에 이전 게시물을 남기겠습니다. 어쩌면 누군가에게 도움이 될 것입니다.)

모든 종류의 멀티 태스킹 OS 및 인터럽트 서비스 루틴은 경쟁하는 시스템 아키텍처가 아니어야합니다. 그것들은 시스템의 다른 레벨에서 다른 작업을위한 것입니다. 인터럽트는 실제로 장치를 다시 시작하거나 인터럽트가없는 장치를 폴링하거나 소프트웨어의 시간을 유지하는 등의 즉각적인 작업을 처리하기 위해 간단한 코드 시퀀스를 위해 의도 된 것입니다. 일반적으로 백그라운드는 더 이상 시간이 중요하지 않은 추가 처리를 수행한다고 가정합니다. 즉각적인 요구가 충족되었습니다. 타이머를 다시 시작하고 LED를 토글하거나 다른 장치를 펄싱하는 것만으로도 ISR은 일반적으로 전경에서 모든 것을 안전하게 수행 할 수 있습니다. 그렇지 않으면 무언가를 수행해야한다는 것을 백그라운드로 알리고 (플래그를 설정하거나 메시지를 큐에 대기) 프로세서를 해제해야합니다.

백그라운드 루프가 유휴 루프 인 매우 간단한 프로그램 구조를 보았습니다 for(;;){ ; }. 모든 작업은 타이머 ISR에서 수행되었습니다. 이것은 프로그램이 타이머 기간보다 짧은 시간 안에 완료되도록 일정한 작동을 반복해야 할 때 작동합니다. 특정 종류의 신호 처리가 떠 오릅니다.

개인적으로, 나는 나가기를 정리하는 ISR을 작성하고, 타이머 시간의 일부만으로 수행 할 수있는 것처럼 곱하고 간단하게 추가하더라도 배경이 필요한 다른 것을 대신하게합니다. 왜? 언젠가는 프로그램에 또 다른 "간단한"기능을 추가 할 수있는 밝은 아이디어를 얻게 될 것입니다. "아마, 짧은 ISR이 필요합니다." 일관되지 않은 일이 발생합니다. 그것들은 디버깅하기가 그리 재미 있지 않습니다.


(이전에 두 종류의 멀티 태스킹 비교 게시)

작업 전환 : 선점 형 MT는 스레드에 CPU가 부족하지 않도록하고 우선 순위가 높은 스레드가 준비 되 자마자 실행되도록하는 등 작업 전환을 처리합니다. 협동 MT는 프로그래머가 스레드가 한 번에 너무 오랫동안 프로세서를 유지하지 않도록해야합니다. 또한 너무 긴 시간을 결정해야합니다. 즉, 코드를 수정할 때마다 코드 세그먼트가 해당 시간-양자를 초과하는지 여부를 알아야합니다.

비 원자 작업 보호 : PMT를 사용하면 나눠서는 안되는 작업 중에 스레드 스왑이 발생하지 않도록해야합니다. 예를 들어 특정 순서로 또는 최대 시간 내에 처리해야하는 특정 장치 레지스터 쌍 읽기 / 쓰기 CMT를 사용하면 매우 쉽습니다. 그러한 작업 중에 프로세서를 양보하지 마십시오.

디버깅 : 스레드 전환 발생시기 / 위치를 계획하므로 일반적으로 CMT를 사용하면 더 쉽습니다. 스레드와 PMT를 통한 스레드로부터 안전하지 않은 작업과 관련된 버그 간의 경쟁 조건은 스레드 변경이 확률적이고 반복 할 수 없으므로 디버깅하기가 특히 어렵습니다.

코드 이해 : PMT 용으로 작성된 스레드는 마치 독립형처럼 작성됩니다. CMT 용으로 작성된 스레드는 세그먼트로 작성되며 선택한 프로그램 구조에 따라 독자가 따라 가기가 더 어려울 수 있습니다.

스레드 안전하지 않은 라이브러리 코드 사용 : PMT 스레드 안전 하에서 호출하는 각 라이브러리 함수를 확인해야합니다. printf () 및 scanf () 및 해당 변형은 거의 항상 스레드 안전하지 않습니다. CMT를 사용하면 프로세서를 구체적으로 생산할 때를 제외하고 스레드 변경이 발생하지 않습니다.

기계 장치를 제어하고 외부 이벤트를 추적하는 유한 상태 기계 구동 시스템은 종종 CMT에 적합한 대상입니다. 각 이벤트마다 모터를 시작 또는 중지하고 플래그를 설정하고 다음 상태를 선택하는 것이별로 없기 때문입니다. 따라서 상태 변경 기능은 본질적으로 간단합니다.

하이브리드 접근 방식은 하나의 스레드로 실행되는 상태 머신 (따라서 대부분의 하드웨어)을 관리하는 CMT 및 상태에 의해 시작된 더 이상 실행되는 계산을 수행하는 하나 이상의 스레드를 관리하는 CMT 변화.


답장을 보내 주셔서 감사합니다. JRobert. 그러나 그것은 내 질문에 맞지 않습니다. 선점 OS와 비 선점 OS를 비교하지만 비 선점 OS와 비 OS를 비교하지는 않습니다.
hailang

그렇습니다. 죄송합니다. 내 편집은 귀하의 질문을 더 잘 해결해야합니다.
JRobert
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.