Exceptional Control Flow
제어 흐름 | 처음 전원을 켤때부터 전원을 끄기까지, 프로그램 카운터는 일련의 값들을 순차적으로 가진다. 순차적으로 명령을 실행하는 것을 제어 전달이라고 하며, 이러한 제어 전달의 연속은 프로세서의 제어 흐름이라고 한다(flow of control). |
예외 제어흐름 | 가장 간단한 종류의 제어 흐름은 메모리에서 인접한 위치에 있는 연속된 명령을 수행하는 것이다. 하지만 이런 흐름의 급격한 변화는 점프(jumps), 호출(calls), 반환(return)과 같은 익숙한 제어문으로 인해 발생한다. 그러나 시스템은 내부 프로그램 변수로 포착되지 않는 시스템 상태의 변화에도 반응해야 하는데, 이는 프로그램의 정상적인 실행과 관련이 없을 수 있다. 예를들어 OS가 관리하는 하드웨어 타이머에 의해 진행중이던 프로세스를 잠깐 멈춰야 할 때도 있을것이고, try, catch와 같은 예외 처리 코드가 작동해도 처리해줘야 한다. 이런 급격한 변화를 exceptional control flow(ECF라고 한다.) |
ECF를 이해해야 하는 이유 | 시스템 개념을 이해하는데 도움이 된다. ECF는 운영체제가 입출력, 프로세스, 가상메모리를 구현하기 위해 사용하는 기본 메커니즘이다. 이런 중요한 아이디어들을 본격적으로 이해하기 전에 ECF를 먼저 이해할 필요가 있다. ECF를 이해하면 어떻게 응용 프로그램들이 운영체제와 상호작용 하는지를 이해하는데 도움이 된다. 응용 프로그램은 트랩 또는 시스템콜이라고 알려진 ECF의 한가지 형태를 사용해서 운영체제로부터 서비스를 요청한다. 새로운 프로세스를 만들거나 현재 프로세스를 종료시키는 등의 일은 모두 응용프로그램이 시스템 콜을 호출해서 이루어진다. 새로운 응용 프로그램 작성에 도움이 된다. 동시성을 이해하는데 도움이 된다. ECF는 동시성을 구현하는 기본 메커니즘으로, 프로세스, 쓰레드등이 ECF의 시그널 핸들러로 구성되어 있다. 예외 상황이 어떻게 동작하는지 이해하는데 도움이 된다. |
시스템콜과 핸들러란? | 시스템콜은 사용자가 OS에 요청을 보냈을때 커널이 제어권을 가져가서 컴퓨터에 명령을 내리는것이라고 생각하면 될것같다. 핸들러는 특정 이벤트나 상황이 발생했을 때 그 처리를 담당하는 함수나 코드 블록을 의미한다. 예외가 발생하면 실행되는 소프트웨어 루틴이라고 생각하자 |
Exceptions

예외 | 시스템 에러 발생 시 프로세스에서 커널로 제어권을 넘긴 후, 에러를 처리하고 다시 프로세스로 제어권을 넘겨준다. |
예외의 구성 요소 | 예외가 발생하는 경우는 다양하다. 예를들어 어떤 인스트럭션이 divide by zero를 시도하는 경우도 있지만 현재 인스트럭션과 관련없이 시스템 타이머가 정지하거나, I/O 요청이 완료되는 경우가 해당한다. 어떤 경우든지 프로세서가 이벤트가 발생했다는 것을 감지하면 예외 테이블이라고 하는 점프 테이블을 통해서 이 특정 종류의 이벤트를 처리하기 위해 특별히 설계된 운영체제 서브루틴으로 간접 프로시저 콜을 하게 된다. 그 과정은 위 사진과 같다. |
Exception Handling

예외를 처리하는 방법 | 시스템 부팅시 예외상황의 종류마다 중복되지 않는 양의 정수를 예외번호로 할당하고, 해당 테이블에 해당 핸들러의 주소를 할당한다. 런타임에 프로세서는 이벤트가 발생했을때 예외번호를 결정하고, 이는 예외 테이블의 엔트리 번호가 되어 해당 예외처리 핸들러를 호출한다. |

