시스템 콜
시스템 콜은 컴퓨터 프로그램이 운영체제가 제공하는 서비스를 제공 받을 때 사용하는 인터페이스이다.
대부분의 CPU는 커널 모드(kernel mode)와 사용자 모드(user mode)를 갖고 있다.
CPU 내부에는 PSW (Program Status Word) 라고 하는 레지스터가 있고, 이 레지스터의 여러가지 비트들 중 하나가 CPU의 모드를 결정한다.
CPU가 커널 모드로 동작하게 되면, CPU에 정의된 instruction set 에 있는 모든 명령어를 실행할 수 있게 되고, 하드웨어의 모든 기능을 사용할 수 있게 된다.
그리고 운영체제는 커널모드에서 동작한다. 따라서 운영체제는 모든 하드웨어 기능을 사용할 수 있다.
반면 우리가 흔히 사용하는 프로그램들은 사용자 모드에서 동작한다.
사용자 모드에서는 instruction set 의 일부 명령어만 사용이 가능하고, 하드웨어의 일부 기능에만 접근할 수 있다.
(보통은 IO 기능) 그리고 memory protection 과 같은 기능에는 접근할 수 없다.
그래서 우리가 사용하는 프로그램들이 만약 커널모드에서 동작하는 기능을 사용하고자 한다면,
운영체제가 제공하는 서비스를 통해 사용해야 하며, 이때 운영체제와 소통하는 수단이 '시스템 콜' 이다.
시스템 콜을 호출하게 되면 기존 프로그램의 실행이 멈추고 커널로 트랩하게 되며 (커널 모드로 전환) 운영체제가 실행된다.
커널에 들어가려면 CPU가 명령어 중 trap instruction 을 실행해야 하고, 이 명령어가 실행되면 CPU의 모드가 유저모드에서 커널모드로 변경된다. 그리고 커널 영역의 특정 위치로 점프가 일어나고, 그 위치에서부터 운영체제가 실행되는 것이다.
운영체제가 자신이 맡은 일을 끝내면 CPU 모드는 다시 유저 모드로 돌아가고, 제어권이 운영체제에서 기존의 사용자 프로그램으로 되돌아간다.
이렇게 소프트웨어 적으로 발생하는 트랩 외에도 하드웨어에 의해 발생되는 트랩도 있다.
대표적인 예시는 0으로 나누는 행위를 할 때 발생하는 트랩으로, 예외 상황에 대해 경고하는 역할로 호출된다.
(정리하면 트랩 인스트럭션이 호출되면 CPU 모드를 커널 모드로 바꾸고, 운영체제 코드로 흐름이 점프하여 운영체제가 실행된다.)
시스템 콜은 보통 우리가 직접 호출하기보다, 시스템 콜을 호출해주는 프로시저를 호출해서 시스템 콜을 사용한다.
그리고 이런 프로시저들이 모여있는 라이브러리가 보통 언어 단에서 제공된다.
이런 프로시저 호출은 단순 함수나 프로시저 콜과는 다르게, CPU 모드를 커널 모드로 변경시킨다는 점에서 차이점이 있다.
예를 들어 하드디스크에 저장되어있는 파일을 하나 읽고 싶다면, read 라는 시스템 콜이 필요하다.
우리는 이 시스템 콜을 직접 호출하지 않고 C언어와 같은 언어에서 제공하는 프로시저를 호출해서 파일을 읽어온다.
즉, 이런 함수를 대신 실행하면 내부적으로 알아서 시스템 콜을 호출하는 것이다.
그림으로 보면 위와 같다.
메모리에는 이렇게 커널 영역이 있고, 유저 영역이 있는데 언어가 제공하는 함수를 호출하면 함수의 매개변수를 스택 영역에 할당해서 쌓아둔 뒤, read() 라는 프로시저를 호출한다. 그러면 이미 정의된 라이브러리 프로시저가 실행되면서 read 라는 시스템 콜에 해당하는 숫자를 레지스터에 저장한 뒤 kernal로 트랩하게 되고, 커널모드로 CPU가 바뀌면 커널 영역에 있는 운영체제 코드가 실행되기 시작한다.
운영 체제 내에는 시스템 콜 번호마다 각 시스템 콜을 처리해주는 시스템 콜 핸들러 함수 주소가 들어있는 테이블이 있다.
이 테이블에서 read 시스템 콜 번호를 인덱스로 접근하여 read 시스템 콜 핸들러를 테이블에서 찾아 호출한다.
그러면 프로그램 카운터가 바뀌어 핸들러 함수의 기능을 따라 파일을 읽는 동작을 처리한 뒤, 유저모드로 돌아와 기존의 언어에서 제공하는 프로시저 함수로 되돌아온다. 이 프로시저의 함수 호출이 끝나면 다시 우리가 작성한 코드로 돌아오고 스택 메모리가 반환된다.
이처럼 UNIX 시스템에 있는 시스템 콜에는 각 시스템 콜에 대응하는 프로시저가 있어서, 프로그래밍 언어에서 특정 시스템 콜을 활용할 때는 해당하는 프로시저를 호출하여 시스템 콜을 호출한다.
UNIX의 표준안인 POSIX 에는 대략 100개 정도의 라이브러리 프로시저를 정의해두었다.
각각의 프로시저들은 파일관리, 프로세스 관리, 디렉토리 관리, 메모리 관리, 입출력 등의 서비스를 제공한다.
이 이미지는 POSIX 시스템에서 제공하는, 특정 시스템 콜을 호출하는 프로시저들의 명세 일부를 나타낸 것이다.
대표적인 것들은 부모 프로세스와 동일한 자식 프로세스를 생성하는 fork(), 파일을 읽어서 버퍼에 데이터를 담는 read(), 1970년 1월 1일 이후의 시간을 단위 초로 환산하여 보여주는 time() 과 같은 프로시저들이 있다.
'CS > 운영체제' 카테고리의 다른 글
[운영체제] 6. 프로세스 동기화 (4) - 식사하는 철학자 문제 (2) | 2024.10.19 |
---|---|
[운영체제] 5. 프로세스 동기화 (3) - Message Passing, Barrier (0) | 2024.10.19 |
[운영체제] 4. 프로세스 동기화 (2) - 세마포, 뮤텍스, 모니터 (0) | 2024.10.19 |
[운영체제] 3. 프로세스 동기화 (1) - 상호배제와 Busy Waiting (2) | 2024.10.17 |
[운영체제] 2. 프로세스 (5) | 2024.10.16 |