[OS] 프로세스? 프로그램?
프로그램과 프로세스
일상생활에서 프로그램이라는 말은 많이 사용한다. 그렇다면 프로세스는 무엇을 뜻하는 것일까?
어떠한 일의 흐름.과정. 일반적인 뜻으로는 그렇게 쓰이지만 프로그래밍 세계에서 프로세스의 의미는 약간 다르다.
그렇다면, 프로그램과 프로세스는 각각 어떤 의미를 가지고 있으며, 프로그램과 프로세스의 차이점은 무엇일까?
프로그램은 실행 시킬 수 있는 코드들이 들어있는 정적 상태의 파일이다.
컴퓨터에서 프로그램은 사용자가 원하는 일을 처리할 수 있도록 프로그래밍 언어를 사용하여 수행절차를 표현해놓은 명령어들의 집합으로,
그에 필요한 데이터들을 모아놓은 파일들이 보조 기억장치에 저장 되어있다.
프로세스는 이런 프로그램이 실행 되고 있는 상태 를 말한다. 프로그램을 실행하면, 운영체제로부터 실행에 필요한 자원을 할당받아 '프로세스' 가 되는 것이다. 이처럼 프로세스는 실행될 때 운영체제(OS)에 의해 다음과 같은 논리적 메모리 구조를 부여받는다.
🗂️ 프로세스의 메모리구조
- Text 영역 (코드 영역)
- 실행할 프로그램의 기계어 코드가 저장됨
- 읽기 전용 (Read-only)
- Data 영역
- 초기화된 전역 변수, static 변수 등이 저장됨
- BSS 영역
- 초기화되지 않은 전역 변수, static 변수 저장
- Heap 영역
- 프로그램을 만드는 사용자, 즉. 프로그래머가 직접 할당할 수 있는 저장공간
- 동적 메모리 할당 영역 (malloc, new 등으로 할당)
- 높은 주소로 할당
- Stack 영역
- 데이터가 일시적으로 저장되는 공간 (ex.매개변수, 지역변수)
- 함수 호출 시 생성되는 지역 변수, 리턴 주소 등 저장
- 낮은 주소로 할당
⚙️ 운영체제는 어떻게 프로세스에 메모리를 할당할까?
프로그램이 실행되면, 운영체제의 의해 호출이 되고 커널이 새로운 가상 메모리 공간을 할당한다. 이 구조는 프로세스마다 독립적으로 제공되기 때문에, 프로세스 간 메모리 침범은 원칙적으로 불가능하다.
프로그램이 동시에 여러개 실행될 수 있는 이유
컴퓨터의 '뇌' 라고 불리는 CPU 는 한 개당 한 개의 프로세스만 처리 할 수 있다.(한개의 코어기준)
하지만 우리가 보통 컴퓨터를 사용하면, 한 개의 프로그램만 실행 시키지 않는다.
액셀을 작성하다가 카카오톡을 하기도 하고, 다른 일을 하다가 공연 티켓팅을 위해 티켓팅도 할 수 있다.
우리 컴퓨터의 CPU 는 한 개당 한개의 프로세스만 처리하는데, 어떻게 우리는 여러 프로그램을 함께 사용할 수 있을까?
이렇게 멀티 태스킹을 할 수 있는 이유는 운영체제가 매우 빠르게 프로세스에 대한 CPU의 할당을 전환하기 때문이다.
즉, CPU 는 여전히 한 개당 한개의 프로세스만 처리하지만 ms 단위의 매우 빠른 속도로 프로세스를 전환하기 때문에
우리 눈에는 동시에 사용할 수 있는 것 처럼 보이는 것이다. 이러한 전환 과정을 '문맥 스위칭(Context Switching)' 이라고 부른다.
그럼 운영체제는 어떻게 이 Context Switching 을 통해 멀티 태스킹을 가능하게 하는걸까?
운영체제는 컨텍스트 스위칭 시, 현재 CPU 에 할당 된 프로세스의 실행을 멈추고 다른 프로세스를 실행 시키기 위해 CPU 상태를 저장하고 복원한다. 이처럼 프로세스는 여러 상태를 거치며 실행이 된다.
CPU가 원래 프로세스를 다시 실행하기 위해서는 레지스터값, 프로세스 상태, 메모리 맵 정보, I/O 상태 를 필요로 하는데 이 값들은 운영체제가 프로세스마다 생성하고 관리하는 자료구조인 PCB(Process Control Block)에 저장된다.
PCB(Process Control Block) 정보
- PID (Process 고유 ID)
- 레지스터 값 (PC)
- 프로세스 상태
- CPU 스케줄링 정보 (우선순위)
- 메모리 관련 정보
- 베이스 레지스터
- 한계 레지스터
- 페이지 테이블 정보
- TCB (Thread Control Block) 리스트
문맥 교환 (Switch Context)
ex) 프로세스 A 실행
|
프로세스 A의 문맥을 PCB에 저장
|
프로세스 B의 PCB로 부터 문맥 가져오기
|
프로세스 B 실행
|
프로세스 B의 문맥을 PCB에 저장
|
프로세스 A의 PCB로 부터 문맥 가져오기
|
프로세스 A 실행
프로세스의 상태
5가지로 나눠볼 수 있다.
1. 생성상태
- 이제 막 메모리에 적재되어 PCB 를 할당 받은 상태.
- 준비가 완료 되었다면, 준비 상태로 이동한다.
2. 준비상태
- 당장이라도 CPU를 할당받아 실행할 수 있는 상태.
- 자신의 차례가 된다면 실행 상태로 이동 (= 디스패치)
3. 실행상태
- CPU 를 할당받아 실행 중인 상태.
- 할당 된 시간이 끝나면 (= 타임 인터럽트) 준비 상태로 이동
- 실행 도중 입출력 장치 요청이 들어오면 대기 상태로 이동
4. 대기상태
- 프로세스가 실행 중 입출력 장치를 사용하는 경우
- 입출력 장치는 CPU 보다 속도가 느리기 때문에, 대기 상태로 들어옴
- 입출력 작업이 끝나면 (= 입출력 인터럽트) 실행 상태로 이동
5. 종료상태
- 프로세스가 종료된 상태
- PCB 및 프로세스의 메모리 영역 정리
프로세스의 계층 구조
윈도우는 프로세스 계층 구조를 사용하지 않지만, macOS, UNIX 는 프로세스를 계층적으로 관리한다.
부모 프로세스 : 새 프로세스를 생성시켜준 프로세스
자식 프로세스 : 부모 프로세스에 의해 생성된 프로세스
최초의 프로세스 : 모든 프로세스 중 가장 위에 있는 프로세스. PID가 1번이다.
최초의 프로세스 예시
macOS : launched
Linux : systemd
Unix : init
프로세스 생성 기법 (macOS의 생성 기법)
1) fork() : 부모 프로세스를 똑같이 복제한다. (PID 값은 다르다)
2) exec() : 새로운 값을 덮어씌운다.