Exceptional Control Flow (12-1, 12-2)

msung99·2022년 11월 22일
0
post-thumbnail

본 포스트팅은 인하대학교 컴퓨터공학과 시스템 프로그래밍 수업자료에 기반하고 있습니다. 개인적인 학습을 위한 정리여서 설명이 다소 미흡할 수 있으니, 간단히 참고하실 분들만 포스팅을 참고해주세요 😎


Control Flow

  • CPU 는 기본적으로는 프로그램에서 주어진 명령어들을 순차적으로 하나하나 수행한다. 이떄 명령어 수행 순서를 바꿔주는 것이 Control Flow 다.

Altering the Control Flow

이전에 배웠던 Jump, call, return 등을 사용했을 떄 프로그램의 state (수행 흐름) 을 바꿀 수 있었다.

그런데 이들만 가지고는 프로그램의 state 를 바꿀 수 없다. 어떤게 더 필요하나면, 프로그래머가 앞선 명령어들처럼 일부러 의도를 가지지 state 대해 처리하는 것
그 이외의 것들이다.

=> Exceptional Control Flow : 프로그램 Handling 을 자동화해주는것


Exceptional Control Flow

low-level 에서의 Exceptional Control Flow

  • 하드웨어(low-level)에서 온 대부분의 신호를 Excpetion 이라 부른다.

high-level 에서의 Exceptional Control Flow 종류

  • Process context switch
  • Signals
  • Nonlocal jumps

Exceptions

  • 대부분의 Exception 은 하드웨어와 연관이 있다. 하드웨어에서 알려줌.

  1. 유저의 코드(user code)를 실행하고 있었는데 하드웨어에 에러를 발생시키는 event 가 발생했다면,

  2. Exception 이 발생했다고 인식하고 user code 실행을 멈추고 kernel code 로 넘어간다. 이게 Context Switching 이다.

  3. 운영체제가 이 에러가 뭔지를 확인하고 해당 에러에 대해 적절히 핸들링(Exception Handling) 해준다.

  4. Handling 이 끝났다면 다시 user code 로 되돌아가서 코드를 이어서 계속 실행(resume) 한다.


Exception Table

  • 모든 시스템(운영체제)은 Exception Table 을 가지고있다.
  • 각 인덱스에서 각 Exception Handler 에 대한 코드를 가리키고있다.

Asynchornous Exceptions

발생한 에러에 대해 바로 처리하지 않아도 되는 에러들

ex) time interrupt, I/O interrupt 와 같은 에러들은 당연히 핸들링 해줘야하지만, 에러 발생 즉시 바로 처리하지는 않고 천천히 처리한다.


Synchornous Exceptions

만일 어떤 수를 0으로 나누는 상황이 발생하고나서 별도로 에러 처리를 안하고 그 결과값을 이후의 명령어들에 활용한다면 모든 명령어들이 다 수행이 망가질 것이다. 따라서 에러 발생 즉시 바로 처리를 따로 해주고 와야한다.

디폴트 에러 처리방식은 Synchornous 이다.

  • Synchornous 란? : 에러 발생시 기존에 하던것을 멈추고 핸들링(에러 처리)을 다 하고나서 재개하는 것. (위에서 봤던 그림 처리방식)
    => 외부에서 발생한 에러 관련 event 로 인해 발생

종류

1. Traps

  • 사용자(프로그래머)가 의도적으로 일부러 발생시킨 에러
    (특정 에러가 발생하면 Trap 발생시켜라! 라는 것)

2. Faults

  • 프로그램 실행하다 뭔가 잘못되었을 때 자동적으로 발생하는 에러
    ex) 잘못된 메모리 인덱싱(접근) 할때 예외발생하는 경우

3. Aborts

  • 심각한 수준의 에러. 발생한 해당 에러에 대한 예외처리와 복구도 불가능한 에러

System Call

  • System Call : 아래와 같은 호출 명령어들이 System call 이다.

System Call 예시

  • System call 이 호출되는 순간 User 쪽에서 Kernel 쪽으로 간다.
  • 사용자(내) 코드면 당연히 권한을 부여받은 만큼만 자원 사용이 가능한 반면, 운영체제의 Kernal 공간쪽으로 넘어가면 Kernal 이 관리자 권한을 가지고 있어서 모든 자원을 자유롭게 사용 가능하다.


Fault 에러발생

앞서 언급했던 Fault 에러를 더 살펴보자.

Fault란 위처럼 잘못된 인덱싱 같은 이상한 행위를 했을 떄 자동으로 발생하는 에러라고 했었다.


Process

  • 프로그램은 소스코드와 데이터를 합쳐놓은 마치 패키치 형태를 가지고 있는데, 이를 실행시키면 생기는 인스턴스가 process 이다.

  • 각 프로세스(process) 는 각자 본인만의 메모리(스택)을 가지고있다.

프로세스는 아래의 2가지 개념을 보유하고 있어야한다.

1. logical control flow

  • 해당 프로세스만의 고유한 프로그램 실행 흐름(순서)

2. private address space

  • 다른 프로세스는 볼 수 없는 private 한 본인만의 virtual space

Multiprocessing

  • 여러 프로세스가 동시에 호출되고 있는 것 "처럼" 보이게 하는 것


MultiProcessing 의 의미(옛날)

  • 예전의 Multiprocessing 이 뭘 뜻했는지를 알아보자.

메모리안에는 프로그램이 여러개 있을 수 있다. 실제로 core 가 하나만 있다고하면, 여러 프로그램중에서 어떤 특정 프로그램의 process 를 실행하고 있을 것이다.

