시스템 콜은 응용프로그램에서 커널에 작성된 함수를 실행하는 기법으로, 커널과 응용프로그램 사이의 인터페이스다.
즉, 커널 모드의 기능을 사용자 모드에서 사용할 수 있게 해준다.
일반적으로 사용자가 사용하는 프로그램은 응용 프로그램이다. 사용자 모드*에서는 파일 읽기 및 쓰기/ 메모리 할당 및 해제/ 프로세스 생성 및 관리 등의 작업을 구현할 수 없다. 즉, 응용 프로그램은 커널이 있는 메모리에 접근할 권한이 없기 때문에, 커널에 작성된 함수를 직접 호출할 수 없다. 커널 모드*로 전환된 후 수행할 수 있는 권한이 생긴다.
운영체제는 응용프로그램을 대신하여 커널 함수에 접근할 수 있는 시스템 콜 라이브러리를 제공한다. 응용프로그램이 커널의 기능을 활용하려면 시스템 콜 라이브러리에 들어 있는 시스템 콜 함수(fork(), exit(), open(), write() 등)를 호출하면 된다.
이러한 함수를 통해 응용프로그램이 커널 코드를 불러 활용할 수 있다. 시스템 콜은 응용프로그램이 커널 코드를 호출할 수 있는 유일한 방법이다.
시스템 콜을 trap
이라고도 한다. 시스템 콜이 진행되는 과정을 'trap을 실행한다.'고 한다. trap을 실행하면, 모드비트*가 0으로 전환된다.
*사용자 모드: PC 레지스터가 사용자 프로그램이 올라가 있는 메모리 위치를 가리키고 있을 때 현재 사용자 프로그램을 수행중이라고 하며, CPU가 사용자 모드에서 수행중이라고 한다.
*커널 모드: PC 레지스터가 운영체제가 존재하는 부분을 가리키고 있다면 현재 운영체제의 코드를 수행중이라고 하며 CPU가 커널 모드에서 수행중이라고 한다.
*모드 비트: 값에 따라 현재 운영체제의 모드를 알 수가 있다. 0: 커널 모드, 1: 사용자 모드
우선, 메모리를 사용자 공간과 커널 공간으로 나누어 사용하는 이유는 응용프로그램으로부터 커널 코드와 데이터를 지키기 위해서이다. 사용자 응용프로그램이 실수로 혹은 악의적인 개발자가 고의적으로, 커널 코드와 데이터를 훔쳐보거나 훼손하는 것을 막기 위해서이다. 커널이 개방되어 있으면 바이러스 침범, 시스템 훼손, 시스템 중단 등 심각한 문제가 발생할 수 있다.
따라서, 응용프로그램은 시스템 콜을 통해서만 커널 공간에 접근 할 수 있다.
사용자 모드 | 커널 모드 | |
---|---|---|
CPU의 메모리 액세스 범위 | 사용자 공간에 국한. 커널 공간 액세스 불가 | 커널 공간을 포함한 모든 메모리 공간 |
CPU의 하드웨어 액세스 여부 | 불가 | 모든 하드웨어 액세스 가능 |
CPU가 처리 가능한 명령 | 특권 명령을 제외한 모든 CPU 명령 | 특권 명령을 포함한 모든 CPU 명령 |
오류 발생 시 처리 | 사용자 프로그램만 실행 종료. 시스템이 종료되지 않으므로 안전 | 시스템에 심각한 오류가 발생한 것으로 시스템 종료 |
-
시스템 콜 함수들은 여러 기능으로 나누어진다.
-
각 시스템 콜에는 번호가 부여되고, 시스템 콜 인터페이스는 시스템 콜 번호와 시스템 콜 핸들러 함수 주소로 구성된 시스템 콜 테이블을 가진다.
-
시스템 콜 함수가 실행되면 시스템 콜 핸들러가 실행되고, 운영체제는 시스템 콜 번호를 분석하여 해당 커널 함수를 실행시킨다.
-
작업이 완료되면 CPU에게 인터럽트를 발생시켜 수행이 완료 되었음을 알린다.
-
예시 open()의 호출
# in.txt에 있는 파일 내용과 같은 내용을 복사하여 out.txt 파일을 만드는 것
cp in.txt out.txt
리눅스 터미널에 위와 같은 명령어를 입력하면, 다음과 같은 시스템 콜이 발생한다.
- 사용자로부터 명령을 입력 받을 때 I/O 시스템 콜이 발생한다.
- 이후 'cp' 프로그램을 실행하면 먼저
in.txt
파일의 접근 가능성 및 권한 확인을 위한 I/O 시스템 콜이 발생한다. (파일이 존재하고, 읽기 권한이 있는지 확인)- 접근이 불가능하다면 에러를 발생시킨 후 프로그램이 종료된다.
- 접근 가능하다면 복사한 파일을 저장하기 위해
out.txt
파일명이 있는지 검사하기 위한 I/O 시스템 콜이 발생한다.
범주 | 기능 | Windows | Linux |
---|---|---|---|
프로세스 컨트롤 | 프로세스 실행 | CreateProcess() | execlp(), execv() |
프로세스 종료 | ExitProcess() | exit(), kill() | |
프로세스 생성 | CreateProcess() | fork(), clone() | |
이벤트, 시간동기 | WaitForSingleObject() | wait() | |
파일 관리 | 파일 생성/삭제 | CreateFile() | open() |
파일 열기/닫기 | CloseHandle() | close() | |
파일 읽기/쓰기 | ReadFile()/WriteFile() | read()/write() | |
디바이스 관리 | 장치로 읽기/쓰기 | ReadFile()/WriteFile() | read()/write() |
정보 관리 | 현재 프로세스의 PID 반환 | GetCurrentProcessId() | getpid() |
시간 지정 | SetTimer() | alarm() | |
시간 대기 | Sleep() | sleep() | |
통신 | 파이프 생성 | CreatePipe() | pipe() |
보안 | 퍼미션 설정 | SetFileSecurity() | chmod() |
함수 호출 | 시스템 콜 | |
---|---|---|
메모리 영역 | 사용자 영역의 코드에서 사용자 영역의 함수 호출 | 사용자 영역의 코드에서 커널 함수 호출 |
CPU 실행 모드 | 사용자 모드 | 사용자 모드에서 커널 모드로 전환 |
비용 | 함수 호출에 따른 비용 | 커널 모드로 전환하는 등 함수 호출에 비해 큰 비용 |