본문 바로가기

프로그래밍/운영체제

운영체제 (2) - 시스템은 어떻게 보호 되는가? (system call)

 

시스템은 사용자 응용 프로그램이 시스템에 해를 끼치는지 어떻게 알아낼 수 있을까?

 

내용을 시작하기에 앞서 이 글은 시스템 호출(system call)에 대한 내용을 메인으로 다룰것이다.

내가 시스템콜에 대해 가장 간단히 방법은 다음과 같다.

만약 당신이 간단한 프로그램을 실행할 때 하나의 프로그램 실행에도 많은 내부과정이 필요하다.

하나의 상황을 예시로 들어보자.

당신은 파일의 내용을 복사하는 프로그램을 작성하기를 희망한다.

이 때 필요한 것은 첫번째로 읽는 입력파일 이름, 출력파일 이름. 이를 위해 프로그램은 사용자에게 두 파일의 이름을 요청할 것이다.

이 때 시스템콜이 필요한데, 프롬프트 메시지를 화면에 표시하기 위해 시스템콜이 필요하고

두 파일의 이름에 해당하는 문자열을 키보드로부터 읽기 위해 두번째 시스템콜이 필요하다.

후에 시스템 콜이 필요한 과정을 포함한 여러 과정을 통해 하나의 프로그램이 작성 될 것이다.

 

오류가 발생할때 검사하기 위해 시스템콜, 파일을 읽는것도 시스템콜, 기록하는것도 시스템콜, 혹은 메세지를 출력하는 것도 시스템콜

말 그대로 시스템을 호출하는것이 시스템 콜이다. ( 쉽게 이해하면 너무 당연한 얘기이기도 하다 )

 

 

 

 

그렇다면 시스템콜과 시스템의 보호에는 어떤 관계가 있는 것일까?

나도 아직 확실하게 이해하지 못하였다고 생각하는데

단순하게 생각함에 있어서는 프로그램이 실행되는 여러과정(시스템콜) 중에 유해한 과정을 검사하는것과 관계가 있지 않나 생각한다.

한 번 천천히 이해하며 공부해보자

우리는 시스템콜을 제대로 이해하기 위해서는 두가지 모드에 대한 이해가 필요하다.

 

 

 

운영체제의 적절한 동작을 보장하기 위해 운영제제 코드의 실행과 사용자 정의 코드의 실행을 구분할 수 있어야 한다.

많은 운영체제에서 사용되는 접근 방법은 여러 실행 모드를 구분할 수 있는 하드웨어 기능을 이용한다.

 

 


일단 두가지

사용자 모드와 커널 모드가 있다.

 

 

 

현재의 모드를 나타내기 위해 모드 비트의 사용, 모드 비트가 추가되어 커널 모드(0) 사용자 모드(1) 을 나타낸다.

 

 

 

간단히

사용자 모드는  컴퓨터 시스템이 사용자 응용을 대신하여 실행 될 때

커널 모드는 사용자 모드에서 운영체제가 제공하는 서비스를 요구하면 커널 모드로 전환한다.

 

system call

 

트랩이나 인터럽트가 발생할 때마다 하드웨어는 사용자 모드에서 커널 모드로 전환한다.

그러므로 운영체제가 컴퓨터의 제어를 얻을 때마다 항상 커널 모드에 있게 된다. 

그 후 시스템은 사용자 프로그램으로 제어를 넘기기 전에 항상 사용자 모드로 전환한다.

 

 

다시 돌아와서

이러한 두 개의 모드는 왜 필요한걸까?

이들이 잘못된 사용자로부터 운영체제를 그리고 잘못된 사용자 서로를 보호하는 방법을 제공하기 때문이다.

 

우리는 악영향을 끼칠 수 있는 일부 명령을 특권 명령(privileged instruction) 이라 지정한다.

하드웨어는 특권 명령이 커널모드에서만 수행되도록 허용한다.

그렇기에 사용자 모드에서 특권 명령을 수행하려고 시도하면 하드웨어는 이를 실행하지 않고 운영체제로 트랩을 건다.

 

 

 


우리는 다시 돌아와서 시스템콜에 대해 생각을 해보자.

우리는 여기서 거시적인 이해가 한 번 필요하다.

처음에 시스템콜에 대해 얘기한 바와 같이 간단한 프로그램이라도 초당 수천 개의 시스템호출을 실행하게 된다.

대부분의 프로그래머들은 이러한 정도로 자세하게 알 수도 없고, 그럴 필요 역시 없다.

우리는 시스템콜을 편리하게 이끌어내기 위해 API를 사용한다.

 

API와 시스템콜

운영체제를 공부하고 있는 분들이라면 API 한 번 쯤은 사용해 본 적이 있을 것이다.

API 를 사용하면 내장 함수들이 여럿 있을텐데

우리가 코드를 짜면서 함수를 사용할 때 이 함수들은 프로그래머들을 대신하여 실제 시스템콜을 호출한다.

 

나중애 표준 C 라이브러리를 예시로 하는 상황이 다시 있겠지만

우리가 C 에서 printf() 함수를 사용하면 API 는 어느 커널에서 write() 시스템콜을 호출하는 것이다.

 

 

 

 

 

여기서 시스템콜 인터페이스라는 개념을 추가해보자.

이것이 하는 역할은 사용자가 printf() 함수를 요청하는 이들은 함수의 호출을 가로채어 필요한 운영체제 시스템콜을 한다.

통상 각 시스템콜에는 번호가 할당되고 이들은 번호에 따라 기록하는 테이블을 유지한다.

이들은 단지 의도하는 시스템 호출을 부르고 시스템 호출의 상태와 반환 값을 돌려준다.

 

앞서 말한것처럼 사용자는 시스템콜이 어떻게 구현되고 실행 중 무슨 작업을 하는지 아무것도 알 필요가 없다.

API 를 준수하고 시스템 호출의 결과로서 운영체제가 무엇을 할 것인지 잘 활용하는 방법만 알면 된다.

따라서 시스템콜 인터페이스에 대한 자세한 내용은 프로그래머로부터 숨겨지는것이다. 

 

API가 함수 시스템콜을 불렀을때 운영체제가 어떻게 처리하는지 그림으로 정리되어있다.

 

 

시스템콜의 유형

대표적으로 다섯 가지의 중요한 범주

프로세스 제어, 파일 조작, 장치 조작, 정보유지, 통신 으로 나줄 수 있다.

종류가 굉장히 많은데 하나하나 일일이 알 정도까진 없다고 느껴서 사진으로만 그 종류를 정리하려 한다.

우리는 그 중에서 프로세스를 제어하는 fork () 와 wait 정도만 나중에 다루려고 한다!