크래프톤정글5주차 - CSAPP 8장

김태성·2024년 2월 17일
0
post-thumbnail

드디어 CSAPP 6,7,8,9장을 모두 읽었다!!
긍정적으로 생각하자면 기본적인 운영체제에 대한 내용을 머리에 담고 있기 때문에
다른 설명을 들을 때 아 그거! 라고 말을 할 수 있는 것이고

부정적으로 생각하자면 아직도 읽어야 할 게 산더미처럼 쌓여있으며
그저 수박겉햝기로 내용을 훑어본 것이다.

그래도 이번에 한번 읽었고, 다음 알고리즘 복습 주차때는 CSAPP 책을 처음부터 끝까지 읽는걸 목표로 삼아야 겠다.

당장의 목표는 일단 10~13장까지 책을 읽은 후 , 시간이 되는대로 다른 운영체제 책을 읽는 것이다.

8장 예외적인 제어흐름

이번장은 내용을 요약하기 간편하다.

  • 시스템 에러 발생 시 프로세스에서 커널로 제어권을 넘긴 후, 에러를 처리하고 다시 프로세스로 제어권이 넘어간다.

이거 한줄이면 끝이난다.
이번장에 적힌 내용들은 이러한 예외적인 제어 흐름이 발생했을때, 어떤 시스템 콜을 쓰고, 그 콜들은 어떤 작용을 하며, 제어흐름을 어떻게 이해하여야 하는지에 관해 적혀있다.

우리는 왜 이런 예외적인 제어흐름(Exeptional Control Flow, ECF)를 알아야 할까?

  • 시스템 개념을 이해하는데 도움이 된다. : ECF는 운영체제 구현을 위해서 사용하는 기본 메커니즘이다.

  • 응용 소프트웨어와 운영체제가 어떻게 상호작용 하는지 이해하는데 도움이 된다. : 소프트웨어들은 trap , systemcall을 통해 운영체제로부터 서비스를 요청한다.

  • 새로운 응용프로그램 작성에 도움이 된다.

  • 동시성을 이해하는데 도움이 된다. : 핸들러와 프로세스/쓰레드의 작용방식 등등

  • 예외상황에 대한 이해가 높아진다. : jump상황에 대한 이해가 높아진다.

시스템 콜 이란?

운영 체제의 커널이 제공하는 서비스에 대해, 응용 프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스.

핸들러란?

-> 앞으로 계속나올건데 햇깔리지 않게 정리하고가자.
핸들러 = 어떤 상황을 해결하기 위한 소프트웨어 루틴.
문제 해결을 할때 수행하는 일정한 절차 라고 보면 된다.

~~핸들러, @@핸들러 라고 계속 나오는데
어떠한 상황에서 시행하는 절차들이다.

8-1 예외상황


위는 응용프로그램에서 예외상황이 발생했을때 어떻게 처리하는지를 보여준다.
devide by zero 연산을 시도하는 경우라고 가정해 보자.

우선 프로세스가 이벤트를 감지했다면, 예외 테이블이라고 하는 점프 테이블을 통해서 문제를 해결하기 위해 특별하게 설계된 운영체제 서브루틴(예외처리 핸들러)로 간접 프로시저 콜을 하게 된다.

정리를 하자면, 문제가 발생했을때, indirected procedure call(the exception)을 하게 되고, 이후 서브루틴(exception handler)를 통해 문제를 해결한 후 , return을 하게 된다.
그리고 리턴은 3종류가 있는데,

  • 핸들러가 제어를 Icurr에 넘겨준다. 예외가 발생한 인스트럭션이다.

  • 핸들러가 제어를 Inext에 넘겨준다. 예외가 발생한 인스트럭션의 다음 단계다.

  • 중단된 프로그램을 종료한다.

이후 설명은 위 세가지의 추가 설명이다.

예외처리
시스템에서 가능한 예외상황의 종류마다 '예외번호'를 붙여서 부른다.
일부는 프로세서 설계자가, 나머지는 커널 설계자가 부여한다.

