미새문지

크래프톤 정글 week05, day40 - 예외적인 제어 흐름 본문

크래프톤 정글/TIL

크래프톤 정글 week05, day40 - 예외적인 제어 흐름

문미새 2024. 2. 21. 01:11
728x90

예외적인 제어 흐름(Exceptional Control Flow, ECF)

  • 시스템들은 내부 프로그램 변수에 의해 표시되지 않으며, 프로그램의 실행과는 반드시 관련되어 있지 않은 시스템 상태 변화에도 반응할 수 있어야 한다.
  • 사용자가 특정 명령어나 요청을 내릴 경우, 시스템은 이에 대해 특정한 방식으로 반응하는데, 정상적인 흐름이 아닌 경우를 말한다.

예외 상황(Exception)

  • 하드웨어와 운영체제에 의해 구현된 예외적인 제어 흐름의 한 형태로 이해할 수 있다. 이는 프로세서 상태의 변화에 대응해 제어 흐름이 급격하게 변경되는 상황을 말한다.
  • 프로세서가 특정 이벤트 발생을 감지하면, 예외 테이블이라는 점프 테이블을 통해 이 특정 종류의 이벤트를 처리하기 위한 운영체제의 서브루틴인 예외 처리 핸들러로 간접적으로 절차 호출을 수행한다.
  • 예외 처리 핸들러가 작업을 완료하면, 예외 상황에 따라 세 가지 동작 중 하나의 동작이 이루어진다.
    • 핸들러는 제어를 현재 명령어로 되돌린다.
    • 핸들러는 제어를 다음 명령어로 전달한다.
    • 핸들러는 중단된 프로그램을 종료한다.

예외 테이블(Exception Table)

  • 프로세서가 예외 상황을 감지했을 때 해당 예외를 어떻게 처리할지 정의해 놓은 테이블
  • 각각의 예외 상황에 대해 어떤 예외 처리 핸들러를 호출할 지 지정해 놓은 것이다.
  • 예외 테이블은 운영 체제에 의해 관리되며, 프로그램이 시작될 때 메모리에 로드된다.

예외 처리 핸들러(Exception Handler)

  • 예외 상황이 발생했을 때 호출되는 특별한 서브루틴이다.
  • 이 핸들러는 예외 상황을 처리하는 로직을 포함하고 있고, 예외가 발생한 원인을 파악하고 적절한 조치를 취하는 역할을 한다.
  • 잘못된 메모리 접근이 발생했다면, 예외 처리 핸들러는 이를 감지하고 프로그램을 안전하게 종료하거나 해당 오류를 기록할 수 있다.

예외 처리

  • 시스템에서는 각각의 예외 상황에 대해 중복되지 않는 양의 정수인 예외 번호를 할당한다.
    • 이 중 일부는 프로세서 설계자에 의해, 나머지는 운영체제 커널의 설계자에 의해 할당된다.
  • 시스템이 부팅될 때, 운영체제는 예외 테이블이라는 점프 테이블을 할당하고 초기화하는데, 이 테이블은 각 예외 번호에 대한 예외 처리 핸들러의 주소를 저장하게 된다.
  • 런타임에 예외 상황이 발생하면, 프로세서는 해당 예외의 번호를 결정하고, 예외 테이블을 참조하여 해당 예외를 처리하는 핸들러로 제어를 이동시킨다.
    • 이 때 프로세서는 핸들러로 제어를 이동시키기 전에 리턴 주소와 필요한 프로세서 상태를 스택에 저장한다. 이 과정에서 제어는 사용자 프로그램에서 커널로 전환되며, 이 때 모든 정보는 커널 스택에 저장된다.
  • 예외 처리 핸들러는 커널 모드에서 동작하며, 이는 핸들러가 모든 시스템 자원에 접근할 수 있다는 것을 의미한다. 이 후, 예외 처리는 핸들러에 의해 소프트웨어 적으로 수행된다.

< 예외의 종류 >