그런데 한 프로그램의 Saved register 라는 곳에 현재 상태를 저장하고 옆에있는 다른 프로그램으로 넘어가서 그 프로그램을 실행시킬 수 있다.

=> 이 과정이 굉장히 빠르게 왔다갔다하면 사람이 볼떄는 여러 프로그램이 마치 동시에 수행되는 것 처럼 보인다.


Multiprocessing 의 의미 (현대)

그런데 실제로는 core 가 하나가 아니고 여러개이다.
그래서 위에서 본 옛날 multiprocessing 처럼 계속 왔다갔다 하긴하는데, 여러 프로그램을 core 가 동시에 수행하고 있는 것이다. (아까는 딱 하나의 core 만 수행하고 있었음)


Concurrent Process (동시성 프로세스)

  • 앞서 언급했듯이, 각 process 는 logical control flow 를 보유하고 있다. 즉 각 프로세스마다 본인만의 고유한 프로그램 실행 흐름을 가지고 있다고 했었다.

그런데 이런 프로세스가 여럿이면, 여러 프로세스가 공유하는 데이터가 생길수도 있고, 2개 이상의 프로세스가 동시에(Courrently 하게) 수행될 수도 있다.

=> Concurrent 프로그래밍이란 Courrently 한 프로그램을 구현하는 것이다. 같은 프로그램을 구현을해도, Courrently 한 프로그램을 잘 최적화시켜 구현한 경우 자원을 최소한으로 사용하며 훨씬 빠르게 수행할 수 있다.

예시


프로세스 A가 먼저 시작되고, 나중에 B가 실행되는데 A와 함께 같은 데이터를 공유하며 실행되고 있다.

지금까지는 프로세스간에 순차적으로(Sequential) 실행되지 않고있다.

그런데 프로세스 B와 C는 순차적으로 실행되고있다. B가 끝나고 C가 실행되었다. 그런데 A와 B는, A를 하다가 stop 하고 B를 수행했다. 그러고 다시 돌아와서 B를 수행하는 것이다.

=> A와 B는 동시에 돌아갈 수 있다. A와 B는 concurrency 가 있다고 표현하며, B와 C는 concurrency 가 없다고 표현한다.

  • 즉, Concurrency 란 두 프로세스가 시작하는 시간과 끝나는 시간을 기준으로 시간대가 겹쳐있다면 (동시에 프로세스가 실행되고 있다면) Concurrent 하다고 표현한다.

  • 반대로 프로세스가 동시에 수행되지 않고 순차적으로 수행되는 것을 Sequential 하다고 표현한다.

=> 이떄 어떤 core 를 사용하던 상관없음. 그냥 프로세스가 동시에 돌아가는지 아닌지 여부만으로 Concurrent, Sequential 을 구분짓는 것이다.


Context Switching

  • Context Switching 이 발생하면 Concurrent 한것이다. 운영체제와 내 프로그램이 동시에 실행되고 있는것!

user code 의 프로세스가 수행되다가 커널로 갔다가 바로 다시 돌아옴


System call Error Handling

  • system call 을 하다가 에러가 발생한 경우, 어떻게 동작했는지 확인해보고 싶다면 errno 변수를 사용하면 된다.

Process Control

  • process 의 상태는 프로그래머 입장에서 봤을때 3가지 종류로 나뉜다.

=> Running (실행되고 있거나), Stopped(잠시 스탑되서 기다리고 있거나), Terminated(끝났거나) 이다.


Creating Process

  • fork() : system call함수. fork를 호출하면 이 함수를 호출한 프로세스가 카피되어 새로운 프로세스가 하나 더 생긴다.

=> 나는 parent process 이고, fork 된 새로운 프로세느는 child process 이다.

  • 리턴값으로 child process 의 PID 값를 리턴

=> 원래 있던 프로세스(parent)와 새로운 프로세스(child) 는 구분하는 방법은 리턴되는 PID 값을 보고 판단한다. (리턴되는 PID 값이 0이면 child process, 그 외의 값은 process process)

  • 새로 생겨난 여러 child process 들이 자기가 담당하는 부분의 코드를 실행하면서 시스템을 초기화한다.

fork 예제


Synchorning 하기

  • child process 로의 분기가 발생했다면 프로그램이 끝날떄 exit 함수가 각자 따로 호출되면 안되고, 동시에 호출되서 같이 종료되어야 한다. parent 가 child 의 수행이 다 끝날때까지 기다려주고 exit 가 호출되어야함

  • wait(), waitpid() 함수를 써서 parent가 끝나면 child가 끝나도록 해야함

    에시

  • 보듯이 wait 을 쓰면 parent 가 child 가 끝날때까지 기다렸다가 process 가 전체적으로 함께 exit(종료) 된다.

Signal

  • Exception 과 비슷한 방식으로 소프트웨어 하나를 구현한 것.

    어떤 중요한 특정 event 가 발생했을 때 운영체제가 user 프로그램들한테 알려주는 방법이다.
    (이러한 중요한 이벤트가 발생했어! 라고 signal(시그널) 로 알려주는 것)

  • 특정 이벤트마다 유일한(unique) 번호(ID) 가 정해져있어서 구분할 수 있다.


커널은 Signal 을 2가지 상황일때 보낸다.

1) 시스템 event 를 감지해서 user process들 한테 알려주고 싶을때
2) system call 을 사용해서 운영체제가 생성한 API 를 통해 한 user process 에서 다른 user process 로 보내고 싶을 때


  • Exception 은 운영체제가 받고 핸들링하는데, Signal 은 운영체제가 보내고 user program 이 받는 것이다.

profile
https://haon.blog

0개의 댓글