->여기서도 알수있다시피 프로세서와 커널의 상호작용이 매우 중요하다.

  • 시스템을 부팅할 때 운영체제는 '예외 테이블' 이라는 점프 테이블을 할당,초기화하고
    엔트리 k가 예외상황 k에 대한 핸들러의 주소를 갖는다.

  • 런타임에 프로세서는 이벤트가 발생했다는걸 감지하고, 대응되는 예외번호 k를 결정한다.
    이후 예외테이블의 엔트리k를 통해서 간접 프로시저 콜을 하는 방법으로 예외상황을 발생시킨다.

하지만 예외상황과 프로시저 콜은 중요한 차이점이 있다.

  • 프로세서가 프로시저 콜을 사용해서 핸들러로 분기(branching)하기 전에 스택에 리턴주소를 푸쉬한다.
    이때 리턴주소는 현제 인스트럭션이거나 다음 인스트럭션이 된다.(8-1 처음 그림에서 나온 설명)

  • 프로세서는 핸들러가 리턴할때 프로그램을 다시 시작하기 위해, 추가적인 프로세서 상태를 푸쉬한다.

  • 이러한 아이템들은 프로그램에서 커널로 제어가 이동할때 커널로 푸쉬된다.

  • 예외 핸들러는 커널모드에서 돌아가는데(run, 작동한다는뜻) 이것은 이들이 모든 시스템 자원에 접근할 수 있는 것을 의미한다.

예외의 종류

async = 비동기 : 응답에 관계없이 실행
sync = 동기 : 응답을 받아야 실행

4가지가 있다 : 인터럽트(interrupt),트랩(trap),오류(fault),중단(abort)

  1. interrupt
  • 하드웨어 인터럽트를 위한 예외 핸들러를 인터럽트 핸들러라고도 부름.

  • 입출력 디바이스들이 프로세서 칩의 핀에 시그널을 보내서 인터럽트 발생시키고, 디바이스를 식별하는 예외번호를 시스템 버스로 보냄

  • 현제 인스트럭션 실행 후, 인터럽트 핀이 high로 올라가있는걸 확인하고 시스템 버스에서 예외번호를 읽은 후 적절한 인터럽트 핸들러를 호출함.

  • 핸들러가 리턴할때 제어를 다음 인스트럭션으로 되돌려줌.

  1. trap and system call
  • 트랩은 의도적인 예외상황이며 어떤 인스트럭션을 실행한 결과로 발생한다.

  • 인터럽트 핸들러와 마찬가지로 제어를 다음 인스트럭션으로 리턴한다.

  • 트랩이 중요한 이유는 '시스템 콜'이라고 부르는 프로그램-커널 사이의 프로시저와 유사한 인터페이스를 제공하는 것이다.

  • 사용자 프로그램은 파일을 읽고(read),프로세스를 만들고(fork),새 프로그램을 로드하고(execve), 프로세스를 종료하는 일 등을 커널에 요청해야 한다.

  • 이러한 커널 요청을 가능하게 만들기 위해 "n" 인스트럭션을 제공하며, 사용자 프로그램이 n을 요청하고자 할때 사용할 수 있는 인스트럭션이다.

  1. fault(fault is not error)
  • fault는 핸들러가 고칠 수 있을거 같은 에러 조건에서 나온다.

  • 올류가 발생했을때 프로세서가 fault핸들러로 제어를 이동한다. 만약 여기서 문제가 해결 된다면 Icurr으로 제어를 돌려 준 후 재시작을 하고, 그렇지 않다면 abort 루틴으로 리턴해서 프로그램을 종료한다.

  1. abort
  • 답이 없는 에러에서 발생한다. 이때 핸들러는 리턴하지 않고, 프로그램을 종료하는 루틴으로 넘긴다.

8-2 프로세스

Exceptions(예외상황)은 커널에서 프로세스의 개념을 잡기위한 가장 좋은 구성요소이다.
(대충 프로세스 개념을 설명하기 위해서는 예외상황만한게 없다는 뜻)

