시스템 콜
정의를 보면 운영체제의 커널이 제공하는 서비스에 대해, 응용 프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스라고 합니다. 간단하게 말하자면 운영체제 서비스를 접근하기 위한 유일한 수단입니다. 프로그램을 실행하거나 프로그램이 컴퓨터 자원을 사용하기 위해서는 시스템 콜을 통해 커널에 자원 사용을 요청을 해야 합니다.
시스템 콜의 주요 세 가지 기능은 다음과 같습니다.
- 사용자 모드에 있는 응용 프로그램이 커널의 기능을 사용할 수 있도록 한다. = 운영체제 서비스에 접근을 할 수 있게 해 줍니다.
- 시스템 호출을 하면 사용자 모드에서 커널 모드로 바뀐다.
- 커널에서 시스템 호출의 작업이 끝나면 사용자 모드로 돌아간다.
여기서 말하는 사용자 모드와 커널 모드의 의미를 조면 사용자 모드는 사용자가 프로그램 실행, 코드 작성 등을 하는 상태를 말하고 커널 모드는 시스템 콜을 처리하는 상태를 말합니다. 하드웨어 내부에 존재하는 Mode bit를 통해 구분합니다. 모든 비트가 0이면 커널 모드, 1이면 사용자 모드가 됩니다.
- 사용자 모드 : 사용자, 프로그램이 접근할 수 있는 범위를 두고 범위 내에서 동작을 합니다.
- 커널 모드 : 컴퓨터의 자원들이 운영체제의 제어 하에 동작하며 모든 종류의 명령을 사용할 수 있게 됩니다.
사용자가 만들어내는 프로그램은 불안정하고 보안성이 부족할 수 있기 때문에 시스템에 큰 영향을 미칠 수 있는 연산들을 커널 모드에서 이루어지는 하드웨어/소프트웨어 추상화를 통해 컴퓨터 전체의 보안을 유지할 수 있게 됩니다.
cp a.txt b.txt : 파일의 복사본을 만들어 내려고 하면 다음과 같은 과정을 거치게 됩니다.
- open a.txt, open b.txt : a.txt 파일을 열고 b.txt파일을 새로 만들어냅니다.
- read a.txt => write b.txt : a.txt의 내용을 읽고 b.txt에 내용을 씁니다.
- close a.txt b.txt : 두 파일을 닫습니다.
위 과정에서 open 2번, read/write, close 2번 총 6번의 시스템 콜이 일어났습니다.
시스템 콜의 유형을 보면 intro에서 소계한 운영체제 서비스와 비슷한 것을 볼 수 있습니다.
- 프로세스 제어 : 프로세스를 생성, 중지(fork, exec, exit ...)
- 파일 조작 : 파일 생성, 삭제, 속성 관리 등(create, open, close, lseek ...)
- 장치 관리 : 장치 연결, 방출, 속성 관리 등(open, close, ioctl ...)
- 정보 유지 : 시간, 날짜 설정, 프로세스와 연결된 파일, 장치 관리 등(time, date, dump, pid ...)
- 통신 : 통신 연결 생성, 제거, 메시지 송수신 등(open, connect, accept, read, pipe ...), 메모리 공유 방식과 메시지 전달 방식이 있습니다.
- 보안 : 파일, 사용자 권한 등(chmod, umask ...)
인터럽트
프로그램이 컴퓨터에서 동작하고 있을 때, 입출력 연산 혹은 예외상황이 발생하여 처리가 필요할 때 이를 마이크로 프로세서에게 알려 처리를 할 수 있도록 하는 것을 말합니다.
인터럽트는 발생원, 우선순위, 인터럽트 벡터로 이루어져 있습니다.
인터럽트에는 2가지 종류가 있습니다.
외부 인터럽트(=하드웨어 인터럽트) : CPU의 외부에서 인터럽트 요구 신호에 의해 발생하는 인터럽트입니다. 하드웨어 흐름에 의해 생기는 인터럽트 이므로 비 동기적 특성을 가지고 있습니다.
- I/O(입출력) 인터럽트 : 입출력 작업이 종료되어 결과를 반환하거나 오류에 의해 정지되었을 때 발생
- Power fail(전원 이상) 인터럽트 : 전원이 이상현상에 의해 공급 중단되었을 때 발생
- Machine check(기계 착오) 인터럽트 : CPU의 기능이 잘못되었을 때 발생
- External(외부) 인터럽트 : 외부 장치로부터 인터럽트가 오거나 ^C 키 발생, 자원 할당 시간이 끝남을 알리는 타이머에 의해 발생
내부 인터럽트(=소프트웨어 인터럽트) : CPU 내부에서 발생하는 인터럽트, 잘못된 명령 혹은 데이터를 사용할 때 발생합니다. Trap이라고 불리기도 합니다. 프로그램 내부의 명령어에 의하여 고정적인 위치에서 발생하는 인터럽트로 동기적 특성을 가집니다.
- 프로그램 검사 인터럽트 : 프로그램적으로 발생하는 오류에 의하여 발생( 0으로 나누기, over/under flow, 예외 등)
- 시스템 콜에 의하여 발생
CPU의 상태를 나타 내 보면 다음과 같습니다.
시스템 콜과 인터럽트 동작 방식
운영체제가 컴퓨터에 장착된 장치나 하드웨어를 관리하기 위해서 2가지 방식 중 하나를 사용합니다.
- 폴링 방식 : 상태를 주기적으로 검사하여 조건을 만족하면 처리를 하는 방식
- 인터럽트 방식 : 특정 신호를 발생시켜 운영체제에 처리를 요구하는 방식
폴링 방식의 문제점은 주기적으로 검사를 해야 하며 문제가 없더라도 검사를 하기 때문에 CPU가 일을 많이 하게 됩니다. 그에 비하여 인터럽트 방식은 발생 시에만 처리를 하고 다른 시간에는 다른 작업을 할 수 있기 때문에 효과적으로 관리를 할 수 있습니다. 따라서 오늘날 거의 모든 컴퓨터가 인터럽트 기반의 시스템을 사용합니다.
보안과 잘 정의된 함수를 사용하여 버그를 방지하고 CPU의 부담을 줄이기 위해 시스템 콜 동작은 인터럽트를 발생시켜 동작합니다.
사용자 프로그램이 시스템 콜을 사용하기 위해서는 시스템 콜을 불러들일 수 있는 어떤 것이 필요합니다. 이를 위해 커널은 다른 인터럽트와 함께 시스템 콜을 종류별로 번호를 매기고 이 번호가 기록된 테이블을 부팅 시 메모리에 올려둡니다. 이 테이블을 인터럽트 디스크립터 테이블이라고 합니다.
시스템 콜에 의하여 발생하는 인터럽트를 살펴보도록 하겠습니다. 전체 흐름을 보면 다음과 같습니다.
- 프로그램 안의 명령어 실행 중 인터럽트가 발생하면 먼저 인터럽트 가능 플래그(IE)와 인터럽트 요청 신호를 비교하여 실행 가능한 인터럽트인지 확인합니다. 인터럽트 종류에 따라 항상 응답을 해야 하는 중요한 인터럽트도 존재합니다.
- 실행 가능한 인터럽트가 아니라면 무시하고, 가능한 인터럽트라면 인터럽트 요청을 제어장치로 전달합니다.
- 제어장치는 현재 실행 중인 프로그램을 중단하고 프로그램의 위치(PC), 레지스터 상태 등 을 스택에 저장 해 둡니다.
- 프로그램이 동작을 멈추면 커널 모드로 진입하고 인터럽트 디스크립터 테이블에서 맞는 ISR의 주소를 찾습니다. 인터럽트 디스크립터 테이블이란 운영체제에 따라 인터럽트가 발생하였을 때 실행시켜야 할 ISR들의 주소들을 모아둔 테이블입니다.
- ISR을 실행시켜 인터럽트를 처리합니다. 인터럽트 서비스 루틴(ISR)이란 인터럽트를 처리하기 위하여 실행되어야 할 명령어들의 모임입니다.
- 처리가 끝나면 ISR의 반환 값과 함께 스택에 저장했던 프로그램 상태를 복구하고 프로그램을 다시 실행합니다.
open()의 결과는 파일 디스크립터를 프로그램에 반환합니다. 시스템 콜의 결과를 사용자 프로그램에 전달하기 위해서 운영체제 설계 시 선택한 방법을 사용하고 있습니다.
- Block 방식 : 반환 값을 레지스터, 크기가 크다면 메모리에 저장 해 두고 주소를 반환합니다.
- Stack 방식 : 반환 값을 프로그램 상태처럼 스택에 기록해 두고 반환합니다.
시스템 콜은 사용자가 직접 사용하기에는 불편하고 어렵기 때문에 시스템 콜 API를 통해 호출합니다.
ex) Windows API, java API, 라이브러리 함수(printf = write, malloc = brk 등)
이를 통해 사용자는 복잡한 시스템 콜, 인터럽트 과정을 알 필요 없으며 필요한 인자, 반환 값을 알면 간단하게 시스템 콜을 호출할 수 있습니다.
'스터디 > 운영체제' 카테고리의 다른 글
[운영체제] Scheduling (0) | 2021.01.22 |
---|---|
[운영체제] Context Switch (0) | 2021.01.16 |
[운영체제] 프로세스 (0) | 2021.01.09 |
[운영체제] OS 디자인과 구현 (0) | 2021.01.05 |
[운영체제] Intro (0) | 2021.01.02 |