CS/operating system

Program Execution: 프로그램의 실행(메모리 로드) (1/2)

superbono 2021. 2. 4. 14:45

1. 프로그램의 구조와 인터럽트

프로그램이 CPU에서 명령을 수행하려면 해당 명령을 담은 프로그램의 주소영역이 메모리에 올라가 있어야 한다. 프로그램의 주소 영역은 크게 code, data, stack 영역으로 구분된다.

code = 작성된 프로그램 함수들의 코드가 cpu에서 실행할 기계어 코드로 변환되어 저장된다

data = 자료구조, 전역 변수 등 프로그램이 사용하는 데이터를 저장하는 부분

stack = 함수 호출, 리턴 시 데이터(복귀할 주소 및 데이터)를 임시로 쌓았다가 썼다가

프로그램 호출 시 함수

프로그램은 처음에 메인 함수의 코드를 cpu가 수행하다가 다른 함수가 호출되면 그 함수 위치로 점프해 그 함수를 실행하고 완료한 뒤에는 원래 호출했던 함쉬 위치로 돌아온다. 이때 돌아와야 하는 지점(데이터)를 stack에 저장한다. 즉 함수가 호출되면 다음에 실행할 instruction의 메모리 위치가 바뀌게 된다. 이때 호출된 함수를 모두 수행하고 나면 기존의 수행하던 함수 위치로 돌아가는데 이때 스택에 아까 저장한 복귀 주소를 사용하여 돌아온다.

인터럽트와도 비슷하다. 사용자 프로그램이 운영체제에게 cpu 제어권을 빼앗기거나 다른 사용자 프로그램에게 timer 등의 인터럽트로 인해 cpu 제어권을 빼앗기게 될 때 다시 제어권을 얻으면 수행해야 할 주소나 데이터를 PCB에 저장한다. 이런 개념에서 PCB = stack은 비슷한 일을 한다고 생각할 수 있다. 

 

2. 컴퓨터 시스템의 작동 개요 (핵심적 부분만)

CPU는 매 시점 메모리의 특정 주소에 존재하는 intruction을 하나씩 읽어서 수행한다. 이때 program counter라고 cpu가 수행해야 할 메모리의 주소를 담고 있는 cpu 내의 레지스터(그러니까 하드웨어)가 가리키는 걸 참조한다. 

메모리에는 사용자 프로그램과 운영체제가 같이 올라가 수행된다. 이때 cpu는 pc(program counter)가 가리키는 메모리 위치의 프로그램을 수행한다. 예를 들어 pc가 메모리 주소 중 운영체제가 존재하는 부분을 가리키고 있다면 현재 운영체제의 코드를 수행 중이며, 이 경우 cpu가 커널모드에서 수행중이라고 말한다. 운영체제가 실행 중이다 라고 말하지 않는다!(왜냐면 사실상 커널은 언제나 실행중인거나 마찬가지임) 반면 사용자 프로그램이 존재하는 메모리의 위치를 가리키고 있다면 사용자 모드에서 cpu가 수행중이다 라고 말한다. 

자세한 부분은 컴퓨터 시스템의 작동 원리를 보면 흐름을 읽을 수 있을 것이다.

 

3. 프로그램의 실행

프로그램이 실행(program execution)되고 있다는 것은 시스템 차원에서 볼 때 크게 2가지 중요한 의미를 가진다.

첫 번째는 디스크에서 존재하던 실행파일이 메모리에 올라간다는 의미이고, 

두 번째는 프로그램이 cpu를 할당 받고 instruction을 수행하고 있는 상태라는 의미이다. 일반적으로 cpu를 잡을 수 있는 프로그램은 하나뿐이지만 메모리에 여러 프로그램이 올라갈 수 있어서 여러 프로그램이 동시에 실행된다고 보편적으로 말한다. 

 

파스텔톤 당근 컨셉으로 그려보았다.

 

virtual memory = 어떤 프로그램을 실행시키면 그 프로그램만의 독자적 address space가 생성된다.

swap area는 메모리 용량 한계로 메모리 연장 선에서 사용하는 저장공간. 전원 나가면 휘발되므로 의미 없다. 