예외 테이블 번호 | 위 사진은 프로세서가 예외 테이블을 잉요해서 해당 예외 핸들러의 주소를 어떻게 만드는지 보여준다. 예외 번호는 예외 테이블에서 인덱스이며, 이 테이블의 시작 주소는 예외 테이블 베이스 레지스터라는 특별한 CPU 레지스터에 저장되어 있다. |
예외상황과 프로시저콜의 차이 | 프로시저는 프로시저 콜을 사용해서 핸들러로 분기하기 전에 스택에 리턴주소를 푸시한다. 하지만 예외는 예외의 종류에 따라 리턴주소는 현재 인스트럭션(이벤트가 발생했을때 실행하고 있던 인스트럭션 이거나 다음 인스트럭션) 이거나 다음 인스트럭션 (이벤트가 일어나지 않았다면 현재 인스트럭션 다음에 실행되었을 인스트럭션)이 된다. 또한 프로세서는 핸들러가 리턴할 때 중단된 프로그램을 다시 시작하기 위해 필요하게 될 스택 상에 추가적인 프로세서 상태를 푸시한다. 제어가 사용자 프로그램에서 커널로 전환하고 있을 때, 이 모든 아이템들은 사용자 스택 위가 아니라 커널 스택 상에 푸시된다. 예외 핸들러는 커널 모드에서 돌아가는데, 이것은 모든 시스템 자원에 완전히 접근할 수 있는 것을 의미한다. 위 사안에 따라 예외가 발생하면 다음과 같은 동작이 발생한다.
|
Classes of Exceptions

예외의 종류 | 예외 상황은 네가지 종류로 구분할 수 있다. 인터럽트, 트랩, 오류, 중단 |

인터럽트 | 비동기적으로 발생한다. 특정 인스트럭션을 실행해서 발생한 예외가 아닌, 하드웨어단 작업에서 발생한 예외를 처리하는 방식. 입출력 디바이스들이 프로세서 칩의 핀에 시그널을 보내서 인터럽트를 발생시키고, 인터럽트를 발생시킨 디바이스를 식별하는 예외번호를 시스템 버스로 보낸다. 현재 인스트럭션이 실행을 완료한 후, 프로세서는 인터럽트 핀이 high로 올라갔다는 것을 발견하고 시스템 버스에서 예외 번호를 읽고 인터럽트 핸들러를 호출함 핸들러가 리턴할 때 제어를 다음 인스트럭션으로 되돌려줌 |

트랩과 시스템콜 | 트랩은 의도적인 예외 상황으로, 어떤 인스트럭션을 실행한 결과로 발생한다. 인터럽트 핸들러와 마찬가지로 트랩 핸들러는 제어를 다음 인스트럭션으로 리턴한다. 트랩이 중요한 이유는 시스템 콜이라고 알려진 프로그램 - 커널 사이의 프로시저와 유사한 인터페이스를 제공하는 것이다. 사용자 프로그램은 파일을 읽거나(read), 새로운 프로세스를 만들거나(fork), 새 프로그램을 로드하고(execve) 현재 프로세스를 종료하는 등의 서비스를 커널에 요청해야 한다. 이러한 요청을 가능하게 하기 위해 프로세서는 "n" 인스트럭션을 제공하며, 이들은 사용자 프로그램이 서비스 n을 요청하고자 할때 사용할 수 있는 인스트럭션이다. 프로그래머의 관점에서 시스템 콜은 보통의 함수 호출과 동일하다. 그렇지만 실제 구현은 매우 다르다. 함수는 사용자 모드에서 돌아가며, 이때문에 이들이 실행할 수 있는 인스트럭션은 제한적이다. 하지만 시스템콜은 커널 모드에서 돌아가며, 이로 인해 모든 작업이 가능함 |

오류(fault는 error와 다르다) | 오류는 핸들러가 정정할 수 있는 가능성이 있는 에러 조건으로부터 발생한다. 오류가 발생하며 프로세서는 제어를 오류 핸들러로 이동시켜준다. 만일 핸들러가 에러 조건을 정정할 수 있다면, 제어를 오류를 발생시킨 인스트럭션으로 돌려 주어서 거기서부터 재 실행한다. 그렇지 않다면 핸들러는 커널 내부의 abort 루틴으로 리턴해서 오류를 발생시킨 응용프로그램을 종료한다. |

