본문 바로가기

CS/운영체제

[OS] 시스템콜, 그리고 관련된 개념들

이 글은 '운영체제 아주 쉬운 세가지 이야기' 책을 학습하고 정리한 내용입니다.

 

 

운영체제 아주 쉬운 세 가지 이야기

운영체제 아주 쉬운 세 가지 이야기

www.aladin.co.kr

 

 


 

 

 OS에서 가상화 기법을 구현하기 위해서 ‘성능 저하’, ‘제어 문제’라는 이슈를 해결해야 했다. 초기 OS 개발자들은 프로그램을 빠르게 실행시키기 위해, 가장 기초적인 접근법인 ‘직접 실행’을 적용하였다.

 

 

(시스템콜 도입 배경) 직접 실행

(여기서 직접 실행이란, 프로그램이 시스템에 필요한 모든 연산들을 직접 통제 가능하다는 의미이다)

 직접 실행이란 간단하다. 말그대로 프로그램을 CPU 상에서 실행시키는 것이다. 프로그램이 실행되기 위해서 OS는 아래의 절차를 수행한다.

  1. 프로세스 목록에 해당 프로세스 항목 생성
  2. 메모리 할당
  3. 프로그램 코드를 디스크에서 메모리로 탑재
  4. 프로그램 시작점(진입점. ex. main 함수)를 찾아 사용자 코드를 실행한다.

 

 위 절차는 별 이상 없어 보인다. 정말 그럴까? 먼저, 프로그램을 직접 실행시킨다면 프로그램이 OS가 원치않는 동작을 수행하지 않는다는 보장이 없다. 그리고, 프로세스 실행 시, OS가 프로그램의 실행을 중단하고 다른 프로그램으로 전환시킬 방법이 없다. 즉, CPU 가상화를 위한 시분할 기법을 구현할 수 없다.

 

 시스템콜과 유저모드 & 커널모드에 관련된 포스팅인데 왜 뚱딴지 같은 이야기를 하지 싶을 것이다. 시스템콜과 이와 관련한 개념들은 위에서 “프로그램을 직접 실행시킨다면 프로그램이 OS가 원치않는 동작을 수행하지 않는다는 보장이 없다”라는 문제를 해결하기 위해 도입된 것이다. 이러한 이유로, 도입 배경을 먼저 설명하였다.

 

 

프로그램의 연산(or 권한)을 제한하는 방법

 ‘직접 실행’은 말 그대로 Direct로 실행하기 때문에, 빠르다는 장점이 존재한다. 그러나, OS가 시스템에 대한 접근 API를 지원하지 않기 때문에, 프로그램에서 I/O나 CPU 및 메모리와 같은 시스템 자원에 대한 추가할당을 요청할 방법이 없다.

물론, 프로세스가 원하는 대로 냅두는 방안도 있다. 하지만, 위에서 말했듯이, OS는 프로그램이 어떤짓을 할 지 믿을 수 없다. 따라서, 안전하게 시스템과 관련한 기능을 제공하는 방법이 필요해졌다.

 

 

시스템 콜

 이러한 목적으로, ‘시스템 콜(system call)’이 도입되었다. 시스템 콜은 사용자 프로세스가 디스크 I/O와 같은 특권 명령어를 실행할 수 있도록 지원해주는 API이다. 시스템 콜이 동작하기 위해서, 프로그램의 동작 모드는 ‘사용자 모드(user mode)’와 ‘커널 모드(kerner mode)’로 나눠진다.

 

유저모드

 유저모드에서 실행되는 코드는 할 수 있는 일이 제한된다. 예를 들어, 프로세스가 사용자 모드에서 실행 중이면, (직접) 입출력 요청을 할 수 없도록 제한한다. 이때 입출력 요청을 하면 프로세서가 예외를 발생시키고, 운영체제는 해당 프로세스를 제거한다.

 

커널모드

 커널 모드는 사용자 모드와 대비되는 모드로서, 운영체제의 중요한 코드들이 실행된다. 이 모드에서 실행되는 코드는 모든 특수한 명령어를 포함하여 원하는 모든 작업을 수행할 수 있다.

 

 

 

