System Programming, Process

강일모·2022년 11월 14일
0

System Programming

목록 보기
1/1

시스템 프로그래밍 수업의 3번째 Lab인 Shell Lab을 수행하기 위한 기초 지식을 정리하기 위해 작성한 글입니다.

먼저, 이 장에서 사용될 용어들에 대한 정의부터 알아봅시다.

제어흐름 (flow of control)
제어흐름이란, CPU는 한 번에 한 가지 명령(Instruction)을 처리하는데, 이 Instruction의 순차적 처리를 flow of control이라고 합니다.

BombLab을 수행하신 분들은 아시겠지만, 컴퓨터는 Assembly 수준에서 순차적으로 명령어들을 처리하다가 function을 call해야 한다거나, Branch 하는 등의 명령을 만나면 current Instruction 수행 후 잠시 다른 주소로 넘어가 subroutine 명령을 수행하고 다시 돌아와 next instruction을 수행합니다.

즉, 프로그램을 짜다보면 제어흐름을 잠깐 벗어나 다른 명령들을 수행하고 돌아올 수 있는 방법, 제어흐름을 변경할 수 있는 방법이 필요합니다. 그 방법들의 대표적인 예가 Call, Return이었습니다.

하지만, 이 정도의 명령만으로는 원하는 것을 구현하기에 부족합니다. 아래와 같은 예외적인 상황을 처리하고 다시 원래하던 일로 돌아 올 수 있는 방법이 필요합니다.

  • Ctrl + C와 같은 interrupt가 발생했을 때
  • 0으로 나눗셈을 시도했을 때

그래서 제어흐름을 변경할 수 있는 또 다른 방법을 제시합니다. 그것이 바로 ECF, Exceptional Control Flow입니다.

ECF의 상위단계의 매커니즘으로는 프로세스 컨텍스트 전환, 시그널, nonlocal 점프가 있습니다. 하위단계의 매커니즘으로는 Exceptions가 있습니다.

프로세스 컨텍스트는 OS와, 하드웨어 타이머로 구현하고, 시그널은 OS로 구현합니다. nonlocal 점프는 C런타임 라이브러리로 구현합니다.
Exceptions은 시스템 이벤트에 대한 반응으로 제어흐름을 변경하며 하드웨어와 OS 소프트웨어를 함께 사용합니다.

먼저 Exceptions에 대해 자세히 살펴봅시다.

Exceptions는 특정 이벤트에 대한 반응으로(예를 들어, division by 0, overflow 발생, 페이지오류, I/O종료, Ctrl+C) OS의 커널로 제어가 전환되는 것을 이야기합니다. 즉, user가 작성한 코드를 수행하다가, 예외가 발생하면 커널부로 넘어가서 커널의 코드를 잠시 수행하고 다시 user가 작성한 코드로 돌아와 다음 명령을 수행하는 것입니다.
*커널은 OS의 메모리 상주 부분을 이야기합니다.

Exceptions는 발생할 수 있는 Exception을 처리해 줄 수 있는 코드들의 주소를 가리키고 있는 Exception Table을 거쳐 처리됩니다. 특정 예외 이벤트를 지칭하는 index가 k일 때, k가 발생하면 Exception Handler k가 호출됩니다.

ECF는 다음 그림과 같이 분류할 수 있습니다.

Synchronous하다는 것은, 프로그램 실행 중에 어떤 이벤트가 발생하는 것이고, Asynchronous하다는 것은, 프로그램 실행 내부에서 발생한 예외가 아닌, 외부요인으로인한 예외 발생을 의미한다고 이해하시면 됩니다.

조금 더 자세히 설명해보록 하겠습니다. 먼저 Asynchronous Exception을 살펴봅시다.

Asynchronous Exception은 프로세서의 외부사건으로부터 발생하는 예외입니다.
Interreupt는 Asynchronous Exception의 대표적인 예시입니다.
프로세서의 인터럽트 핀을 세팅해서 Asynchronous Exception 이 발생했음을 표시합니다. 이런 Asynchronous Exception의 구체적인 예로는 입출력 인터럽트 (Ctrl + C, 네트워크에서 들어온 패킷 감지)와 하드 리셋 인터럽트(컴퓨터의 리셋버튼을 길게 누르면 리셋되는 그것), 소프트 리셋 인터럽트(ctrl+alt+del) 등이 있습니다.

이번엔 Synchronous Exceptions에 대해 알아봅시다.
Synchronous Exception은 명령어를 실행한 결과로 발생하는 사건입니다. 즉 프로그램 실행 중 내부에서 발생한 오류로 이해할 수 있습니다.
Sychrounous Exception은 다시 Traps, Faults, Aborts 로 나눌 수 있습니다.

Trap은 명령어의 결과로 발생하는 의도적인 예외를 의미합니다.
System Call(read, write, open, fork, execve, kill, _exit ...etc), Breakpoint traps(중단점 걸기) 등이 Traps의 대표적 예시입니다. 이 Traps Exception은 처리 후, next instruction으로 복귀합니다.

Faults는 핸들러가 정정할 수 있는 에러의 결과로 발생하는 예외를 의미합니다.
Page Fault(회복가능), Proctection Faults(회복 불가), floating point exceptions 가 Fault의 예입니다.
Faults Exceptions는 Fault를 일으킨 명령을 다시 실행하거나 Abort 합니다.