파일시스템의 실행 파일을 실행하면 그게 메모리로 올라가서 프로세스가 됨 중간에 virtual memory를 거쳐 physical memory로 간다. A라는 프로그램을 실행시키면 0번지부터 시작하는 독자적 address space가 생긴다. virtual memory에 생성되는 address space 는 프로그램 종료시 사라진다. 그러나 커널은 아님! 언제나 존재한다. address space의 전부를 physical memory에 올리지 않는다. 코드의 필요한 부분(cpu의 수행에 필요한 부분)만 그때그때 올리고 그렇지 않은 부분은 disk의 swap area에 넣어둔다. 이는 여러 프로그램이 함께 사용하는 메모리 공간을 좀 더 효율적으로 사용하기 위한 방법이다. 

 

커널 주소 공간의 내용 초록색 부분은 오브젝트(하드웨어, 소프트웨어)이고 주황색 부분은 테이블(자료 구조) 관리하기 위한 자료구조이다

 

운영체제도 하나의 프로그램이므로 운영체제 커널 역시 코드, 데이터, 스택의 주소 공간 구성을 가지고 있다. 운영체제의 기능이 하드웨어 자원을 효율적으로 관리하는 것과 윗단의 응요프로그램 및 사용자에게 편리한 서비스를 제공하는 것이므로

커널의 코드 영역은 cpu, 메모리 자원을 관리하기 위한 부분과 사용자에게 편리한 인터페이스를 제공하기 위한 부분이 주를 이루고 있다. 또한 시스템 콜 및 인터럽트를 처리하기 위한 부분을 포함한다.

커널의 데이터 영역은 각종 자원을 관리하기 위한 자료구조가 들어간다. cpu나 메모리, 디스크와 같은 하드웨어 자원을 관리하기 위한 자료구조 뿐만 아니라 프로세스(process: 현재 수행 중인 프로그램)를 관리하기 위한 자료구조(PCB: 프로세스의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지하기 위한 자료구조. 프로그램 마다 생성된다)도 저장된다. 그러니까 커널의 데이터 영역에는 하드웨어와 소프트웨어를 포함하는 시스템 내의 모든 자원을 관리하기 위한 자료구조를 각각 유지하고 있다.

커널의 스택 영역은 프로세스마다 별도의 스택을 두어 관리한다. 일반 프로그램의 스택 영역과 마찬가지로 함수 호출 시 복귀 주소를 저장하기 위한 용도로 사용되지만 프로세스마다 별도의 스택을 둔다는 점이 차이점이다. 왜냐하면 프로세스가 함수를 호출할 때 자기 주소 내부에 정의된 함수를 호출하면 자신의 스택에 복귀 주소를 저장하지만, 프로세스가 특권 명령을 수행하려고 커널에 정의된 시스템 콜을 호출하고 시스템 콜 내부에서 다른 함수를 호출하는 경우 그 복귀 주소는 커널 내의 주소가 되어 사용자 프로그램의 스택과는 별도의 저장공간이 필요하게 되기 때문이다. 또한 커널은 일종의 공유 코드로 모든 유저 프로그램이 시스템 콜을 통해 커널의 함수를 접근할 수 있으므로 일관성 유지를 위해 커널 내에 별도의 스택을 두게 되는 것이다. 프로그램이 자기 자신의 코드 내에서 함수호출 및 복귀 주소를 유지하기 위해서는 자기 주소 공간 내의 스택을 사용하고, 시스템 콜이나 인터럽트 등으로 운영체제의 코드가 실행되는 중에 함수 호출이 발생한 경우 커널 스택을 사용하게 되는 것이다. 

프로그램 내의 함수 호출 시 스택에 복귀 주소를 저장하지만 시스템 콜이나 인터럽트 등으로 cpu의 수행 주체가 운영체제로 바뀌게 되면 복귀 정보를 스택이 아닌 pcb에 저장한다. 자세한 내용은 문맥 교환(context switch)에서 다루도록 하겠다. 커널 역시 함수 구조로 이루어져 있으므로, 커널의 코드가 수행되는 도중에 이루어지는 함수 호출은 커널 스택을 사용하게 되는 것이다. 한편 커널스택은 프로세스마다 별도로 두고 있어, 커널 내에서 이루어지는 함수 호출은 직전에 cpu를 가지고 있던 프로세스의 커널 스택을 사용하게 된다.