Trap 특수 명령어(함정이 아닌, 트랩)

 시스템 콜을 실행하기 위해 프로그램은 Trap 특수 명령어를 실행해야 한다. trap 이 동작하게 되면, 커널 안으로 분기하는 동시에 특권 수준을 (유저모드 → ) 커널모드로 상향 조정된다. 커널 모드로 진입하면 OS는 모든 명령어를 실행할 수 있고 이를 통하여 프로세스가 요청한 작업을 처리할 수 있다.

 

 처리가 완료되면 OS는 return-from-trap 특수 명령어를 호출하는데, 이 명령어는 trap과는 반대로, (커널모드 → ) 유저모드로 하향 조정하면서, 호출한 사용자 프로그램으로 돌아간다. trap과 return-from-trap 특수 명령어가 수행될 때, 하드웨어에서 지원해야 될 부분이 있는데, 호출한 프로세스에 필요한 레지스터 값들을 Load & Store 연산을 수행해줘야 한다. 이는 OS가 return-from-trap 명령어 실행 시 사용자 프로세스로 정상적으로 돌아갈 수 있도록 하기 위함이다.

 

 구체적인 예시를 들자면, x86 시스템에서는 프로그램 카운터, 플래그와 다른 몇 개의 레지스터 값들을 커널 스택(kernel stack)에 저장한다. 이후 return-from-trap 명령어가 호출되면, x86은 커널 스택에서 레지스터 값들을 pop하여, trap 명령어 실행 이전 상태로 복구한다.

 

유저 스택 vs 커널 스택

 스택 영역이 두 공간으로 나눠진 것은 보안 및 권한을 나누기 위함이다. 구체적으로 들여다 보지는 않을 것이지만, 유저 스택에는 사용자가 프로그램을 실행하는 중에 사용하는 데이터 구조들이 저장되고, 커널 스택에는 커널이 각각의 프로세스들의 상태를 유지하기 위한 데이터들을 저장해둔다. 물론, 위 데이터만 저장되는 것은 아니며, 더 자세한 내용은 아래 링크를 참조하자.

 

What is a processes' kernel stack? What exactly is its use besides keeping the thread_info?

Answer (1 of 3): In a Linux system, every user process has 2 stacks, a user stack and a dedicated kernel stack for the process. The user stack resides in the user address space (first 3GB in 32-bit x86 arch.) and the kernel stack resides in the kernel addr

www.quora.com

A process's kernel stack is a region of memory used by the operating system to store the execution context of a thread while it's running in kernel mode. This includes things like function call information, local variables, and other data necessary for the thread's execution. Besides keeping the thread_info, the kernel stack is used for handling interrupts, exceptions, and system calls, as well as for managing the thread's state while it's running in kernel mode. It's an essential part of the operating system's infrastructure for managing and executing threads.

 

 

 

Trap 명령어 호출 과정

 커널은 부팅 시에 트랩 테이블(trap table)을 만들고 이를 이용하여 시스템을 통제한다. 컴퓨터가 부팅될 때 시스템을 마음대로 다울 수 있어야 되기 때문에, 부팅 시에 트랩 테이블이 생성되는 것이다.

 

 트랩 테이블에는 어떤 것이 저장될까? 예외 사건이 발생했을 때 하드웨어가 어떤 동작을 수행해야 되는지 알려주는 것이다. 예외 사건으로는, 하드 디스크에 인터럽트가 발생할 경우, 키보드 인터럽트가 발생할 경우, 등등이 있다. (인터럽트라는 단어가 ‘방해하다’라는 의미를 갖는다고 해서, 부정적인 의미로 받아들여서는 안된다. 시스템에 오류가 발생하는 것을 의미하는 것이 아닌, 프로그램이 실행 중 특정 처리를 필요로 할 때 발생하는 개념이다.)

 

 그런데 위와 같은 인터럽트(혹은 트랩)가 발생했을 떄, 어떤 동작을 해야되는지는 트랩 테이블에 적혀있는 것일까? 엄밀히 말하면 그렇지 않다. 트랩 테이블은 트랩 핸들러의 위치를 알려줄 뿐이다. 트랩 핸들러란 특정 트랩 명령어에 대해 어떤 동작이 수행되어야 하는지 알려주는 코드이다. OS는 트랩 테이블을 통해 트랩 핸들러의 위치를 알려주는 것이다.

 

 

전체적인 Trap 명령어 호출 과정은 아래와 같다.

1. (시스템 부팅 단계)트랩 테이블 초기화 및 위치 기억

2. trap 명령어 실행

 

3. return-from-trap 명령어 실행

 

'CS > 운영체제' 카테고리의 다른 글

[OS] I/O 장치 - 폴링 & 인터럽트 & DMA  (0) 2024.01.22
[OS] 운영체제 개요  (2) 2024.01.17