프로세스
메인 메모리에 적재되어 실행중인 프로그램이다.
여러 종류의 디스크에 저장된 프로그램 파일들은 CPU를 이용해 연산을 수행해야 하고, 각종 입출력장치와 데이터를 주고 받으며 동작해야 한다. 그런데, CPU의 동작 속도에 비해 디스크의 동작 속도가 느리기 때문에 CPU가 디스크에 저장되어있는 프로그램 코드를 직접 읽는 것은 아주 비효율적이다. 따라서, 비교적 용량이 작지만, 디스크에 비해 훨씬 동작 속도가 빠른 저장장치를 “메인 메모리” 라는 이름으로 중간에 두어 사용한다. 처음에 메모리에 프로그램의 코드와 기타 데이터를 미리 옮겨두고, CPU는 메인 메모리에서 코드를 읽어 CPU가 덜 낭비되게 된다.
메모리 구조
프로세스의 실행 코드와 각종 데이터는 메모리에 저장된다. 운영체제는 프로세스에 할당할 메모리를 적절한 용도로 구분하는 것이 유용할 것이다. 그렇게 운영체제는 메모리를 다음과 같은 구조로 할당한다.
•
스택 : 함수의 매개변수 및 지역변수, 함수 종료 후 복귀 주소 등 임시로 데이터를 저장하는 영역이다.
•
힙 : 프로세스 실행 도중에 할당되는 메모리 영역으로, 이 곳의 주소를 스택에서 참조하는 형태로 사용된다.
•
데이터 : 전역변수, 정적 변수가 저장된다.
•
텍스트 : 프로세스가 실행해야 하는 명령어가 저장되는 영역이다.
PCB(프로세스 컨트롤 블록)
프로세스의 메타데이터를 표현한 자료구조다.
PCB에는 프로세스의 상태, 프로세스의 식별자, 프로세스가 사용하는 입출력장치 목록, 프로그램 카운터(다음에 실행할 명령어의 주소), cpu 레지스터 정보 등 운영체제가 프로세스의 실행을 위해 필요로 하는 정보를 포함한다.
이런 정보들은 당연히 메인 메모리에 저장되며, 아주 중요한 정보이므로 사용자 영역이 아니라 커널 영역에 저장한다.
프로세스 스케줄링
앞서 말한 대로, 메인 메모리의 존재로 인해 CPU의 비효율 일부는 해결되었다. 하지만, 프로세스는 입출력장치와도 통신해야 하는데, 프로세스가 입출력장치와 통신하는 동안 CPU는 프로세스의 다음 명령을 수행할 수 없다. 이를 해결하기 위해, 어떤 프로세스가 입출력을 하는 동안 다른 프로세스를 CPU가 수행해 CPU가 쉬지 않고 일을 하게 한다.
자연스럽게, 메모리에 여러 프로세스가 존재하게 되고, CPU가 이 들 중 어떤 프로세스를 실행하게 할지 정하는 알고리즘이 필요하게 된다. 이것이 프로세스 스케줄링이다.
프로세스 상태
말 그대로 프로세스가 지금 어떤 상황인지를 나타내는 표시다. 이를 활용해 스케줄링을 하게 된다. 상태의 종류는 운영체제가 정하기 나름이지만, 일반적인 것은 있다.
operating system concepts - 95pg
스케줄링의 기본적인 동작 방식
프로세스가 생성된 뒤, 실행할 준비가 되었다면, 이들은 준비완료 큐에 들어간다. 이후 cpu에 의해 준비완료 큐에서 프로세스를 하나 골라 실행한다. 이때 큐에서 제거된다. 이후 스케줄링 알고리즘에 의해 적절한 시점까지 프로세스가 실행된 뒤, 다시 준비완료 큐로 이동된다.
만약 프로세스가 입출력을 기다리는 상황이라면, 각 입출력 기기의 입출력 큐로 이동한다. 입출력이 끝나면 준비 완료 큐로 들어간다.
프로세스가 완전히 수행되면 종료되고, 그 어떤 큐에도 들어가지 않는다.
스케줄링 알고리즘은 준비완료 큐에서 어떤 기준으로 프로세스를 선택하는지가 핵심이 된다.
컨텍스트 스위칭
위에서 CPU가 메인 메모리와 통신하며 연산을 한다고 했지만, 사실 CPU 내부에 더욱 고속의 저장장치인 레지스터가 있다. 실제로 명령어는 이 레지스터에 값을 쓰거나 읽어 연산을 수행하게 된다.
앞서 말한 대로 CPU가 실행하는 프로세스가 완전히 수행되기 전에 입출력 작업을 수행하는 것을 기다리는 동안, 다른 프로세스를 실행한다면, 입출력 작업을 수행하는 프로세스가 다시 이전에 수행한 지점 이후부터 실행되어야 함을 의미한다. 따라서, 해당 시점의 실행 문맥(문맥을 영어로 컨텍스트라 한다)을 저장해야 한다. 그리고, CPU가 실행하려고 하는 그 다른 프로세스 역시 자신의 실행 문맥을 가지고 있을 것이다. 따라서, CPU가 실행중인 프로세스를 전환하려면, 문맥을 교환하는 작업이 필요하다. 이를 컨텍스트 스위칭이라 한다.
컨텍스트 스위칭은 순수하게 오버헤드이다. 따라서 이를 적게 발생하도록 하는 것이 스케줄링 알고리즘의 또 다른 핵심이다.
프로세스간 통신
병행으로 실행되는 이 프로세스 사이에 데이터를 공유할 수 있다면 아주 유용할 것이다. 여러 프로세스가 동시에 필요로 하는 파일이 있을 수도 있고, 병렬로 계산할 수 있는 논리인 경우 여러 프로세스가 나누어 수행한다면 효율적일 것이다. 또, 모듈화의 장점을 누릴 수도 있다.
파일을 이용한 방식
같은 파일에 여러 프로세스가 데이터를 읽고 쓰는 것을 말한다.
공유 메모리 방식
말 그대로 특정 메모리를 여러 프로세스가 공유하는 것이다.
기본적으로 각 프로세스의 메모리는 격리되어있다. 이를 부분적으로 해제하는 것 까지가 운영체제의 역할이고, 이 메모리 공간에 어떤 데이터를 어떻게 저장하고 읽을 것이며 동시성 문제를 관리할지는 각 프로세스가 해야 한다.
대신, 메모리를 직접 참조하기 때문에, 빠르게 데이터를 공유할 수 있다.
메시지 전달 방식
프로세스가 메시지를 운영체제가 제공하는 설비를 통해 전달함으로써 통신하는 것이다.
운영체제가 제공하는 설비 역시 메모리를 사용할 것이고, 이는 커널 영역에 있을 것이므로, 결과적으로 각 프로세스는 공유 메모리 방식보다 몇단계를 거쳐 통신하게 된다. 따라서 느리다. 하지만, 공유메모리에서는 직접 제어해야 하던 많은 문제를 운영체제가 대신 해주므로 간편하다.
고려해야 할 사항
메시지 전달 방식을 구현하기 위해선 운영체제 입장에서 최소 3가지를 고려해야 한다.
1.
통신 방식
2.
동기화
3.
버퍼링
다른 컴퓨터의 프로세스 간 통신
물리적으로 떨어져있는 별개의 컴퓨터에서 실행중인 프로세스가 데이터를 공유하기 위해선 메시지 전달 방식으로 수행해야 한다. 이 과정에서 당연히 데이터는 네트워크 프로토콜에 맞게 적절히 변형되어 전달될 것이다.
소켓
TCP나 UDP를 사용하기 위해 운영체제가 제공하는 저수준의 인터페이스다.
소켓은 바이트 스트림을 전송하고 수신하게 해준다. 즉, 어떤 구조화된 데이터라도 모두 바이트 스트림으로 변환해서 전송하고, 바이트 스트림을 변환해서 수신해야 한다.
RPC
프로세스가 다른 컴퓨터에 있는 다른 프로세스의 함수를 마치 자신의 함수를 호출하는 것 처럼 사용할 수 있도록 제공되는 시스템
클라이언트는 운영체제가 제공하는 stub에 메세지를 보낸다. 이 메세지에는 원격 프로세스의 주소, 함수의 식별자, 매개변수 등이 포함된다. stub은 이 메세지를 네트워크를 통해 전달할 수 있도록 적절히 가공하고, 네트워크 프로토콜을 통해 서버에 메세지를 전달한다. 서버의 stub이 이 메세지를 수신해 적절한 함수를 호출한다. 반환 값도 같은 방식으로 전달한다.
추상적인 개념이기 때문에, 메세지의 구체적인 형태, 사용하는 네트워크 프로토콜 등 여러 가지 사항을 실제로 어떻게 하는지는 그 구현에 달려있다.
gRPC
구글이 만든 오픈소스 RPC 프레임워크.
SOAP, REST 등의 방식보다 더 빠르게 통신을 할 수 있도록 고안된 RPC이다. 주요 특이점은 다음과 같다.
1.
HTTP/2를 이용해 데이터를 전송한다.
2.
프로토콜버퍼 라는 방식으로 데이터를 표현한다.