[운영체제] 4. 프로그램의 구조와 실행
by 콰이엇반효경 교수님의 "운영체제와 정보기술의 원리" 책을 학습하고 정리한 글입니다.
1. 프로그램의 구조와 인터럽트
1-1. 프로그램의 주소 영역
📌 코드 (code)
사용자 프로그램 함수들의 코드가 CPU에서 수행할 수 있는 명령어(machine instruction) 형태로 변환하여 저장하는 부분
📌 데이터 (data)
전역 변수(global variable) 등 프로그램이 사용하는 데이터를 저장하는 부분
📌 스택 (stack)
함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시 저장하는 공간
1-2. 프로그램 실행 단계
예를 들어, X 함수가 수행 중에 Y 함수를 호출한 경우를 생각해보자. X 함수에서 Y 함수를 호출한 지점을 스택에 저장해놓았다가 Y 함수가 수행된 후 스택에 저장된 주소로 돌아와 코드를 계속 수행하게 된다.
즉, 함수가 호출되면 다음에 실행할 명령의 메모리 위치가 변경된다. 이는 CPU가 명령을 순차적으로 수행하다가 호출한 함수의 위치로 이동하여 명령을 실행하기 때문이다. 호출한 함수를 모두 수행하고 나면 스택에 저장되어 있는 복귀 주소를 사용하여 원래 위치로 돌아간다.
✍🏻 인터럽트의 동작 원리 또한 유사하다!
A 프로그램이 CPU를 할당받고 명령을 수행하고 있는데, 인터럽트가 발생하면 프로그램 A는 현재 수행 중인 명령의 위치를 저장한다. 이후, 운영체제 내부 코드인 인터럽트 처리 루틴으로 인터럽트 처리를 하고 돌아와 프로그램 A 이전 작업부터 수행을 이어가게 된다. 다만 일반적으로 프로그램 내에서 발생하는 호출에 필요한 복귀 주소는 각 프로그램의 주소 공간 중 스택 영역에 보관한다.
하지만, 인터럽트 때문에 CPU를 빼앗긴 위치는 운영체제가 관리하는 PCB(프로세스 제어 블록)에 저장한다. PCB는 인터럽트 발생 시점에 그 프로그램의 어느 부분까지 실행했는지를 저장하며, 인터럽트 처리 후 PCB에 저장된 주소를 복원시켜 원래 수행하던 일을 재개한다.
2. 컴퓨터 시스템의 작동 개요
2-1. CPU 이해하기
흔히 CPU를 '컴퓨터의 두뇌'라고 부르는 것처럼 빠른 속도로 처리하는 계산 능력을 가지고 있다. 하지만 어떤 작업을 수행해야 하는지는 스스로 결정하지 못한다. 즉, 매 시점 메모리의 특정 주소에 존재하는 명령을 하나씩 읽어와 그대로 실행하게 된다. 이때 수행해야 할 메모리 주소를 담고 있는 레지스터를 프로세스 카운터(PC, Process Counter)라고 부른다.
컴퓨터 시스템은 CPU에 의해사면 이루어지는 것은 아니다. 프로그램 실행 중 디스크에서 파일을 읽어오기도, 키보드로 입력을 받기도, 처리 결과를 출력하기도 한다. 각 입출력 장치와 이들 장치를 전담하는 작은 CPU와 메모리를 각각 입출력 컨트롤러와 로컬 버퍼라고 부른다.
📌 프로세스 카운터 (PC, Process Counter)
CPU가 수행해야 할 메모리 주소를 담고 있는 레지스터
📌 입출력 컨트롤러 (I/O Controller) / 로컬 버퍼 (Local Buffer)
각 입출력 장치와 이들 장치를 전담하는 작은 CPU와 메모리
2-2. 메모리 이해하기
메모리에는 사용자 프로그램들과 운영체제가 같이 올라가 수행된다.
CPU의 프로그램 카운터가 메모리 주소 중 운영체제가 존재하는 부분을 가리키고 있다면 현재 운영체제의 코드를 수행 중이며, CPU가 커널모드(kernel mode)에서 수행 중이라고 한다.
반대로 프로그램 카운터가 사용자 프로그램이 존재하는 메모리 위치를 가리키고 있다면 현재 사용자 프로그램이 수행 중이며, CPU가 사용자 모드(user modee)에서 수행 중이라고 한다.
2-3. 일반명령과 특권명령
📌 일반명령
메모리에서 자료를 읽어와 CPU에서 계산하고 결과를 메모리에 쓰는 일련의 명령
⇒ 모든 프로그램이 수행할 수 있는 명령
📌 특권명령
보안이 필요한 명령으로 입출력 장치, 타이머 등 각종 장치에 접근하는 명령
⇒ 운영체제만 수행할 수 있다
📌 모드비트 (mode bit)
컴퓨터 시스템이 운영체제에서만 특권명령을 실행할 수 있도록 현재 CPU 사용정보를 판단하기 위한 레지스터
📌 시스템 콜
사용자 프로그램이 운영체제에게 특권명령의 대행을 요청하는 서비스 요청
사용자 프로그램이 디스크에서 자료를 읽어오는 시스템 콜을 요청하면 CPU는 디스크 컨트롤러에게 데티터를 읽어오라는 명령을 내린다. 그러면 디스크 컨트롤러는 디스크로부터 데이터를 읽어와서 자신의 로컬버퍼에 저장한다. 작업 완료 후 디스크 컨트롤러가 CPU에 인터럽트를 발생시켜 입출력 작업이 완료되었음을 통지한다.
📌 인터럽트 라인 (Interrupt line)
인터럽트 요청을 순서대로 저장하여 CPU 처리를 대기하기 위한 주변장치
3. 프로그램의 실행
3-1. 프로그램 실행의 의미
- 디스크에 존재하던 실행파일이 메모리에 적재된다는 것
- 프로그램이 CPU를 할당받고 명령(Instruction)을 수행하고 있는 상태라는 것
일반적인 컴퓨터 시스템의 경우 CPU는 하나지만, 짧은 단위로 CPU를 나눠 사용하여 여러 프로그램이 메모리에 동시에 적재되어 있을 수 있으므로 동시에 실행한다는 말을 사용한다.
실행파일이 메모리에 적재될 때 실행파일 일부분만 올라가고 나머지는 디스크 특정 영역에 존재한다. 이는 여러 프로그램이 메모리 공간을 좀 더 효율적으로 사용하기 위한 방법이다.
- CPU 수행에 필요한 부분은 메모리에 올려두고
- 그렇지 않은 부분은 디스크 중 메모리 연장 공간으로 사용되는 스왑 영역에 내려두는 방식을 사용한다.
📌 가상 메모리 (virtual memory) 또는 논리적 메모리 (logical memory)
물리적 메모리 주소와 독립적으로 각 프로그램마다 독자적으로 가지고 있는 주소 공간
3-2. 운영체제의 주소 공간 구성
✍🏻 운영체제의 기능
- 하드웨어 자원을 효율적으로 관리하는 것
- 응용프로그램 및 사용자에게 편리한 서비스를 제공하는 것
📌 커널의 코드 (Code)
자원을 관리하고 편리한 인터페이스를 제공하며, 시스템콜 / 인터럽트를 처리하는 부분
📌 커널의 데이터 (Data)
각종 자원을 관리하기 위한 자료구조를 저장하는 부분
- CPU / 메모리 드으 하드웨어 자원을 관리하기 위한 자료구조
- 현재 수행 중인 프로그램을 관리하기 위한 자료구조 (PCB)
📌 커널의 스택 (Stack)
함수 호출 시 복귀 주소를 저장하는 부분
- 프로그램이 자신의 코드에서 함수 호출 및 복귀 주소를 유지하려면 자기 주소 공간 내 스택을 사용
- 시스템콜 / 인터럽트 등으로 운영체제의 코드가 실행될 때 함수 호출이 발생할 경우 커널 스택 사용
🧐 커널 내 프로세스마다 별도의 스택이 필요한 이유?
프로세스가 함수를 호출할 때 자기 주소 영역 내부에 정의된 함수를 호출하면 자신의 스택에 복귀 주소를 저장하지만, 프로세스가 특권명령을 수행하려고 커널에 정의된 시스템콜을 호출하고 시스템콜 내부에서 다른 함수를 호출하는 경우, 그 복귀 주소는 커널 내의 주소가 되어 사용자 프로그램의 스택과는 별도의 저장 공간이 필요하기 때문이다.
또한, 커널은 일종의 공유 코드로서 모든 사용자 프로그램이 시스템콜을 통해 커널의 함수에 접근할 수 있으므로, 일관성 유지를 위해 각 프로세스마다 별도의 스택을 둔다.
📌 프로세스 (Process)
파일 시스템 내 프로그램의 실행파일을 실행하여 메모리에 올라간 상태
📌 PCB (Process Control Block, 프로세스 제어 블록)
각 프로세스의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지하기 위한 자료구조
4. 사용자 프로그램이 사용하는 함수
1. 사용자 정의 함수
프로그래머 본인이 직접 작성한 함수
2. 라이브러리 함수
프로그래머 본인이 직접 작성하지는 않았지만 이미 누군가 작성해놓은 함수를 호출하여 사용하는 함수
사용자 정의 함수와 라이브러리 함수는 모두 그 프로그램 코드 영역에 기계어 명령 형태로 존재한다. 두 함수는 프로그램이 실행될 때 해당 프로세스의 주소 공간에 포함되며, 함수 호출 시에도 자신의 주소 공간에 있는 스택을 사용한다.
- sin() : 삼각함수에 대한 라이브러리 함수
- printf() : 라이브러리 함수지만 궁극적으로 특권명령인 입출력을 수반하여 시스템콜을 동반하게 되는 함수
3. 커널 함수
운영체제 커널의 코드에 정의된 함수
✍🏻 커널 함수의 종류
- 시스템콜 : 사용자 프로그램이 운영체제의 서비스를 요청하기 위해 호출하는 함수
- 인터럽트 처리 함수 : 각종 HW / SW가 CPU 서비스를 요청하기 위해 호출하는 함수
커널 함수는 운영체제 커널의 주소 공간에 정의되어 있고, 사용자 프로그램이 호출하여 사용
- read() / write() : 각각 사용자 프로그램이 입/출력을 필요로 할 때 호출하는 시스템콜 함수
5. 인터럽트
🧐 인터럽트 처리 중에 또 다른 인터럽트가 발생하는 경우
원칙적으로는 인터럽트 처리 중에 또 다른 인터럽트가 발생하는 것을 허용하지 않는다. 그 이유는 인터럽트 처리 중에 다른 인터럽트를 처리하면 데이터의 일관성이 유지되지 않는 문제가 발생할 수 있기 때문이다.
경우에 따라 예외가 존재할 필요성이 있는데, 상대적으로 낮은 중요도를 가진 인터럽트를 처리하는 도중에 중요도가 더 높은 인터럽트가 발생하는 것을 허락할 필요가 있다. 이때는 현재 처리 중이던 인터럽트 코드의 수행 지점을 저장하고, 우선 순위가 높은 인터럽트를 처리하게 된다. 인터럽트 처리가 끝나면 저장된 주소로 복귀해 이전에 수행하던 인터럽트 처리 코드를 마저 수행하게 된다.
6. 시스템 콜
시스템 콜은 자신의 주소 공간을 거스르는 영역에 존재하는 함수를 호출하는 것을 말한다. 자신의 프로그램이 아닌, 커널이라는 다른 프로그램의 주소 공간에 존재하는 함수를 호출하는 것이다. 이 방법은 프로그램 자신이 인터럽트 라인에 인터럽트를 세팅하는 명령을 통해 이루어진다. 이는 프로그램이 스스로 인터럽트 라인을 세팅한다는 점만 다를 뿐, 일반적인 인터럽트의 발생과 동일한 방법이라 할 수 있다.
✍🏻 디스크 파일 입출력 과정을 통해 시스템 콜 알아보기
사용자 프로그램이 CPU에서 명령을 수행하던 중 디스크 파일을 읽어와야 할 경우 시스템 콜로 커널의 함수를 호출하게 된다. 사용자 프로그램은 CPU 제어권을 운영체제에게 이양하게 되는데, 이는 인터럽트 라인을 세팅하는 명령을 통해 이루어진다. CPU는 다음 명령을 수행하기 전 인터럽트 발생을 인지하고 제어권을 운영체제로 이양하게 된다. 운영체제는 설정된 인터럽트 라인에 의해 입출력 요청 인터럽트를 인지하여 입출력 작업을 수행하게 되고, 이 과정에서 CPU는 디스크 컨트롤러에게 파일을 읽어오라는 명령을 하게 된다.
디스크 컨트롤러가 디스크에서 데이터를 읽어오는 일은 CPU가 명령을 수행하는 일보다 상대적으로 많은 시간이 소요된다. 따라서 대부분의 경우 운영체제는 입출력을 요청한 다음 CPU 제어권을 다른 프로세스에게 이양한다. 디스크 컨트롤러는 입출력 작업이 완료되면 CPU에게 인터럽트를 발생시켜 입출력 작업 완료를 알리게 된다. 그러면 CPU는 인터럽트 처리루틴으로 사용자 프로세스의 수행을 멈추고 제어권을 넘긴다. 이때 발생한 인터럽트는 하드웨어 인터럽트에 해당하며, 그 처리 내용은 디스크로부터 로컬버퍼로 읽어온 내용을 컴퓨터 내 메모리로 복사한 후 디스크 입출력을 요청했던 프로세스에게 다시 CPU를 획득할 권한을 주는 것이다. 그러면 해당 프로세스는 CPU를 기다리는 큐에 삽입되고 CPU의 제어권은 인터럽트를 당한 프로세스에게 넘어가 하던 작업을 계속 수행하게 된다.
✍🏻 CPU 할당을 중간에 빼앗기는 경우
- 타이머에 의해 인터럽트가 발생하는 경우
📌 타이머
특정 프로그램에 의해 CPU가 독점되는 것을 방지하기 위한 하드웨어 - 입출력 요청을 위해 시스템 콜을 하는 경우
7. 프로세스의 두 가지 실행 상태
✍🏻 프로세스 수행 완료 과정
1. 사용자 모드에서의 실행 상태 (user mode running)
프로그램 자신의 주소 공간에 정의된 코드를 실행하는 것
2. 커널 모드에서의 실행 상태 (kernel mode running)
프로그램이 커널의 시스템 콜 함수를 실행하는 것
🧐 프로세스 A에 의해 시스템 콜이 수행되는 동안 실행 상태는 커널일까 프로세스일까?
시스템 콜이 수행하는 동안 커널이 실행 상태(running state)에 있다고 하지 않고, 프로세스 A가 실행 상태에 있다고 말한다.
커널의 코드가 실행되는 것이 사실상 프로세스 A가 해야할 일을 대행하는 것이기 때문이다. 다만 프로세스 A의 코드를 실행하는 것과 구분지어 이러한 상태를 '프로세스 A가 커널 모드에서 실행 중'이라고 이야기 한다.
참고자료
- 책 - 운영체제와 정보기술의 원리 (반효경, 2020년 5월)
'컴퓨터과학 > 운영체제' 카테고리의 다른 글
[운영체제] 컴퓨터 3계층 구조 (0) | 2024.10.22 |
---|---|
[운영체제] 5. 프로세스 관리 (0) | 2024.10.22 |
[운영체제] 3. 컴퓨터 시스템의 동작 원리 (0) | 2024.10.16 |
[운영체제] 2. 운영체제 개요 (0) | 2024.10.10 |
[운영체제] 1. 컴퓨터 및 정보기술의 역사 (0) | 2024.10.10 |
블로그의 정보
콰이엇의 개발기록
콰이엇