앞장에서 운영체제는 여러 개의 가상의 CPU가 존재한다는 환상을 제공한다고 설명하였다.
대표적인 가상화 방법으로 시분할(Time Sharing)기법이 있다.
시분할은 하나의 프로세스를 실행하고 멈추고, 다른 프로세스를 실행하는 작업을 반복하며 마치 여러 개의 CPU가 존재하는 것처럼 보이게 한다.
따라서 원하는 수 만큼의 프로세스를 동시에 실행할 수 있지만 CPU를 공유하기 때문에 각 프로세스의 성능이 낮아지고 느려진다.
프로세스는 실행중인 프로그램이다.
구성 요소는 다음과 같다.
메모리(주소 공간) : 명령어, 데이터
레지스터 : 프로그램 카운터(PC), 스택 포인터(SP), 일반 레지스터
CPU는 메모리에 있는 데이터만 사용이 가능하다. 따라서 하드디스크와 같은 저장 공간의 메모리를 가져와야 한다.
그러나 메모리만 존재한다면 아무일도 일어나지 않으며 CPU가 명령어를 꺼내어 데이터를 읽어 레지스터에 넣어야 실행이 된다.
요약) 실행 가능한 포맷으로 작성, 로딩 -> 지역변수, 함수 매개변수, 복귀주소 등의 스택 할당 -> 힙 할당 -> 초기화 -> main으로 jump
실행(Running) : CPU가 실행 중
준비(Ready, 실행 대기) : 실행할 준비가 다 되어 있음. CPU 사용 차례를 기다리고 있음
대기(Blocked) : 다른 사건이 발생하기를 기다리고 있음, 사건) 입출력 완료, 메시지 도착, 약속 시간, ex)scanf, printf
PCB(Process Control Block)
운영체제가 관리하는 핵심 자료구조들
현실에서 프로세스는 운영체제가 만든다.
어떠한 프로세스가 요청했기 때문에 프로세스를 만든다.
최초의 프로세스는 운영체제가 알아서 만든다.
최초의 프로세스는 Windows : winload.exe, Linux : init
시스템 호출을 통해 프로세스 생성을 요청한다. Windows : CreateProcess, Linux : fork, exec, clone
앞서 설명했듯이 운영체제는 실제 CPU를 시분할(Time Sharing)방식으로 나눠 사용한다.
그러나 가상화 기법을 구현하는데 몇가지 문제가 있는데
우선 성능 저하이며 이를 해결하기 위해 시스템에 큰 오버헤드를 주지 않으며 가상화를 구현하는 방식이다.
두번 째는 제어 문제로 CPU에 대한 통제를 유지하며 프로세스를 효율적으로 실행할 수 있는 방법이다.
제어권을 상실한 프로세스가 영원히 실행을 계속하며 컴퓨터를 장악하고, 접근하면 안되는 정보에 접근하도록 두면 안된다.
따라서 제어권을 유지하며 성능저하가 없도록 운영체제를 구축해야 하는 것이 핵심적 과제이다.
운영체제 엔지니어들은 프로그램을 빠르게 실행하기 위해 제한적 직접 실행이라는 기법을 개발하였다.
제한적 직접 실행은 프로그램을 CPU상에서 그냥 직접 실행시키는 것이다.
운영체제는 프로그램을 실행하기 시작할 때, 프로세스 목록에 해당 프로세스 항목을 만들고, 프로그램 메모리를 할당하며, 디스크에서 프로그램을 꺼내어 탑재하고, 초기화하며 main으로 점프하여 사용자 코드를 실행한다.
! 그러나 이러한 방법은 몇 가지 문제가 있다.
프로그램은 제한 없이 뭐든지 할 수 있어 디스크의 파일을 지우거나 컴퓨터를 태울 수 있다.
OS는 프로그램 실행을 그저 바라보기만 해야 하고, "일반 라이브러리"처럼 호출 당해야 한다.
프로그램을 제어하지 못하는 운영체제는 그저 단순한 라이브러리에 불과하다.
다음으로 이러한 문제점에 대하여 자세히 알아보자
만약 프로세스가 다음과 같은 하면 안되는 동작을 한다면?
만약 프로세스가 원하는 대로 해준다면 프로세스는 전체 디스크를 읽고 쓸 수 있어 접근 권한을 검사하는 파일 시스템은 아무런 의미가 없게 된다.
따라서 사용자 모드(User mode), 커널 모드(Kernel mode)가 도입되었다.
이러한 방식으로 우리는 디스크 입출력과 같은 명령을 실행할 때, 시스템 콜을 사용하여 파일 시스템에 접근, 프로세스 생성 및 제거 등을 한다.
따라서 시스템 콜을 통해 사용자 모드의 문제점을 해결할 수 있다.
시스템 콜
Trap
Trap은 시스템 콜을 실행하기 위한 특수 명령어이다. 트랩 테이블에 정해진 주소 안으로 jump할 수 있고 동시에 커널 모드로 상향 조정한다.
커널 모드로 진입하게 되면 운영체제는 모든 명령어를 실행할 수 있고 이를 통해 프로세스가 요청한 작업을 처리할 수 있다.
Return-from-trap
Return-from-trap명령어는 특권 수준을 다시 사용자 모드로 하향 조정하며 호출한 사용자 프로그램으로 되돌아 간다.
다음 그림은 제한적 직접 실행을 요약하여 나타낸 것이다.
두 번째 문제점은 프로세스간 전환이다. 프로세스간 전환은 간단해야 하고, 운영체제는 실행 중인 프로세스를 계속 실행할지, 멈추고 다른 프로세스를 실행할 것인지 결정해야 한다. 그러나 직접 실행으로 CPU에서 프로세스가 실행중이라는 것은 운영체제는 실행중이지 않다는 것을 의미한다. 그렇다면 어떻게 CPU를 운영체제가 다시 획득하여 프로세스를 전환할 수 있을까
여기에는 두 가지 방식이 있는데 첫 번째로 협조 방식이다.
위 무한루프와 같은 경우 컴퓨터를 재부팅 할 수 밖에 없다. 그러면 어떻게 CPU 제어권을 다시 운영체제가 획득할 수 있을까
시스템 콜을 협조로 하든, 타이머 인터럽트를 통해 강제로 하든, 운영체제가 제어권을 다시 획득하면 현재 실행중인 프로세스를 계속 실행할 것인지, 다른 프로세스로 전환할 것인지를 결정해야 한다. 이 결정은 운영체제의 스케쥴러에 의해 결정된다.
다른 프로세스로 전환된다면 운영체제는 문맥 교환(Context switch)을 한다.
문맥 교환(Context Switch)