[OS] 프로그램 구조와 실행
Updated:
프로그램 구조와 실행
1. 프로그램의 구조와 인터럽트
프로그램이 CPU에서 명령을 수행하려면 해당 명령을 담은 프로그램의 주소 영역이 메모리에 올라가 있어야 한다. 이때 프로그램의 주소 영역은 크게 세가지로 구분된다.
- 코드(code)영역 : 작성된 프로그램 함수들의 코드가 CPU에서 수행할 수 있는 기계어(machine instruction) 형태로 변환되어 저장되는 부분이다.
- 데이터 영역(data)영역 : 전역 변수(global variable)등 프로그램이 사용하는 데이터를 저장하는 부분이다.
- 스택(stack)영역 : 함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시로 저장하는 데에 사용되는 공간이다.
일반적으로 프로그램 내에서 발생되는 함수호출에 필요한 복귀 주소는 각 프로그램의 주소 공간 중 스택 영역에 보관한다. 반면 인터럽트 때문에 CPU를 빼앗긴 위치는 운영체제가 관리하는 프로세스 제어블록(PCB)에 저장된다.
2. 컴퓨터 시스템의 동작 개요
-
CPU는 매 시점 메모리의 특정 주소에 존재하는 명령을 하나씩 읽어와 그대로 실행할 뿐이다. 이때 CPU가 수행해야 할 메모리 주소를 담고 있는 레지스터를 프로그램 카운터(Program Counter:PC)라고 한다.
-
CPU는 프로그램 카운터가 가리키는 메모리의 위치의 프로그램을 수행한다. 프로그램 카운터가 운영체제가 존재하는 메모리를 가리키고 있다면 운영체제의 코드를 수행중이며, 이 경우 CPU가 ‘커널모드’에서 수행중이라고 이야기 한다. 반대로 사용자 프로그램이 존재하는 메모리 위치를 가리키고 있다면 사용자 프로그램이 수행 중이며, ‘사용자모드’에서 CPU가 수행되고 있다고 이야기한다.
-
사용자 프로그램은 스스로 특권명령을 수행할 수 없으므로 운영체제에게 특권명령의 대행을 요청한다. 이러한 서비스 요청이 ‘시스템 콜’이다. 사용자 프로그램이 시스템 콜을 하게 되면 운영체제는 사용자 프로그램의 코드가 아닌 커널 영역에 정의된 시스템 콜 처리 코드를 수행하게 된다.
-
인터럽트를 발생시키기 위해 주변장치는 ‘인터럽트 라인’을 세팅하고, CPU는 매번 명령을 수행한 직후 인터럽트 라인을 체크해 서비스 요청이 들어왔는지 확인한다.
3. 프로그램의 실행
-
프로그램이 실행되고 있다는 것은 컴퓨터 시스템 차원에서 볼때 크게 두가지 중요한 의미를 가진다. 첫 번째는 디스크에 존재하던 실행파일이 메모리에 적재된다는 의미이고, 두 번째는 프로그램이 CPU를 할당받고 명령을 수행하고 있는 상태라는 의미이다.
-
프로그램의 주소 공간 중 당장 CPU의 수행에 필요한 부분은 메모리에 올려놓고 그렇지 않은 부분은 디스크 중 메모리의 연장 공간으로 사용되는 스왑 영역에 내려놓는 방식으로 운영된다.
-
현재 수행 중인 프로그램을 ‘프로세스(process)’라고 부르고, 커널의 데이터 영역 내에는 각 프로세스의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지하기 위한 자료구조인 PCB를 두고 있다.
-
프로그램 내의 함수호출 시 해당 프로그램의 스택에 복귀 주소를 저장하지만, 시스템 콜이나 인터럽트 발생으로 CPU의 수행 주체가 운영체제로 바뀌는 순간에는 직전에 수행되던 프로그램의 복귀 정보를 스택이 아닌 PCB에 저장한다.
-
시스템 콜, 인터럽트 등 특권명령으로 인해 운영체제의 코드(커널 코드)가 실행되는 중에 함수호출이 발생할 경우 직전에 CPU를 가지고 있던 프로세스의 ‘커널 스택’을 사용하게 된다.
4. 사용자 프로그램이 사용하는 함수
프로그램이 사용하는 함수는 크게 사용자 정의함수와 라이브러리 함수, 커널함수의 세 가지로 구분해볼 수 있다.
- 사용자 정의 함수 : 프로그래머 본인이 직접 작성한 함수
- 라이브러리 함수 : 이미 누군가 작성해놓은 함수를 호출만 하여 사용하는 함수
위 두 함수는 프로그램이 실행될 때에 해당 프로세스의 주소 공간에 포함되며, 또한 함수 호출 시에도 자신의 주소공간에 있는 스택을 사용하게 된다.
- 커널 함수 : 운영체제 커널의 코드에 정의된 함수이다. 커널함수의 종류에는 시스템 콜 함수와, 인터럽트 처리 함수가 있다. 이와 같은 커널 함수는 사용자 프로그램 주소 공간에 그 코드가 존재하는 것이 아니라 운영체제 커널의 주소 공간에 코드가 정의된다.
일반적인 함수 호출은 사용자 프로그램 내에 존재하는 코드를 실행하는 것이고 시스템 콜은 사용자 프로그램이 아닌 운영체제라는 별개의 프로그램 CPU를 넘겨서 실행하는 것이다. CPU를 운영체제에 넘기기 위해 시스템 콜은 인터럽트와 동일한 메커니즈, 즉 CPU의 인터럽트 라인을 세팅하는 방법을 사용한다.
5. 인터럽트
-
CPU는 매번 프로그램 카운터가 가리키는 지점의 명령을 하나씩 수행하고 나서, 다음 명령을 수행하기 직전에 인터럽트 라인이 세팅되어 있는지 체크한다. 인터럽트 라인 체크를 통해 인터럽트가 발생했으면 CPU는 현재 수행중이던 프로세스를 멈추고 운영체제의 인터럽트 처리루틴으로 이동해서 인터럽트 처리를 수행한다.
-
현재 처리 중인 인터럽트보다 더 높은 우선순위의 인터럽트가 발생한다면 현재 처리 중인 인터럽트 코드의 수행 지점을 저장하고 우선순위가 높은 인터럽트를 처리하게 된다. 인터럽트 처리가 끝나면 저장된 주소로 복귀해 이전에 수행하던 인터럽트 처리 코드를 마저 수행하게 된다.
6. 시스템 콜
- 시스템 콜은 커널이라는 다른 프로그램의 주소 공간에 존재하는 함수를 호출하는 것을 말한다.
- 사용자 프로그램이 입출력 요청을 위해 시스템 콜을 할 경우, CPU를 다른 프로세스에게 이양하게 된다. 입출력이 완료되면 해당 컨트롤러가 인터럽트를 발생시킨 시점부터 다시 CPU를 얻을 수 있는 자격을 부여받게 된다.
7.프로세스의 두 가지 실행 상태
-
프로그램에서 다양한 함수호출을 하며 실행되는 모드로 ‘시용자 모드’와 ‘커널 모드’ 두가지가 있다. 프로그램이 사용자 정의함수나 라이브러리 함수를 호출할 때에는 모드의 변경 없이 사용자모드에서의 실행을 지속하게 되고, 스시템 콜을 하는 경우에는 커널모드로 진입해 커널의 주소 공간에 정의된 함수를 실행하게 된다.
-
시스템 콜의 실행이 끝나면 다시 사용자 모드로 복귀해서 시스템 콜 이후의 명령들을 계속 실행한다. 프로그램의 실행이 끝날 때에는 커널 모드로 진입해 프로그램을 종료한다.
참고
- 서적 ‘운영체제와 정보기술의 원리’
Leave a comment