이전의 hello 프로그램을 쉘 프로그램이 로드하고 실행했을 때나
hello 프로그램이 메시지를 출력할 때,
이 프로그램이 키보드나 디스플레이, 디스크나 메인 메모리
를 직접 액세스하지 않는다.
운영체제가 제공하는 서비스를 활용한다.
운영체제는 하드웨어
와 소프트웨어
사이에 위치한 소프트웨어 계층이다.
응용프로그램
이 하드웨어
를 제어하려면 언제나 운영체제를 통해서 해야 한다.
1) 제멋대로 동작하는 응용프로그램들이 하드웨어를 잘못 사용하는 것을 막는다.
2) 응용프로그램들이 단순하고 균일한 메커니즘을 사용하여 복잡하고 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 한다.
(응용프로그램이 하드웨어를 직접 조작하려면 복잡하다. 운영체제가 중간다리 역할을 해서 쉽게 해준다.)
💡 추상화: 일정한 목적을 위해 필요한 핵심적인 부분만을 간추려 내는 과정
운영체제는 위 두 가지 목표를 근본적인 추상화를 통해 달성하고 있다.
파일: 입출력장치의 추상화
가상메모리: 메인 메모리와 디스크 입출력 장치의 추상화
프로세스: 프로세서, 메인 메모리, 입출력 장치 모두의 추상화 결과
👆 이것들을 이어서 알아보자!!
hello 같은 프로그램이 최신 시스템에서 실행될 때
운영체제는 시스템에서 이 한 개의 프로그램만 실행되는 것 같은 착각
에 빠지게 해준다.
프로그램이 프로세서, 메인 메모리, 입출력장치
를 모두 독차지하고 있는 것처럼 보인다.
프로세서는 프로그램 내의 인스트럭션들을 다른 방해 없이 순차적으로 실행하는 것처럼
보인다.
프로그램의 코드와 데이터가 시스템 메모리의 유일한 객체인 것처럼
보인다.
👆 이러한 환상은 전산학에서 가장 중요한 프로세스라고 하는 개념에 의해서 만들어진다.
프로세스는 실행 중인 프로그램에 대한 운영체제의 추상화다.
다수의 프로세스들은 동일한 시스템에서 동시에 실행될 수 있고,
각 프로세스는 하드웨어
를 배타적으로 사용하는 것처럼 느낀다.
동시에(concurrently)
라는 말은, 한 프로세스의 인스트럭션들이 다른 프로세스의 인스트럭션들과 섞인다는 것을 의미한다.
대부분의 시스템에서 프로세스를 실행할 CPU의 숫자보다 더 많은 프로세스들이 존재한다.
(이전의 시스템들은 한 번에 한 개의 프로그램만 실행할 수 있었지만, 요즘의 멀티코어 프로세서들은 여러 개의 프로그램을 동시에 실행할 수 있다.)
어느 쪽이건 프로세서가 프로세스들을 바꿔주는 방식으로 한 개의 CPU가 다수의 프로세스를 동시에 실행하는 것처럼 보이게 해준다.
context switching
운영체제는 문맥 전환이라는 방법을 사용해서 이러한 교차실행을 수행한다.
운영체제는 프로세스가 실행하는 데 필요한 모든 상태정보(컨텍스트)의 변화를 추적한다.
(상태정보는 PC, 레지스터 파일, 메인 메모리의 현재 값을 포함한다.)
어느 한순간에 단일 프로세서 시스템은 한 개의 프로세스의 코드만을 실행할 수 있다.
👉🏻 운영체제는 현재 프로세스에서 다른 새로운 프로세스로 제어를 옮기려고 할 때
1) 현재 프로세스의 컨텍스트를 저장하고,
2) 새 프로세스의 컨텍스트를 복원시키는 문맥전환을 실행하여
3) 제어권을 새 프로세스로 넘겨준다.
4) 새 프로세스는 이전에 중단했던 바로 그 위치부터 다시 실행된다.
kernel
하나의 프로세스에서 다른 프로세스로의 전환은 운영체제 커널에 의해 관리된다.
커널은 운영체제 코드의 일부분으로, 메모리에 상주한다.
응용프로그램이 운영체제에 의한 어떤 작업을 요청하면
1) 컴퓨터는 파일 읽기나 쓰기와 같은 특정 시스템 콜
을 실행해서 커널에 제어를 넘겨준다.
2) 그러면 커널은 요청된 작업을 수행하고 응용프로그램으로 리턴한다.
커널은 별도의 프로세스가 아니라는 점에 유의해야 한다!
대신, 커널은 모든 프로세스를 관리하기 위해 시스템이 이용하는 코드와 자료 구조의 집합
이다.
프로세스가 마치 한 개의 제어흐름을 갖는 것으로 생각할 수 있지만,
최근의 시스템에서는 프로세스가 실제로 쓰레드
라고 하는 다수의 실행 유닛으로 구성되어 있다.
각각의 쓰레드는 해당 프로세스의 컨텍스트
에서 실행되며
동일한 코드
와 전역 데이터
를 공유한다.
쓰레드는 프로그래밍 모델로서의 중요성이 더욱 커지고 있다.
👉🏻 Why? 다수의 프로세스들에서보다
1) 데이터의 공유가 더 쉽다.
2) 쓰레드가 프로세스보다 더 효율적이다.
다중 쓰레딩도 다중 프로세서를 활용할 수 있다면 프로그램의 실행 속도를 빠르게 하는 한 가지 방법이다.
(그림에서 위쪽으로 갈수록 주소가 증가한다!)
가상메모리는 각 프로세스들이 메인 메모리
전체를 독점적으로 사용하고 있는 것 같은 환상을 제공하는 추상화이다.
각 프로세스는 가상주소 공간
이라고 하는 균일한 메모리의 모습을 갖게 된다.
리눅스에서, 주소공간의 최상위 영역은 모든 프로세스들이 공통으로 사용하는 운영체제의 코드와 데이터를 위한 공간이다.
주소공간의 하위 영역은 사용자 프로세스의 코드와 데이터를 저장한다.
실행 가능 목적파일
인 hello로부터 직접 초기화된다.가상메모리가 작동하기 위해서는 프로세서가 만들어내는 모든 주소를 하드웨어로 번역하는 등의 하드웨어와 운영체제 소프트웨어 간의 복잡한 상호작용이 필요하다.
기본적인 아이디어는 프로세스의 가상메모리
의 내용을 디스크
에 저장하고, 메인 메모리
를 디스크의 캐시로 사용하는 것이다.
파일은 더도 덜도 말고 그저 연속된 바이트들이다.
디스크, 키보드, 디스플레이, 네트워크까지 포함하는 모든 입출력장치는 파일로 모델링한다.
시스템의 모든 입출력은 유닉스 I/O
라는 시스템 콜들을 이용하여 파일을 읽고 쓰는 형태로 이루어진다.
파일 개념은 매우 강력한 것이다! 응용프로그램에 시스템에 들어 있는 다양한 입출력장치들의 통일된 관점을 제공한다.