중단 | 중단은 대게 DRAM이나 SRAM이 고장날 때 발생하는 패리티 에러와 하드웨어 같은 복구할 수 없는 치명적인 에러에서 발생한다. 중단 핸들러는 절대로 응용프로그램으로 제어를 리턴하지 않는다. 위 그림과 같이 핸들러는 제어를 응용프로그램을 종료하는 중단 루틴으로 넘겨준다. |
'Krafton_Jungle > Study' 카테고리의 다른 글
Krafton_jungle 5기 6주차 WIL - The Memory Hierarchy (3) | 2024.04.30 |
---|---|
Krafton_jungle 5기 6주차 WIL - Implicit free list (0) | 2024.04.27 |
Krafton_jungle 5기 5주차 WIL - Linker (0) | 2024.04.23 |
Krafton_jungle 5기 5주차 WIL - RB_Tree (0) | 2024.04.22 |
Krafton_jungle 5기 31 ~ 32일차 TIL - RB-Tree, 알고리즘 (2) | 2024.04.19 |
Exceptional Control Flow
제어 흐름 | 처음 전원을 켤때부터 전원을 끄기까지, 프로그램 카운터는 일련의 값들을 순차적으로 가진다. 순차적으로 명령을 실행하는 것을 제어 전달이라고 하며, 이러한 제어 전달의 연속은 프로세서의 제어 흐름이라고 한다(flow of control). |
예외 제어흐름 | 가장 간단한 종류의 제어 흐름은 메모리에서 인접한 위치에 있는 연속된 명령을 수행하는 것이다. 하지만 이런 흐름의 급격한 변화는 점프(jumps), 호출(calls), 반환(return)과 같은 익숙한 제어문으로 인해 발생한다. 그러나 시스템은 내부 프로그램 변수로 포착되지 않는 시스템 상태의 변화에도 반응해야 하는데, 이는 프로그램의 정상적인 실행과 관련이 없을 수 있다. 예를들어 OS가 관리하는 하드웨어 타이머에 의해 진행중이던 프로세스를 잠깐 멈춰야 할 때도 있을것이고, try, catch와 같은 예외 처리 코드가 작동해도 처리해줘야 한다. 이런 급격한 변화를 exceptional control flow(ECF라고 한다.) |
ECF를 이해해야 하는 이유 | 시스템 개념을 이해하는데 도움이 된다. ECF는 운영체제가 입출력, 프로세스, 가상메모리를 구현하기 위해 사용하는 기본 메커니즘이다. 이런 중요한 아이디어들을 본격적으로 이해하기 전에 ECF를 먼저 이해할 필요가 있다. ECF를 이해하면 어떻게 응용 프로그램들이 운영체제와 상호작용 하는지를 이해하는데 도움이 된다. 응용 프로그램은 트랩 또는 시스템콜이라고 알려진 ECF의 한가지 형태를 사용해서 운영체제로부터 서비스를 요청한다. 새로운 프로세스를 만들거나 현재 프로세스를 종료시키는 등의 일은 모두 응용프로그램이 시스템 콜을 호출해서 이루어진다. 새로운 응용 프로그램 작성에 도움이 된다. 동시성을 이해하는데 도움이 된다. ECF는 동시성을 구현하는 기본 메커니즘으로, 프로세스, 쓰레드등이 ECF의 시그널 핸들러로 구성되어 있다. 예외 상황이 어떻게 동작하는지 이해하는데 도움이 된다. |
시스템콜과 핸들러란? | 시스템콜은 사용자가 OS에 요청을 보냈을때 커널이 제어권을 가져가서 컴퓨터에 명령을 내리는것이라고 생각하면 될것같다. 핸들러는 특정 이벤트나 상황이 발생했을 때 그 처리를 담당하는 함수나 코드 블록을 의미한다. 예외가 발생하면 실행되는 소프트웨어 루틴이라고 생각하자 |
Exceptions

예외 | 시스템 에러 발생 시 프로세스에서 커널로 제어권을 넘긴 후, 에러를 처리하고 다시 프로세스로 제어권을 넘겨준다. |
예외의 구성 요소 | 예외가 발생하는 경우는 다양하다. 예를들어 어떤 인스트럭션이 divide by zero를 시도하는 경우도 있지만 현재 인스트럭션과 관련없이 시스템 타이머가 정지하거나, I/O 요청이 완료되는 경우가 해당한다. 어떤 경우든지 프로세서가 이벤트가 발생했다는 것을 감지하면 예외 테이블이라고 하는 점프 테이블을 통해서 이 특정 종류의 이벤트를 처리하기 위해 특별히 설계된 운영체제 서브루틴으로 간접 프로시저 콜을 하게 된다. 그 과정은 위 사진과 같다. |
Exception Handling

예외를 처리하는 방법 | 시스템 부팅시 예외상황의 종류마다 중복되지 않는 양의 정수를 예외번호로 할당하고, 해당 테이블에 해당 핸들러의 주소를 할당한다. 런타임에 프로세서는 이벤트가 발생했을때 예외번호를 결정하고, 이는 예외 테이블의 엔트리 번호가 되어 해당 예외처리 핸들러를 호출한다. |