Aborts는 하드웨어 오류와 같이 복구 불가능한 에러의 결과로 발생하는 Exception입니다.
Parity Error, System Check Error 가 Abort의 예입니다. 이것은 복구 불가능한 에러가 원인이므로, 원래 응용프로그램으로 복귀하여 다음 명령을 수행 할 수 없습니다. 따라서 현재 프로그램을 종료하도록 Exception을 처리합니다.

Trap의 하나인 System Call의 open의 수행과정을 그림으로 나타낸 것입니다.

Fault의 하나인 Page Fault에 대해선 조금 더 자세히 알아보겠습니다.

아래과 같은 C 코드가 있습니다.

1000개의 int를 저장할 수 있는 배열을 선언한 후 index 500에 13을 저장하는 간단한 코드입니다.

이 코드를 실행하면 메모리에 integer 1000개 크기의 메모리 공간을 확보하고, 13을 그 확보된 공간 안에 넣어야 합니다. 즉 Assembly Code에서는 다음과 같은 명령이 존재합니다.

그런데 a[500]이 물리메모리에 올라가있지 않고, 하드디스크에 위치하는 경우 Page Fault가 발생합니다. 이것을 Page handler가 물리메모리에 Load 하고, 오류를 발생시켰던 위 어셈블리 명령을 다시 수행하는 것입니다. Fault는 오류를 해결하고 다시 수행하거나 해결하지 못하면 Abort 하는 Exception 입니다.

이제, 프로세스에 대해서 알아봅시다.

먼저 프로세스의 정의를 살펴보겠습니다.

프로세스 : 프로세스는 운영체제가 만들어 주는 프로그램의 한 실행 예시입니다.

*프로세스와 프로세서는 다른 개념입니다.

프로세스는 프로그램에 두 개의 중요한 추상화를 제공합니다.
-논리적인 제어흐름 : 각 프로그램이 CPU를 독점하는 것처럼 보이도록 합니다.
-사적인 주소공간 : 각 프로그램이 주 메모리를 독점하는 것처럼 보이도록 합니다.

프로세스의 실행이 서로 교대로 실행되고, 주소공간은 가상메모리 시스템에 의해 관리되기 때문에 이런 착시가 가능해집니다.

멀티프로세싱이 무엇인지 그림과 함께 살펴보겠습니다.

하나의 프로세서는 여러 프로세스를 동시에 실행합니다.

다른 프로세스로 넘어갈 때 현재 레지스터들을 다음에 다시 돌아와서 사용할 수 있도록 프로세서에 저장된 레지스터들을 현재 처리하고 있는 프로세스의 메모리 공간에 저장해둡니다.

다음에 어떤 프로세스를 처리할 지는 스케쥴링을 통해 고르게 됩니다.

고른 프로세스를 처리하기 위해 현재 처리할 프로세스에 저장된 레지스터들을 프로세서의 레지스터들로 가져오고, 주소공간을 전환합니다. 이를 Context Switch (컨텍스트 스위칭) 라고 합니다.

멀티코어를 사용하는 현대에는 메인 메모리는 공유하면서 한개의 칩에 포함된 여러개의 CPU 각각이 아까와 같은 방법을 수행합니다.

이번엔 아까 위에서 프로세스가 제공하는 두 가지 추상화 중 하나였던 논리적 제어흐름에 대해 알아봅시다.

각 프로세스는 자신만의 논리적인 제어흐름을 갖습니다.

동시성 프로세스의 개념에 대해 알아봅시다.

두 프로세스가 있을 때 그들의 실행 시간이 서로 중첩되면, Concurrent하다. 동시에 실행된다고 부릅니다. 그렇지 않다면, 즉 실행 시간이 서로 중첩되지 않는다면 Sequential 하다, 순차적으로 실행된다라고 이야기합니다.

위 그림에서, A와 B, A와 C는 서로 Coucurrent하고, B와 C는 Sequential 하게 실행되고 있습니다.

동시 프로세스들을 위한 제어흐름(명령어의 흐름)은 시간적, 물리적으로는 분리되지만, 마치 병렬적으로 실행된다고 생각할 수 있습니다. 이것을 멀티태스킹(MultiTasking), 타임슬라이싱(Time Slicing)이라고 부릅니다.

Context Switch에 대해 알아봅시다.

프로세스는 커널이라고 부르는 운영체제에 의해서 관리됩니다.
커널은 프로세스가 아니며, 유저 프로세스의 일부분으로 실행됩니다.

한 개의 프로세스에서 다른 프로세스로 제어흐름이 넘어가는 것을 Context Switch라고 부릅니다.

다음 그림을 살펴보면, Process A와 B가 Concurrent하게 실행되고 있을 때, Kernel Code 부에서 Context Switch가 일어나며 제어 흐름이 조절되는 것을 알 수 있습니다.

프로세스의 상태는 다음과 같이 존재합니다.

부연설명을 위해 다음 링크를 첨부합니다. https://itwiki.kr/w/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4_%EC%83%81%ED%83%9C
<프로세스 상태 - IT 위키>

다음 게시글에서 본격적으로 Shell Lab을 하기 위한 C언어 함수들을 살펴보겠습니다.

0개의 댓글