컴퓨터에서 실행 중인 하나의 프로그램을 의미한다.
프로그램: 특정 작업을 수행하기 위한 명령어의 집합
프로세스는 OS로부터 독립된 메모리 영역(코드, 데이터, 스택, 힙)을 할당받으며, 다른 프로세스의 메모리 영역에 접근할 수 없다.
지역변수, 함수의 매개변수, 반환되는 값 등이 저장되는 영역 (LIFO)
높은 주소 값에서 낮은 주소 값으로 메모리가 할당된다.
영역 크기는 컴파일 때 결정된다.
스택 영역은 함수의 호출과 함께 할당되며 함수의 호출이 완료되면 소멸한다.
이렇게 스택 영역에 저장되는 함수의 호출 정보를 스택 프레임
이라고 한다.
사용자에 의해 동적 메모리 할당 및 해제가 일어나는 영역 (FIFO)
낮은 주소 값에서 높은 주소 값으로 메모리가 할당되며, 영역 크기는 런타임 때 결정된다.
스택 영역이 힙 영역을 침범하는 경우를 스택 오버플로
, 힙 영역이 스택 영역을 침범하는 경우를 힙 오버플로
라고 한다.
스택이 훨씬 빠르다.
스택은 이미 할당되어 있는 공간을 사용하는 것이고, 힙은 따로 할당해서 사용하는 공간이다.
스택은 이미 할당되어 있는 스택에 대해 포인터의 위치만 바꿔주는 단순한 CPU 연산이다.
반면 힙은 요청된 chunk의 크기, 현재 메모리의 fragmentation 상황 등 다양한 요소를 고려하기 때문에 더 많은 CPU 연산이 필요하다.
다만, 스택은 공간이 매우 적기에 모든 응용 프로그램에서 스택을 사용할 수는 없다.
메모리의 데이터 영역은 프로그램의 전역 변수와 정적 변수가 저장되는 영역이다.
프로그램이 시작하고 끝날 때까지 계속 남아있다.
데이터 영역은 세부적으로 BSS(Block Stated Symbol)영역
과 데이터 영역
으로 나뉜다.
실행할 코드가 기계어로 컴파일되어 저장되는 영역으로, 텍스트 영역이라고도 한다.
실행할 프로그램의 코드는 프로그래머가 작성한 소스 코드이다.
프로그램이 시작하고 끝날 때까지 메모리에 계속 남아있다.
CPU는 코드 영역에 저장된 명령어를 하나씩 가져와서 처리하게 된다.
프로그램에 대해 설명해주세요.
프로그램이란 메모리에 올라가 있지 않고, 저장 장치에 저장되어 있는 상태의 코드 파일을 의미합니다.
프로그램을 실행하기 위해서는 OS로부터 프로그램이 동작하는데 필요한 CPU, 메모리 등을 할당 받아야 합니다.
프로세스에 대해 설명해주세요.
프로세스란 실행중인 프로그램입니다.
디스크에 파일로 존재하던 프로그램이 메모리에 올라가서 실행되면 프로세스가 됩니다.
프로세스의 메모리 공간에 대해 설명해주세요.
프로세스의 메모리 공간은 Code, Data, Heap, Stack으로 이루어져 있습니다.
Code는 실행할 프로그램 코드가 저장되며, CPU에서 수행되는 명령어를 저장하는 공간입니다.
Data는 정적변수, 배열, 구조체 등이 저장되는 공간입니다.
Heap은 동적 데이터가 저장되는 공간입니다.
Stack은 지역 변수와 인자, 함수의 리턴 주소가 저장되는 곳입니다. 함수 호출 시 프레임이 생성되고, 함수가 끝나면 반환됩니다.
OS는 프로세스를 제어하기 위해 프로세스 정보를 저장한다.
이를 PCB(프로세스 제어 블록)
이라고 한다.
등을 저장한다.
프로세스 제어블록(PCB)에 대해 설명해주세요.
프로세스 제어 블록이란 프로세스를 실행하는 데 필요한 정보를 담고 있는 자료 구조입니다.
PCB에는 어떤 정보가 담겨있을까요?
프로세스를 구분할 수 있는 식별자인 PID,
준비/대기/실행 등 프로세스의 상태를 나타내는 정보,
CPU가 다음으로 실행할 명령어를 가리키는 값인 PC 레지스터,
우선 순위, CPU 점유 시간 등에 대한 CPU 스케줄링 정보 등을 담고 있습니다.
새로운 프로세스는 기존 프로세스에서 fork()
함수를 호출해 생성한다.
부모 프로세스에서 fork()
함수를 호출하면 부모 프로세스는 자식 프로세스의 pid값을, 자식 프로세스는 0을 반환한다.
fork() 명령어에 대해 설명해주세요.
유닉스에서fork()
명령어는 새로운 프로세스를 생성하게 해주는 시스템 콜입니다.
fork()
시스템 콜을 통해 부모 프로세스의 내용을 그대로 복제한 자식 프로세스를 생성할 수 있습니다.
이때 부모 프로세스와 자식 프로세스의 주소 공간은 각각 따로 갖지만, 주소 공간 내에는 동일한 공간을 갖습니다.
모든 프로세스는 CPU에 의해 생성되고 소멸하는 과정을 거친다.
이 과정에서 프로세스는 생성
, 준비
,대기
,실행
,종료
라는 5가지 상태로 존재한다.
생성->준비
: 생성 상태의 프로세스가 OS로부터 승인을 받아, 준비 상태의 프로세스가 모여 있는 자료구조인 준비큐에 추가된다.
준비->실행
: 준비 큐에 있는 프로세스 중 우선순위가 높은 프로세스가 디스패치되어 실행된다.
실행->준비
: CPU 독점을 방지하기 위해 타임아웃되어 준비 상태로 변경된다.
실행->대기
: 입출력 또는 이벤트 때문에 대기 상태로 변경된다.
대기->준비
: 입출력 또는 이벤트가 완료되어 준비 상태로 변경된다.
실행->종료
: 실행 중인 프로세스가 정상적으로 끝나서 종료 상태로 변경된다.
프로세스 수행 상태 변화 과정에 대해 설명해주세요.
최초 상태인생성(new)
은 프로세스가 생성중인 상태입니다.
그 다음준비(ready)
상태는 OS로부터 승인을 받아 실행 가능한 상태이고,
CPU를 할당 받아 실제로 수행하는 상태는실행(running)
상태입니다.
프로세스가 수행 도중 I/O 요청을 하게 되면, I/O 요청이 완료될 때까지대기(block)
상태가 됩니다.
I/O 요청이 완료되면 다시준비(ready)
상태로 돌아갑니다.
마지막으로 프로세스가 종료된종료(terminated)
상태가 됩니다.
동시성
: 하나의 코어(싱글 토어)에서 여러 작업을 번갈아 가면서 처리하는 방식
하나의 CPU에서 여러 작업을 번갈아 가면서 처리하기 위해 처리 중인 작업을 교체하는 것을 콘텍스트 스위칭
이라고 한다.
병렬성
: CPU가 여러 개(멀티 코어) 있어서 각 CPU에서 각 작업을 동시에 처리하는 방식
응용 프로그램 하나를 여러 프로세스
로 구성하는 것을 의미한다.
멀티 프로세스 환경에서는 한 프로세스가 죽어도 다른 프로세스에 영향을 주지 않는다.
-> 응용 프로그램을 프로세스 하나로 구성하는 것보다, 여러 개로 구성하는 것이 안정적이다.
하지만 시간과 메모리 공간을 많이 사용한다는 단점이 존재한다.
처리 중인 프로세스를 교체하는콘텍스트 스위칭
작업이 이루어질 때 CPU에서 기존에 처리하던 프로세스가 할당 받은 메모리 영역을 다른 프로세스가 사용할 수 있게 교체하면서 시간과 메모리가 필요한데, 이를 오버헤드
라고 한다.
또한, 프로세스는 독립적인 메모리를 할당받는다.
따라서 프로세스 간에 공유할 자원이 있다면 IPC
를 통해 프로세스 간에 자원을 공유해야 한다.
(공유 메모리를 직접 참조하는 것보다 비효율적)
IPC
프로세스 간 통신(Inter-Process Communication, IPC)이란 뜻이며, 프로세스들 사이에 서로 데이터를 주고받는 행위 또는 그에 대한 방법이나 경로를 뜻한다.
여러 개의 작업을 동시에 처리하기 위해 fork()
시스템 호출을 사용하여 부모와 똑같은 프로세스를 생성하거나, exec()
시스템 호출로 프로세스를 전환하는 방법을 사용하는 것이 효율적이다.
하지만 fork()
시스템 호출은 낭비 요소가 많다.
fork()
시스템 호출로 프로세스를 복사하면, 코드 영역과 데이터 영역의 일부가 메모리에 중복되어 존재하며 부모-자식 관계이지만 서로 독립적인 프로세스이므로 이러한 낭비 요소를 제거할 수 없다.
즉, fork()
시스템 호출로 여러 프로세스를 만들게 되면 코드 일부, 프로세스 제어블록, 공유 변수가 메모리의 여러 곳에 중복되어 메모리가 낭비된다. (필요 없는 정적 영역이 여러 개가 된다.)
스레드는 이러한 낭비 요소를 제거하기 위해 사용된다.
비슷한 일을 하는 2개의 프로세스를 만드는 대신, 코드와 데이터 등을 공유하면서 여러 개의 일을 하나의 프로세스 내에서 하는 것이다.
하나의 프로세스 내에서 여러 개의 스레드를 생성하면, 코드와 파일 등의 자원이 공유되므로 자원의 낭비를 막고 효율성을 향상할 수 있다.
fork()
와exec()
의 차이
fork()
시스템 호출은 새로운 프로세스를 위한 메모리를 할당한다.
그리고 fork()를 호출한 프로세스를 새로운 공간으로 전부 복사하게 되고, 원래 프로세스는 원래 프로세스대로 작업을 실행하고 fork()를 이용해 생성된 프로세스도 그 나름대로 fork() 시스템 콜이 수행된 라인의 다음 라인부터 실행된다.반면
exec()
는 fork()처럼 새로운 프로세스를 위한 메모리를 할당하지 않고, `exec()를 호출한 프로세스가 아닌 exec()에 의해 호출된 프로세스만 메모리에 남게 된다.즉,
fork()
의 결과는 프로세스가 하나 더 생기는 것이다.(PID가 완전히 다른)
반면exec()
의 결과로 생성되는 프로세스는 없고, exec()를 호출한 프로세스의 PID가 그대로 새로운 프로세스에 적용되어 기존의 프로세스는 새로운 프로세스에 의해 덮어 쓰여지게 된다.
멀티 프로세스에 대해서 설명해주세요.
멀티 프로세스는 하나의 프로그램에서 동시에 여러 개의 프로세스를 실행하는 기술입니다.
하나의 부모 프로세스가 여러 개의 자식 프로세스를 생성하는 구조이며 서로 독립적인 메모리 공간을 가지고 있습니다.
그렇기에 프로세스는 다른 프로세스에게 영향을 줄 수 없습니다.
예를 들어 구글의 크롬 탭은 각각이 프로세스이며, 하나의 탭이 멈추더라도 다른 탭은 정상 작동합니다.
프로세스는 고유한 메모리 영역을 갖기 때문에 프로세스 간 자원을 공유해야 할 때 IPC 해야 한다.
즉, IPC는 프로세스 간에 자원을 공유하는 방식을 나타낸다.
대부분의 IPC 기법은 커널 공간을 활용하는 것이다.
커널 공간은 모든 프로세스가 공유하기 때문이다.
프로세스 간에 공유 가능한 메모리를 구성해 자원을 공유하는 방식이다.
데이터를 주고 받는 방법을 프로세스끼리 알아서 결정해야 하기 때문에 원시적인 방식이라고 한다.
공유 메모리를 사용하는 통신 방식의 가장 큰 문제는, 상대방이 데이터를 언제 보낼지 받는 쪽에서 모른다는 것이다.
그래서 데이터를 받는 쪽에서 수시로 상태 변화를 살피는 바쁜 대기를 해야 하는데, 이는 자원 낭비가 심하다.
바쁜 대기 문제를 해결하기 위해 데이터가 도착했음을 알려주는 동기화를 사용한다.
여러 프로세스에서 접근할 수 있으므로 동기화 문제가 발생할 수 있다.
대기가 있는 통신:
동기화를 지원하는 방식이다.
데이터를 받는 쪽이 데이터가 도착할 때까지 자동으로 대기 상태에 머물러 있다.
대기가 없는 통신:
동기화를 지원하지 않는 방식이다.
데이터를 받는 쪽은 바쁜 대기를 사용하여 데이터가 도착했는지 여부를 직접 확인한다.
컴퓨터와 컴퓨터가 네트워크로 연결된 경우의 통신에 주로 사용되는 수단이다.
소켓은 네트워크로 연결된 컴퓨터에서 데이터를 주고받기 위한 통신 기법이다.
파이프와 비교하면 소켓 방식은 초기화할 내용도 많고 시스템 자원도 많이 사용한다.
따라서 같은 컴퓨터 내에서 소켓으로 통신하는 것은 비효율적이다.
네트워크 소켓을 이용하는 프로세스 간 통신으로, 외부 시스템과도 이용할 수 있다.
클라이언트와 서버 구조로 자원을 주고받는다.
FIFO 형태의 메모리인 파이프
를 이용해 프로세스 간 자원을 공유하는 방식이다.
파이프는 프로세스 간 통신을 위해 운영체제가 제공하는 통신 기법이다.
보통의 경우에 파이프는 fork()
로 만들어진 부모-자식 간 통신에 사용된다.
파이프는 단방향 통신만 지원하므로 읽기 또는 쓰기 중 하나만 할 수 있다.
따라서 양방향 통신을 하려면 읽기 파이프와 쓰기 파이프를 각각 생성해야 한다.
하나의 컴퓨터 내에서 프로세스 간 통신에 많이 사용된다.
FIFO 형태의 큐 자료구조를 사용해 프로세스 간 메시지를 주고받는 방식이다.
프로세스끼리 협력하는 방법에 대해서 설명해주세요.
프로세스끼리 협력하는 IPC 방법에는 파이프 방식과 공유 메모리 방식 등이 있습니다.
파이프 방식은 프로세스 간 통신을 위해 운영체제가 제공하는 통신 기법으로, FIFO 형태의 메모리인파이프
를 이용해 프로세스 간 자원을 공유하는 단방향 통신 방식입니다.공유 메모리 방식은 시스템 콜을 통해 각 프로세스 간 공유하는 공간을 만들어, 프로세스 간 같은 공유 공간에 대해 읽고 쓸 수 있도록 하는 단방향 통신 방식입니다.
콘텍스트
: CPU가 처리하는 프로세스의 정보
CPU는 하나의 프로세스만 처리할 수 있다.
멀티 프로세스를 처리하려면 CPU 스케줄러에 의해 인터럽트가 발생하면서 콘텍스트 스위칭이 이뤄진다.
멀티 프로세스 환경에서 CPU가 처리 중인 프로세스의 정보를 바꾸는 것이 콘텍스트 스위칭(문맥 교환)
이다.
스케줄러는 레지스터에 있는 처리 중인 작업 정보를 P1의 PCB에 저장한다.
그리고 P2의 PCB에 있는 정보를 가져와 레지스터에 로드하고, CPU는 P2를 처리하기 시작한다.
위의 일을 하는 동안 CPU는 아무 일도 하지 못하게 된다.(유휴 상태)
이처럼 어떤 처리를 하는 데 간접적인 처리 시간과 메모리가 소요될 경우에 오버헤드가 발생한다.
고 한다.
멀티 스레드를 처리할 때도 콘텍스트 스위칭이 이뤄진다.
하지만, 멀티 스레드는 힙, 데이터, 코드 영역을 공유하므로 오버헤드가 적게 발생한다.
CPU에서 처리 중인 프로세스가 중간에 변경되어도 이전에 실행하던 코드를 이어서 실행할 수 있는 이유는 PCB에
프로그램 카운터(PC)
와스택 포인터
값이 저장되어 있기 때문이다.
프로그램 카운터(PC)
: 프로세스가 어어서 처리해야 하는 명령어의 주소 값
스택 포인터
: 스택 영역에서 데이터가 채워진 가장 마지막 주소 값
프로세스 문맥(process context)에 대해 설명해주세요
프로세스 문맥이란, 프로세스가 어떤 상태에서 수행되고 있는지에 대한 정보입니다.
문맥교환(context switch)에 대해 설명해주세요.
멀티 프로세스 환경에서 CPU가 프로세스를 변경할 때, 이전의 프로세스 상태를 PCB에 저장하고, 새로운 프로세스의 저장된 상태를 복구하는 작업입니다.
문맥교환은 언제 발생하나요?
일반적으로 한 프로세스의 타임 슬라이스가 끝날 경우 발생합니다. (라운드 로빈 방식)
타이머 인터럽트나 I/O 요청 시스템 콜이 들어왔을 때 발생합니다.
문맥 교환 발생 과정에 대해서 조금 더 상세히 설명해주세요.
사용자 프로세스가 CPU를 할당 받고 실행되던 중에, 타이머 인터럽트가 발생하면 CPU의 제어권은 운영체제에게 넘어가게 됩니다.
CPU의 제어권을 가지게 된 운영체제는 원래 수행 중이던 프로세스의 문맥을 PCB에 저장하고 새롭게 실행시킬 프로세스에게 CPU 제어권을 이양합니다.
이 과정에서 원래 수행 중이던 프로세스는 준비 상태로 바뀌고, 새롭게 CPU를 할당받은 프로세스는 실행 상태가 됩니다.