운영체제와 정보기술의 원리
4장 프로그램의 구조와 실행
1. 프로그램의 구조와 인터럽트
프로그램이 CPU에서 명령을 수행하려면 해당 명령을 담은 프로그램 주소 영역이 메모리에 올라가 있어야 한다. 이 프로그램 주소 영역은 코드 + 데이터 + 스택
영역으로 이루어져 있다.
-
코드
작성한 프로그램 함수들의 코드가 CPU에서 수행할 수 있는 기계어 명령 형태로 변환되어 저장되는 부분
-
데이터
전역 변수 등 프로그램이 사용하는 데이터를 저장하는 부분
-
스택
함수가 호출될 때 호출된 함수의 수행을 마치고 복귀할 주소 및 데이터를 임시로 저장하는 데에 사용되는 공간
함수를 실행하다가 다른 함수를 호출하면 현재 위치를 스택에 저장하고 다른 함수에서 명령을 수행한 뒤 다시 스택에 저장된 주소로 돌아온다.
-
인터럽트
A라는 프로그램이 CPU를 할당받아서 명령 실행 중인데 인터럽트가 발생하면 A는 현재 수행 중인 명령의 위치를 저장해놓는다.
이 때 저장하는 위치는 함수 호출과 달리 운영체제가 관리하는 프로세스 제어블록(PCB)이다.
2. 컴퓨터 시스템의 작동 개요
CPU는 빠르게 계산할 수 있지만, 어떤 작업을 수행해야할지 스스로 결정하는 능력은 없어 특정 주소에 있는 명령을 하나씩 읽어와 실행할 뿐이다.
- 프로그램 카운터(PC): CPU가 수행해야 할 메모리 주소를 담고 있는 레지스터 CPU는 프로그램 카운터가 가리키는 위치의 명령을 실행한다.
하지만 모든 컴퓨터 시스템의 동작이 CPU에 의해서만 이루어지지는 않는다. 디스크에서 파일을 읽어오기도 하고, 키보드로부터 입출력하기도 한다.
이 때 각 입출력 장치별로 존재하는 작은 CPU를 입출력 컨트롤러, 메모리를 로컬버퍼 라고 부른다.
일반 명령과 특권 명령
-
일반 명령
모든 프로그램이 수행할 수 있는 명령으로 메모리에서 데이터를 읽어와 CPU에서 계산 후 결과를 다시 메모리에 쓰는 일련의 명령이다.
-
특권 명령
보안이 필요한 명령으로 입출력 장치, 타이머 등 각종 장치에 접근하는 명령이다.
특권 명령은 운영체제만 수행할 수 있도록 모드비트를 통해 제한한다.
시스템 콜
사용자 프로그램이 실행되다 보면 일반명령 외에 특권명령의 수행이 필요할 수 있다.
사용자 프로그램은 스스로 특권명령을 수행할 수 없으므로 운영체제에 특권명령의 대행을 요청하는 것이다.
시스템 콜이 요청되면 커널 영역에 정의된 시스템 콜 처리 코드를 수행한다.
CPU는 매번 명령을 수행한 후 인터럽트 라인을 체크해 시스템 콜이 들어왔는지 확인하고 주변 장치들은 인터럽트의 종류마다 인터럽트 라인을 다르게 해 구분한다.
ex) 디스크에서 자료를 읽어오는 시스템 콜: CPU가 디스크 컨트롤러에게 데이터 읽어오라는 명령을 내리고, 디스크 컨트롤러는 디스크로부터 데이터를 읽어와서 자신의 로컬버퍼에 저장 후 CPU에 인터럽트를 발생시킨다.
3. 프로그램의 실행
프로그램이 실행되고 있다는 것의 의미
-
디스크에 존재하던 실행파일이 메모리에 적재된다.
실행파일 전체가 메모리에 적재되기 보다는 메모리 공간을 더욱 효율적으로 사용하기 위해 일부만 올라가고 나머지는 디스크에 특정 영역에 존재한다.
-
프로그램이 CPU를 할당받아 명령을 수행하고 있다.
운영체제의 프로그램 실행
운영체제 또한 하나의 프로그램이므로 코드, 데이터, 스택 영역을 가지고 있다.
-
코드
CPU, 메모리 등의 자원을 효율적으로 관리함과 동시에 사용자에게 편리한 인터페이스를 제공하고자 한다.
-
데이터
CPU나 메모리 같은 하드웨어 자원 뿐 아니라 수행 중인 프로그램을 관리하기 위한 자료구조가 저장된다.
-
PCB
각 프로세스(현재 수행중인 프로그램)의 상태, CPU 사용 정보, 메모리 사용 정보 등을 유지하기 위한 자료구조이다.
-
-
스택
함수 호출 시에 복귀 주소를 저장하기 위한 용도이다.
현재 수행 중인 프로세스마다 별도의 스택을 두어 관리한다.
- 커널은 일종의 공유 코드로 모든 프로세스가 접근할 수 있으므로 일관성을 위해
- 커널 영역의 메모리 주소를 일반 사용자용 프로그램의 복귀 주소로 지정할 수 없으므로 커널이 관리하는 프로세스별 스택에 지정
일반 프로그램이 시스템 콜을 했거나 인터럽트가 발생해 CPU 할당이 운영체제로 넘어가면 프로그램의 복귀 주소를 자신의 스택이 아닌 커널의 데이터 영역에 있는 PCB에 저장한다. 커널 영역에서 이뤄지는 함수 호출은 직전에 CPU를 갖고 있던 프로세스를 커널 스택 사용한다.
4. 사용자 프로그램이 사용하는 함수
-
사용자 정의 함수
프로그래머가 작성한 함수
-
라이브러리 함수
직접 작성한 것은 아니지만 누군가작성해놓은 함수를 호출만 하여 사용 하는 것
-
커널 함수
시스템 콜 함수, 각종 하드웨어 및 소프트웨어가 CPU의 서비스를 요청하기 위해 발생시키는 인터럽트 처리 함수
사용자 정의 함수와 라이브러리 함수는 코드 영역에 기계어 명령 형태로 존재한다. 해당 프로세스의 주소 공간에 포함되고, 자신의 스택을 사용한다.
커널함수는 운영체제 커널의 주소 공간에 코드가 정의된다.
5. 인터럽트
시스템 콜은 사용자 프로그램이 아닌 운영체제라는 별개의 프로그램에 CPU를 넘겨서 실행하는 것이다. 이를 넘기기 위해 인터럽트와 동일한 메커니즘을 갖는다.
- CPU는 프로그램 카운터가 가리키는 곳에 있는 명령을 순차적으로 수행한다.
- 다음 명령 수행하기 전에 인터럽트 라인이 세팅되었는지 체크한다.
- 인터럽트가 발생했으면 하던 프로세스를 멈추고 인터럽트를 처리한다.
인터럽트 처리 중 또 다른 인터럽트가 발생한다면?
원칙적으로 일관성이 유지되지 않기 때문에 허용하지 않는다.
하지만 우선순위가 높은 인터럽트가 발생하면 처리 중이던 인터럽트 코드의 수행 지점을 저장하고 중요한 인터럽트를 먼저 처리한다. 이후에 다시 저장한 지점으로 돌아와 마저 처리한다.
6. 시스템콜
커널이라는 다른 프로그램의 주소 공간에 존재하는 함수를 호출하는 것
주소 공간 자체가 다른 곳으로 이동해야 하므로 프로그램 자신이 인터럽트 라인에 인터럽트를 세팅하는 명령을 통해 이뤄진다.
프로그램이 CPU를 빼앗기는 경우
-
타이머에 의한 인터럽트 발생
특정 프로그램이 CPU를 독점하는 것을 방지하기 위해 할당 시간이 만료되면 인터럽트를 발생시키는 것이다.
-
입출력 요청을 위해 시스템 콜
입출력을 위해 시스템 콜로 커널의 함수를 호출할 때, 입출력 함수의 호출이 자신의 주소 공간에서 이루어질 수 없기 때문에 CPU 제어권을 운영체제로 넘기는데, 이게 인터럽트 라인 세팅을 통해 이루어지는 것이다.
시스템 콜이 들어오더라도 CPU는 로컬 버퍼에 다 옮기고 인터럽트가 발생할 때까지 다른 프로세스에 할당된다.
7. 프로세스의 두가지 상태
-
사용자모드에서의 실행 상태 (user mode running)
사용자 정의 함수, 라이브러리 함수 사용
-
커널모드에서의 실행 상태 (kernel mode running)
커널의 시스템 콜 함수 실행
프로세스 A가 시스템 콜을 해 실행되는 것이 커널의 코드이지만 사실상 프로세스가 할 일을 대행하기에 커널 모드에서 실행 중이라고 구분지어 이야기한다.
프로그램이 끝나면 커널 모드로 진입해 종료한다.