예외 테이블 번호 | 위 사진은 프로세서가 예외 테이블을 잉요해서 해당 예외 핸들러의 주소를 어떻게 만드는지 보여준다. 예외 번호는 예외 테이블에서 인덱스이며, 이 테이블의 시작 주소는 예외 테이블 베이스 레지스터라는 특별한 CPU 레지스터에 저장되어 있다. |
예외상황과 프로시저콜의 차이 | 프로시저는 프로시저 콜을 사용해서 핸들러로 분기하기 전에 스택에 리턴주소를 푸시한다. 하지만 예외는 예외의 종류에 따라 리턴주소는 현재 인스트럭션(이벤트가 발생했을때 실행하고 있던 인스트럭션 이거나 다음 인스트럭션) 이거나 다음 인스트럭션 (이벤트가 일어나지 않았다면 현재 인스트럭션 다음에 실행되었을 인스트럭션)이 된다. 또한 프로세서는 핸들러가 리턴할 때 중단된 프로그램을 다시 시작하기 위해 필요하게 될 스택 상에 추가적인 프로세서 상태를 푸시한다. 제어가 사용자 프로그램에서 커널로 전환하고 있을 때, 이 모든 아이템들은 사용자 스택 위가 아니라 커널 스택 상에 푸시된다. 예외 핸들러는 커널 모드에서 돌아가는데, 이것은 모든 시스템 자원에 완전히 접근할 수 있는 것을 의미한다. 위 사안에 따라 예외가 발생하면 다음과 같은 동작이 발생한다.
|
Classes of Exceptions

예외의 종류 | 예외 상황은 네가지 종류로 구분할 수 있다. 인터럽트, 트랩, 오류, 중단 |

인터럽트 | 비동기적으로 발생한다. 특정 인스트럭션을 실행해서 발생한 예외가 아닌, 하드웨어단 작업에서 발생한 예외를 처리하는 방식. 입출력 디바이스들이 프로세서 칩의 핀에 시그널을 보내서 인터럽트를 발생시키고, 인터럽트를 발생시킨 디바이스를 식별하는 예외번호를 시스템 버스로 보낸다. 현재 인스트럭션이 실행을 완료한 후, 프로세서는 인터럽트 핀이 high로 올라갔다는 것을 발견하고 시스템 버스에서 예외 번호를 읽고 인터럽트 핸들러를 호출함 핸들러가 리턴할 때 제어를 다음 인스트럭션으로 되돌려줌 |

트랩과 시스템콜 | 트랩은 의도적인 예외 상황으로, 어떤 인스트럭션을 실행한 결과로 발생한다. 인터럽트 핸들러와 마찬가지로 트랩 핸들러는 제어를 다음 인스트럭션으로 리턴한다. 트랩이 중요한 이유는 시스템 콜이라고 알려진 프로그램 - 커널 사이의 프로시저와 유사한 인터페이스를 제공하는 것이다. 사용자 프로그램은 파일을 읽거나(read), 새로운 프로세스를 만들거나(fork), 새 프로그램을 로드하고(execve) 현재 프로세스를 종료하는 등의 서비스를 커널에 요청해야 한다. 이러한 요청을 가능하게 하기 위해 프로세서는 "n" 인스트럭션을 제공하며, 이들은 사용자 프로그램이 서비스 n을 요청하고자 할때 사용할 수 있는 인스트럭션이다. 프로그래머의 관점에서 시스템 콜은 보통의 함수 호출과 동일하다. 그렇지만 실제 구현은 매우 다르다. 함수는 사용자 모드에서 돌아가며, 이때문에 이들이 실행할 수 있는 인스트럭션은 제한적이다. 하지만 시스템콜은 커널 모드에서 돌아가며, 이로 인해 모든 작업이 가능함 |

오류(fault는 error와 다르다) | 오류는 핸들러가 정정할 수 있는 가능성이 있는 에러 조건으로부터 발생한다. 오류가 발생하며 프로세서는 제어를 오류 핸들러로 이동시켜준다. 만일 핸들러가 에러 조건을 정정할 수 있다면, 제어를 오류를 발생시킨 인스트럭션으로 돌려 주어서 거기서부터 재 실행한다. 그렇지 않다면 핸들러는 커널 내부의 abort 루틴으로 리턴해서 오류를 발생시킨 응용프로그램을 종료한다. |

중단 | 중단은 대게 DRAM이나 SRAM이 고장날 때 발생하는 패리티 에러와 하드웨어 같은 복구할 수 없는 치명적인 에러에서 발생한다. 중단 핸들러는 절대로 응용프로그램으로 제어를 리턴하지 않는다. 위 그림과 같이 핸들러는 제어를 응용프로그램을 종료하는 중단 루틴으로 넘겨준다. |
'Krafton_Jungle > Study' 카테고리의 다른 글
Krafton_jungle 5기 6주차 WIL - The Memory Hierarchy (3) | 2024.04.30 |
---|---|
Krafton_jungle 5기 6주차 WIL - Implicit free list (0) | 2024.04.27 |
Krafton_jungle 5기 5주차 WIL - Linker (0) | 2024.04.23 |
Krafton_jungle 5기 5주차 WIL - RB_Tree (0) | 2024.04.22 |
Krafton_jungle 5기 31 ~ 32일차 TIL - RB-Tree, 알고리즘 (2) | 2024.04.19 |