● 프로그램의 실행 (메모리 Load)
실행 파일은 하드 디스크에 저장이 되고, 실행을 시키면 가상 메모리 단계를 거쳐 물리적 메모리에 올라가 프로세스가 된다.
프로그램을 실행시키면 자기 자신만의 독자적인 주소 공간이 만들어지며, 주소 공간은 Stack, Data, Code영역으로 구성되어 있다.
- 코드 영역
메모리의 코드 영역은 실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고도 부른다.
CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리하게 된다.
- 데이터 영역
메모리의 데이터 영역은 프로그램의 전역 변수와 정적 변수가 저장되는 영역이다.
데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.
- 스택 영역
메모리의 스택 영역은 함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역이다.
스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다.
이렇게 스택 영역에 저장되는 함수의 호출 정보를 스택 프래임(stack frame)이라고 한다.
커널은 부팅하는 시점부터 메모리에 항상 올라가 있지만, 사용자 프로세스는 메모리에 주소 공간이 생겼다가 프로그램을 종료시키면 사라진다.
프로그램이 생성되었을 때 만들어진 주소 공간을 물리적 메모리에 통째로 다 올려놓게 되면 메모리 낭비로 이어지기 때문에 당장 필요한 부분만 물리적 메모리에 올린다.
경우에 따라서 물리적 메모리에 올린 것을 보관하고 있어야 하는 정보들은 디스크에 따로 내려놓게 되는 데, 그 공간을 swap area라고 한다.
각 프로그램마다 0번지부터 시작하는 가상 메모리가 존재한다.
실제 올라가는 물리적인 메모리의 주소와 가상 메모리의 주소는 서로 다르기 때문에 메모리 주소 변환을 해줘야 한다.
운영체제가 하는 게 아니라 하드웨어의 지원을 받아 주소 변환 계층에서 주소 변환을 한다. (메모리 관리에서 더 다룰 내용)
가상 메모리 (Virtual Memory)
메모리가 실제 메모리보다 많아 보이게 하는 기술
- 프로그램 실행 시, 필요한 부분만 메모리에 올라가며, 나머지는 디스크(보조기억장치)에 남게 됨.
- 디스크가 RAM의 보조기억장치처럼 동작
- 빠르고 작은 기억장치(RAM) + 크고 느린 기억장치(디스크) = 하나의 크고 빠른 기억장치(가상 메모리)
- 가상 메모리를 구현하기 위해서는 메모리 관리 하드웨어(MMU:Memory Management Unit)가 필요
어떤 프로세스가 실행될 때 메모리에 해당 프로세스 전체가 올라가지 않더라도 실행이 가능하다는 점에 착안하여 고안되었다.
File system & swap area
File system과 swap area는 둘 다 하드 디스크인데, File system은 전원이 나가더라도 파일 내용이 저장되어야 하니까 정보가 날아가지 않는다.
전원이 꺼진다는 것은 프로세스가 종료되어 메모리에 있는 내용도 날아가기 때문에 swap area의 데이터는 전원이 꺼지면 데이터가 날아간다.
두 영역의 용도가 다르기 때문에 관리하는 방법도 다르다.
- File system : 비휘발성의 용도로 사용. 전원이 나가도 데이터 유지
- swap area : 메모리 용량의 한계로 메모리 연장 공간으로 사용
● 커널 주소 공간의 내용
커널도 하나의 프로그램이기 때문에 Code, Data, Stack의 주소 공간으로 구성되어 있다.
- 코드 영역
운영체제는 자원을 효율적으로 관리한다. 그러기 위한 코드들이 코드 영역에 존재한다.
사용자에게 편리한 인터페이스를 제공하거나, 인터럽트마다 어떤 일을 처리해야 하는지, 소프트웨어 인터럽트 (system call) 또는 하드웨어 인터럽트가 발생하면 어떤 일을 처리해야 하는지에 대한 코드들이 함수 형태로 구현되어 있다.
- 데이터 영역
운영체제가 사용하는 여러 자료구조들이 저장되어 있다. 프로세스를 관리해야 하니까 각 프로그램들을 관리하기 위한 자료구조(PCB)를 포함한다.
CPU, 메모리, 디스크와 같은 하드웨어들을 직접 관리하고 통제하기 위해 각각의 종류마다 자료구조를 하나씩 만들어서 관리한다.
(커널 안의 사각형은 자료구조를, 육면제는 하드웨어를 의미)
→ 운영체제가 모든 하드웨어, 프로세스들을 관리하기 위한 자료구조를 포함한다.
- 스택 영역
운영체제의 커널은 여러 사용자 프로그램들의 요청에 따라 불러 쓸 수 있다.
커널로 들어오기 전에, 어떤 사용자 프로그램에 의해 호출되었는지에 따라 프로세스별로 별도 커널의 스택이 사용된다. 그림에서 보면, 프로세스마다 커널 스택을 따로 그려 놓았다.
사용자 프로그램이 사용하는 함수
함수에는 서로 다른 세 가지가 종류가 있다.
- 사용자 정의 함수
자신의 프로그램에서 정의한 함수이다.
- 라이브러리 함수
자신의 프로그램에서 정의하지 않고 갖다 쓴 함수로, 누군가 유용한 기능을 만들어 놓아서 내가 사용만 하는 함수이다.
자신의 프로그램의 실행파일에 포함되어 있다
- 커널 함수
운영체제 프로그램의 함수이다. 내 프로그램 안에 들어있는 함수가 아니라 커널 코드 안에 들어있는 함수이다.
내 프로그램 안에는 함수에 대한 정의가 없으며, 그냥 커널에 있는 함수를 호출하는 것이다. 커널 함수의 호출 = 시스템 콜
1번과 2번 둘 다 어찌 됐건 컴파일하여 실행 파일을 만들게 되면, 내 실행 파일 안에 함수들이 모두 포함되어 있다. 반면에 커널 함수는 운영체제 안에서 정의된 함수이기 때문에 프로그램 안에서 시스템 콜을 통해서만 가져다 쓸 수 있다.
사용자 프로세스의 코드 영역에 있는 함수를 호출하면 해당 프로세스의 주소 공간 안에서 점프를 하여 함수가 실행되는 것이다. 만약 커널 함수를 호출(시스템 콜)을 한다면 해당 함수는 운영체제(OS)에 있으니 메모리 주소를 점프하지 못한다.
※ 일반적으로 말하는 메모리 주소를 점프한다는 말은 물리적 메모리에서의 점프가 아니라 논리적(virtual) 메모리 주소상에서의 점프를 말한다.
System call을 할 때에는 Interrupt 라인을 세팅하여 CPU 제어권이 운영체제로 넘어가게 함으로써 커널 함수를 실행한다.
● 프로그램 실행 단계
프로그램은 생성되어서 종료될 때까지 User mode와 Kernel mode를 반복하다가 main 함수가 끝나면 프로그램이 종료된다.
아래 이미지는 A라는 프로그램이 실행될 때부터 종료가 될 때까지의 모습을 도식화하여 나타낸 그림이다.
프로그램이 실행되고 있을 때, CPU를 잡고 있으면 보통 User mode라고 한다. 프로그램이 사용자 정의 함수를 호출해서 사용할 때에도 User mode로 실행된다.
User mode에서 동작하다가 System Call을 하게 되면, 커널 주소 공간에 있는 코드(함수)가 실행되기 때문에, 이 때는 CPU는 커널 모드에서 동작한다.
System Call이 끝나면 다시 프로그램 A에게 CPU 제어권이 넘어가고 프로그램 A의 주소 공간에 있는 코드를 실행한다.