• 2023. 9. 13.

    by. 도 현

    반응형
    선점 스케줄링

    레이스 컨디션이 발생하는 두 번째 요인은 리눅스 커널이 선점 스케줄링을 지원하기 때문이다. 현재 대부분의 리눅스 커널은 선점형 스케줄링 환경에서 실행되는데, 이를 가리켜 "우리가 입력한 코드 블록이 실행되는 도중 선점 스케줄링될 수 있다"라고 해석할 수 있다. 선점 스케줄링으로 다양한 종류의 레이스 컨디션이 발생할 수 있는데, 예를 들어 작성한 코드가 rpi_set_synchronize() 함수에서 실행 중이라고 가정한다. A 프로세스가 rpi_set_synchronize() 함수를 실행하는 도중 선점 스케줄링이 된 후 B 프로세스가 다시 rpi_set_synchronize() 함수를 호출하면 중요한 자료구조를 처리하는 코드 구간을 B프로세스가 다시 실행하면서 레이스 컨디션이 발생할 수 있다. 선점 스케줄링이 발생해 다른 프로세스가 rpi_set_synchronize() 함수를 호출하지 않아도 다른 문제를 겪을 수 있다. 만약 rpi_set_synchronize() 함수 내에서 알고리즘 연산이나 정확한 딜레이를 주는 코드를 실행 중이라고 가정할 때, 선점 스케줄링으로 실행하는 코드를 멈추고 다른 프로세스로 스케줄링되면 정해진 딜레이를 주지 못해 오동작을 유발할 수 있다. 

     

    인터럽트 발생

    어떤 CPU에서도 인터럽트는 언제든 발생할 수 있다. 작성한 코드가 실행되는 도중에 인터럽트가 발생하면 실행을 멈추고 인터럽트 핸들러를 호출할 수 있다. 만약 rpi_set_synchronize() 함수를 실행하는 도중 인터럽트가 발생해 다시 rpi_set_synchronize() 함수에 진입하면 레이스 컨디션이 발생할 수 있다.

     

    유저 프로세스에서 스레드 핸들링

    유저 애플리케이션에서 스레드를 생성해 한 개의 파일에 다수의 스레드가 접근할 수 있다. 이 과정에서 다수의 스레드가 같은 커널 코드의 구간을 실행할 수 있으며, 그 결과 동시성 혹은 레이스 컨디션이 발생할 수 있다.

     

    동시성 발생 사례

    CPU0이 mmap_sem() 함수에 접근해 락을 획득하였을때, CPU1에서 같이 mmap_sem() 함수에 접근한다고 보자. "2개의 CPU에서 실행 중인 프로세스가 동시에 같은 코드 블록을 실행한다"가 된다. 

     

    1. 레이스 컨디션 관련 커널 패치

    - 레이스 컨디션의 발생원인

    - 임계 영역 구간

    - 패치 코드와 관련된 소스 코드 분석

     

    CPU0와 CPU1에서 실행하는 함수의 호출 흐름을 알기 쉽게 표현하였을 때 CPU0은 pty_write() 함수에 접근, 그런데 CPU1은 pty_write() 함수를 거의 동시에 실행한다. CPU0와 CPU1의 함수 실행 흐름에서 마지막 부분을 보면 CPU0과 CPU1이 tty_insert_flip_string() 함수와 tty_insert_flip_string_fixed_flag() 함수를 동시에 실행한다는 사실을 알 수 있다. 이를 일반화하면 서로 다른 CPU에서 실행 중인 프로세스가 같은 코드나 함수에 접근한다고 할 수 있다. 위와 같은 레이스 컨디션에서는 커널 패닉으로 시스템을 다운시킨다. 

     

    커널 패닉이란?

    "리눅스 시스템에 심각한 오류가 생겨 시스템이 다운되는 동작"을 의미하며, 간혹 컴퓨터를 오래 쓰다가 블루 스크린을 본 것처럼 라즈베리 파이와 같은 리눅스 컴퓨터에서 검은색 배경에 흰색 문구를 띄우며, 이를 보통 커널 패닉 혹은 커널 크래시라고 부른다.

     

    커널 패닉이 발생했을 시 커널 로그를 보면 로그를 통해 커널 패닉이 "CPU0과 CPU1이 동시에 memcpy() 함수를 실행하여" 레이스 컨디션으로 발생했다는 사실을 알 수 있다.

     

    지정한 배열의 범위를 넘어서서 메모리 공간을 침범하는 상황을 경계 침범(Out-of-bound)라고 부른다. 조금더 구체적으로 보면 지정된 배열의 인덱스 범위를 넘어 메모리 값을 복사하거나 읽는 과정을 의미한다. 가령 배열의 크기를 10으로 잡았는데 12번째 위치로 메모리를 복사하는 경우이다. 경계 침법이 발생하면 메모리를 오염시키므로 커널은 오동작을 하면 대부분의 경우 커널 패닉을 유발한다.

    전 세계 리눅스 커널의 개발자들은 리눅스 커널 메일링 리스트를 통해 커널 버그와 패치에 대해 논의를 한다. 이 메일링 리스트에서 가장 많이 논의하는 주제 중 하나가 커널 동기화 문제로 생기는 레이스 컨디션이다. 그렇다면 레이스 컨디션과 관련된 문제에 대해 많이 논의하는 이유는 레이스 컨디션이 발생하면 리눅스 시스템은 아주 느려지거나 대부분 커널 패닉으로 시스템이 다운되기 때문이다. 리눅스 커널이나 디바이스 드라이버 개발자 입장에서 커널 패닉은 빨리 해결해야 할 문제이다. 그래서 레이스 컨디션으로 생기는 리눅스 커널 크래시와 같은 문제를 해결하기 위해 지금도 수많은 리눅스 커널 개발자들은 디버깅하고 있다.

    반응형