인터럽트(Interrupt)

  • 인터럽트는 프로그램의 일반적인 실행 흐름을 잠시 중단시키고 특정 이벤트를 처리하기 위한 메커니즘이다.
  • 인터럽트 발생 시 프로세서는 실행 중인 작업을 중단하고 인터럽트를 먼저 처리한 후 원래 작업으로 돌아가는데, 이 과정은 인터럽트 핸들러에 의해 인터럽트의 종류에 따라 적절하게 처리를 수행받는다.
  • 인터럽트는 주로 하드웨어 장치나 운영체제로부터 발생하며, 그 종류와 처리 방법은 다양하다.
    • 하드웨어 인터럽트
      • 하드웨어 장치(네트워크 카드, 디스크, 키보드 등)로부터 발생하는 인터럽트
      • 키보드에 키가 눌리면 키보드는 프로세서에 인터럽트를 보내서 이를 알려준다. 그러면 프로세서는 그 인터럽트를 받아 키 입력 처리를 하고 이 후 원래의 작업을 다시 시작한다.
    • 소프트웨어 인터럽트
      • 프로그램이 명시적으로 인터럽트를 발생시키는 경우
      • 주로 프로그램의 오류를 검출하거나 운영 체제의 서비스를 요청하는데 사용된다.
    • 타이머 인터럽트
      • 프로세서의 타이머에 의해 발생하는 인터럽트
      • 멀티태스킹 운영체제에서 프로세스의 시간 할당을 관리하는데 사용된다.

트랩과 시스템 콜

  • 트랩(Trap)
    • 소프트웨어 예외나 프로그램의 오류를 감지하는데 사용되는 메커니즘
    • 트랩은 프로그램에 의해 명시적으로 발생시키는 예외 상황으로, 프로그램의 오류를 검출하거나 디버깅하는데 사용된다.
    • 0으로 나누기, 잘못된 메모리 접근 같은 오류 상황에 트랩이 발생할 수 있으며, 트랩이 발생했을 시 프로그램의 실행은 중단되고, 트랩 핸들러가 호출되어 적절한 처리를 수행한다.
  • 시스템 호출(System Call)
    • 프로그램이 운영체제의 서비스를 요청할 때 사용하는 메커니즘
    • 트랩을 이용해 실행되며, 프로그램은 시스템 호출을 통해 운영체제로 제어를 넘기는데, 운영체제는 요청된 서비스를 수행한 후 제어를 프로그램으로 넘겨준다.
    • 파일을 열거나 네트워크 통신을 수행하는 등의 작업을 위해 시스템 호출이 필요하다.
  • 이 두 가지 메커니즘은 프로그램이 하드웨어 리소스를 안전하게 사용하고, 오류 상황을 적절하게 처리하는데 필수적이다.

오류(Fault)

  • 프로그램이 잘못된 작업을 수행했음을 나타내는 예외 처리. 매우 중요한 예외 상황이며, 이러한 오류는 시스템이 감지하여 적절한 예외 처리 루틴을 호출해 처리한다.
  • 오류는 일반적으로 프로그램의 버그나 잘못된 입력 등으로 인해 발생한다.
    • 예시
      • 잘못된 메모리 접근 : 프로그램이 접근 권한이 없거나 존재하지 않는 메모리 주소를 참조하려고 할 때 발생한다.
      • 0으로 나누기 : 프로그램이 0으로 나누는 연산을 수행하려고 할 때 발생한다.
      • 잘못된 명령어 실행 : 프로그램이 잘못된 명령어 형식을 실행하려고 할 때 발생한다.
  • 이러한 오류가 발생하면, 운영체제는 오류를 감지하고 해당 오류를 처리하기 위한 예외 처리 루틴을 호출한다.