보통 우리는 프로그램이 프로세서,메모리를 독점하고, 인스트럭션이 매끄럽게 실행되는것 처럼 보이는데, 이것은 모두 프로세스라는 개념이 만들어준다.

논리적인 제어흐름

위의 그림은 3개의 프로세스를 실행하는 과정을 설명해 준다.
위 그림을 보면, A 프로세스가 실행되다가 멈춘 후 B 프로세스가 실행되고, 이후 멈췄다가 C,A,C 순으로 다시 실행되는 것이다.

어찌보면 이상하다고 생각할 수 있지만, 메모리 위치나 레지스터 내용은 변경되는 것이 없으니 사람이 보기에는 3개가 서로 충돌 하지 않고 논리적인 제어를 따라 실행된다.

동시성 흐름

자신의 실행 시간이 다른 흐름과 겹치는 논리흐름을 '동시성 흐름'이라고 한다.
위의 그림을 예로 들면, 프로세스 A 는 C와 번갈아 실행이 됨으로 동시성 흐름이라고 할 수 있고,
C의 시작 전에 B가 끝났음으로 프로세스 B는 A와 '동시성 흐름'을 가지고 있지만, B와 C는 '동시성 흐름'을 가지고 있지 않다.

병렬 흐름과는 잘 구분해서 생각해야되는데,
동시성 흐름은 프로세스 코어/ 컴퓨터 개수와는 상관이 없다. 두개의 흐름이 중첩된다면 그건 동시성 흐름이다.
하지만 이것이 다른 프로세스 코어나 컴퓨터에서 돌아가고 있다면 병렬 흐름이다.

즉 병렬 흐름은 동시성 흐름의 부분집합인 것이다.

사적 주소공간

프로세스는 각 프로그램에 사적 주소공간을 할당해 준다.
이 주소공간은 다른 프로세스에 의해 읽히거나 쓰일 수 없는, 보호된 공간이다.

이 주소공간의 내용들은 다르다고 할지라도, 모두 같은 구조를 갖는다.
라고 말하지만 그냥 가상메모리 이야기이다.
프로세스 관점에서 봤을때는 사적 주소공간,
메모리 관점에서 봤을때는 가상 메모리 라고 이해하면 된다.

사용자 및 커널 모드

빙빙빙 돌려돌려 설명하고 있지만 간단하게 요약을 하자면

  • 완벽한 프로세스 추상화를 제공하기 위해, 응용프로그램의 인스트럭션을 제한해야 된다.

  • 하지만 특별한 경우에는 모든 인스트럭션을 실행할 수 있다.

  • 이런 특별한 경우를 '커널 모드'라고 하며, 이를 판단하는 레지스터 내 비트를 '모드비트'라고 한다.

끄읏

*문맥 전환

이것도 빙빙돌려 설명하지만 말하고자 하는건 간단하다.
다른 프로세스를 실행하고 싶을 때, 지금 프로세스의 문맥(정보)를 전환하고,
커널을 통해 다른 프로세스로 전환한다.

이러한 문맥 전환은 시스템 콜 , 인터럽트의 결과에서 나타난다.
멀티태스킹을 위해서도 사용한다고 한다.

8-3 시스템 콜의 에러

간단하게 말하면 에러를 발생할때 함수를 쓰면 간단해진다는걸 말하고 있다.

pid_t Fork(void)
{
	pid_t pid;
    
    if((pid = fork()) < 0 )
    	unix_error("Fork error");
    return pid;
}

라는 함수가

pid = Fork();  

라는 한줄로 줄어든다고 한다. 그냥 당연한 소리를 적어놨다.

여기 뒤의 내용은 그냥 프로세스 제어함수및 여러가지를 설명해 놨다.

Fork , wait,execve,시그널,jump

그저 함수의 활용을 나타낸 것임으로, 굳이 정리하지는 않겠다.

profile
닭이 되고싶은 병아리

0개의 댓글

관련 채용 정보