중단

  • 프로그램이 예외 상황이나 오류를 만나 더 이상 안전하게 진행할 수 없을 때 일어나는 상황
  • 다음과 같은 상황에서 발생하며, 이 경우에 프로그램은 중단되고 운영체제는 상황에 맞게 적절히 대응한다.
    • 복구 불가능한 오류 발생
      • 프로그램이 복구할 수 없는 오류를 만나면 중단될 수 있다.
      • 예를 들어 메모리 할당이 실패한 경우, 프로그램은 더 이상 진행이 안될 수도 있다.
    • 시스템 자원 부족
      • 프로그램이 필요한 시스템 자원을 얻지 못하면 중단될 수 있다.
      • 예를 들어 필요한 메모리나 디스크 공간이 부족한 경우가 이에 해당한다.
    • 예외 처리 루틴 실패
      • 예외 처리 루틴이 예외 상황을 적절히 처리하지 못하면 프로그램은 중단될 수 있다.
  • 프로그램이 중단되면, 운영체제는 프로그램의 실행을 종료하고 해당 프로그램에 할당된 모든 시스템 자원을 회수한다. 그리고 오류에 대한 정보를 로그에 기록하거나 사용자에게 알릴 수 있다.
  • 이런 식으로 처리함으로써 시스템의 안정성을 유지하고, 문제를 해결하는 데 필요한 정보를 제공할 수 있다.

리눅스/x86-64 시스템에서의 예외 상황

  • 하드웨어 예외 상황
    • 하드웨어 장치에 의해 발생하는 예외 상황
    • 예시로 프로그램이 메모리의 잘못된 위치에 접근하려고 하면 세그멘데이션 폴트(Segmentation fault)가 발생한다.
    • 또는 프로그램이 0으로 나누는 연산을 수행하려 하면 디바이드 바이 제로(Devide-by-zero)가 발생한다.
  • 소프트웨어 예외 상황
    • 프로그램이 운영체제의 서비스를 요청할 때 발생하는 예외 상황
    • 예시로 프로그램이 파일을 열거나 네트워크 통신을 수행하려고 할 때 시스템 호출(System Call)이 발생한다.
    • 시스템 호출은 트랩을 통해 처리되며, 운영체제는 요청된 서비스를 수행한 후 제어를 다시 프로그램에 넘긴다.
  • 인터럽트(Interrupt)
    • 하드웨어 장치가 특정 이벤트를 알리기 위해 발생시키는 예외 상황
    • 예시로 키보드의 키가 눌리거나 네트워크 패킷이 도착하면 인터럽트가 발생하는데, 인터럽트 핸들러에 의해 처리되며 핸들러는 이벤트를 처리한 후 원래 프로그램으로 제어를 돌려준다.

세그먼트 오류(Segmentation Fault)

  • 컴퓨터 프로그램이 자신에게 할당되지 않은 메모리를 참조하려고 할 때 발생하는 특정 유형의 오류
  • 프로그램이 허용된 메모리 영역 밖의 메모리를 읽거나 쓰려고 할 때, 운영체제는 이를 방지하고 프로그램에 세그먼트 오류를 알린다.
  • 발생하는 경우
    • NULL 포인터를 참조할 때
    • 이미 해제된 메모리를 참조할 때
    • 배열의 경계를 넘어서 메모리를 접근할 때
    • 실행 권한이 없는 메모리 영역에 쓰거나 읽으려 할 때
  • 세그먼트 오류는 프로그램의 안정성과 보안에 심각한 문제를 일으킬 수 있기 때문에, 주의를 기울여야 한다.

디바이드 바이 제로(Divide by Zero)

  • 프로그래밍에서 발생하는 흔한 오류 중 하나로, 숫자를 0으로 나누려고 할 때 발생한다.
  • 수학적으로 어떤 숫자를 0으로 나누는 것은 정의되지 않았기 때문에 프로그램이 이를 수행하려고 하면 예외를 발생시키거나 오류 메세지를 출력한다.
  • 0으로 나눠지는 상황을 충분히 고려하지 않아 발생하는 경우가 많기 때문에, 항상 나누는 수가 0이 아닌지 확인하면 오류를 피할 수 있다.

학습 시간 : 10 ~ 25시

728x90