학습 목표
•
프로세스 제어 블록이란
•
문맥 교환의 정의와 과정
•
프로세스는 메모리에 어떻게 배치되는지
•
프로세스 상태와 프로세스 계층 구조
•
스레드의 개념을 이해하고, 멀티프로세스와 멀티스레드
프로세스 개요
•
프로세스 = 실행 중인 프로그램
◦
실행 전의 프로그램 = 보조기억장치 속의 데이터 덩어리
◦
실행 중인 프로그램 = 메모리에 적재 된 프로그램 = 프로세스
•
포그라운드 프로세스, foreground process
◦
사용자가 보는 앞에서 실행되는 프로세스
•
백그라운드 프로세스, background process
◦
유닉스 체계 ⇒ 데몬, daemon
◦
윈도우 체계 ⇒ 서비스, service
프로세스 제어 블록
•
모든 프로세스는 실행되기 위해 CPU가 필요
◦
CPU 자원은 한정되어 있음
•
프로세스는 돌아가며 한정된 시간 동안만 CPU를 이용
◦
정해진 시간이 끝나면 끝났다고 알림 (타이머 인터럽트)
◦
타이머 인터럽트를 날리고 다음 차례가 올 때까지 기다린다
•
해당 과정을 위해 운영체제는 PCB를 이용한다
◦
PCB, Process Control Block, 프로세스 제어 블록
◦
프로세스와 관련된 정보를 저장하는 자료구조
◦
상품 태그처럼, 프로세스를 식별하기 위한 정보 포함
•
PCB는 커널 영역에서 생성된다
◦
사용자 영역에서 생성될 수 없다
•
PCB는 프로세스 생성 시에 만들어지고, 실행이 끝나면 폐기된다
◦
프로세스 자체와 생명주기를 같이 한다
PCB에 담긴 정보
프로세스 ID
PID, Process ID
•
프로세스를 식별하기 위해 부여하는 고유한 번호
•
같은 프로그램이라도 실행될 때마다 서로 다른 값 부여된다
레지스터 값
•
자신의 차례가 돌아오면 사용했던 레지스터의 중간값들을 모두 복원
◦
그래야 하던 일을 이어서 진행할 수 있다
◦
Program Counter를 포함하는 레지스터 값들 …
프로세스 상태
•
현재 프로세스의 상태
◦
입출력장치를 기다리는 상태인가?
◦
CPU를 사용하기 위해 기다리는 상태인가?
◦
현재 CPU를 이용하고 있는 상태인가?
CPU 스케쥴링 정보
•
프로세스가 언제, 어떤 순서로 CPU를 할당받을 지에 대한 정보
메모리 관리 정보
•
프로세스가 어느 주소에 저장되어있는가에 대한 정보
◦
프로세스마다 메모리에 저장된 위치가 다르다
◦
PCB에는 베이스 레지스터, 한계 레지스터 값과 같은 정보 있다
◦
페이지 테이블 정보도 담긴다
사용한 파일과 입출력장치 목록
•
프로세스가 실행 과정에서 사용한 입출력장치나 파일 → PCB에 명시됨 (기록됨)
◦
어떤 입출력장치가 이 프로세스에 할당 됐는 지
◦
어떤 파일이 이 프로세스에 의해 열렸는지
문맥 교환
•
문맥(context): 프로세스가 다음 차례에 하던 일을 이어할 수 있도록 기억해야하는 정보
•
하나의 프로세스 문맥은 해당 프로세스의 PCB에 표현
◦
PCB에 기록되는 정보 = 문맥 이라고 봐도 무관
•
인터럽트가 발생하면 운영체제는 해당 프로세스의 PCB에 문맥 업데이트
프로세스의 메모리 영역
•
프로세스가 생성되면 커널 영역에 PCB가 생성
•
사용자 영역에는 프로세스가 어떻게 배치될까?
코드 영역
Code segment, Text segment
•
코드 영역, 텍스트 영역
•
실행할 수 있는 코드 (기계어로 이루어진 명령어)가 배치
•
데이터가 아닌 CPU가 실행할 명령어가 담김
◦
쓰기는 금지된 영역 (읽기 전용, Read-only)
데이터 영역
Data segment
•
잠깐 썼다 지우는 게 아닌, 프로그램이 실행되는 동안 유지되어야 할 데이터가 저장되는 곳
◦
대표적으로 전역변수 (global variable)
코드 영역 + 데이터 영역
→ 크기가 변할 일이 없는 영역
⇒ 정적 할당 영역
힙 영역
Heap segment
•
프로그래머가 직접 할당할 수 있는 영역
◦
다 사용하면 꼭 반환해야한다
◦
반환 = 운영체제에 사용하지 않겠다고 알려주는 것
◦
반환하지 않으면 메모리 누수(memory leak) 발생
스택 영역
Stack segment
•
데이터를 일시적으로 저장하는 공간
◦
대표적으로 함수의 실행이 끝나면 사라질 지역 변수
힙 영역 + 스택 영역
실시간으로 크기가 변할 수 있다
⇒ 동적 할당 영역
프로세스 상태와 계층 구조
프로세스 상태
•
프로세스는 번갈아 가면서 실행되기 때문에 여러 상태를 거친다
•
운영체제는 PCB의 프로세스 상태를 인식하고 관리
생성 상태
new
•
프로세스를 생성중인 상태
•
이제 막 메모리에 적재되어 PCB를 할당받은 상태
•
실행할 준비가 완료되면 준비 상태로 바뀜 (바로 실행되는 게 아님)
준비 상태
ready
•
당장이라도 CPU를 할당받아 시작할 수 있지만, 차례를 기다리고 있는 상태
•
자신의 차례가 되면 CPU를 할당받아 실행 상태가 됨
디스패치(Dispatch)
준비 중의 프로세스가 실행 상태로 전환되는 것
실행 상태
running
•
CPU를 할당받아 실행 중인 상태
•
자신에게 할당된 시간을 모두 쓰면 (타이머 인터럽트가 발생하면)
◦
다시 준비상태가 된다
•
혹은, 실행 도중 입출력장치를 사용하여 입출력 장치의 작업이 끝날 때까지 기다려야하면
◦
대기 상태가 된다
대기 상태
blocked
•
실행 도중 입출력장치를 사용하는 경우
◦
입출력 작업은 CPU에 비해 매우 느리다
•
입출력 끝날 때까지 (입출력 완료 인터럽트를 받을 때까지) 기다려야 한다
◦
이렇게 기다리는 상태를 대기상태, blocked 라고 한다
•
입출력 작업이 완료되면 해당 프로세스는 다시 준비 상태가 된다
대기 상태의 일반적 정의
입출력이 유일한 이유는 아님. 특정 이벤트가 일어나길 기다릴 때 프로세스는 대기 상태가 된다. 다만, 프로세스가 대기 상태가 되는 대부분의 원인이 “입출력 작업” 이기 때문에 큰 차이는 없다
종료 상태
terminated
•
프로세스가 종료된 상태
•
프로세스가 종료되면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리한다
•
이런 도표를 프로세스 상태 다이어그램 (Process State Diagram)이라고 한다
프로세스 계층 구조
•
프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있다
◦
원래 프로세스: 부모 프로세스, parent process
◦
생성된 프로세스: 자식 프로세스, child process
◦
서로 다른 프로세스이기 때문에 다른 PID를 가진다
◦
일부 운영체제는 자식 프로세스에 부모의 PID를 PPID 값으로 기록하기도 한다
프로세스 생성 기법
복제와 옷 갈이입히기
•
fork, exec라는 시스템 호출 이용
•
부모는 fork를 통해 자신의 복사본을 자식 프로세스로 생성
◦
fork: 자신의 복사본을 만드는 시스템 호출
◦
부모의 프로세스 자원들 (메모리 내용, 열린 파일 목록 등) 상속
◦
다만 pid나 저장된 메모리 위치는 다르다
•
자식은 exec를 통해 자신의 메모리 공간을 다른 프로그램으로 교체
◦
exec: 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰는 시스템 호출
◦
즉, 새로운 프로그램 내용으로 전환하여 실행
◦
메모리 공간에 새로운 프로그램이 덮어 써진다는 점에서 옷 갈아입기
◦
코드 영역과 데이터 영역은 새로 실행할 프로그램의 내용으로 교체
◦
나머지 영역은 초기화
예시
•
bash에 ls 명령어를 쳤다
•
셸 프로세스는 fork → 자식 프로세스는 exec를 통해 ls 실행을 위한 프로세스로 전환
•
메모리 공간은 ls 명령어를 실행하기 위한 내용들로 채워짐
예시 2
•
만약 자식 부모 둘 다 exec를 호출하지 않는다면
•
같은 코드를 병행하여 실행하는 프로세스가 된다
스레드
•
스레드란 프로세스를 구성하는 실행 (흐름)의 단위이다
◦
하나의 프로세스는 여러 개의 스레드를 가질 수 있다
◦
스레드를 이용하면 하나의 프로세스에서 여러 부분을 동시에 실행 가능
프로세스와 스레드
•
하나의 프로세스가 하나의 흐름만 가지는 경우
◦
한 번에 하나의 부분만 실행
◦
⇒ 단일 스레드 프로세스
•
스레드라는 개념의 도입 → 프로세스를 구성하는 여러 명령어들을 동시에 수행 가능
•
스레드 = 프로세스를 구성하는 실행 단위
◦
스레드는 프로세스 내에서 각기 다른 스레드 ID, PC, 레지스터 값, 스택으로 구성
◦
각기 다른 레지스터 값, 스택 → 각기 다른 코드 실행 가능
•
스레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만 유지
◦
최대한의 프로세스 자원을 공유하며 실행 (스레드의 핵심)
리눅스의 프로세스와 스레드
리눅스는 프로세스와 스레드를 구분하지 않고 태스크(task)라는 이름으로 통일하여 명명
멀티프로세스와 멀티스레드
•
프로세스를 fork하여 같은 작업을 반복하면
◦
코드, 데이터, 힙 영역을 비롯한 모든 데이터 자원이 복제되어 메모리에 적재
◦
즉, PID와 저장된 메모리 주소를 제외한 모든 것이 동일한 프로세스 두 개가 통째로 메모리에 적재
◦
fork 10번이면 똑같은 애 10 개가 .. ⇒ 낭비!
•
멀티 프로세스
•
멀티 스레드
◦
코드, 데이터, 힙 영역 공유
◦
열린 파일과 같은 프로세스 자원 공유
◦
효율적인 메모리 사용, 서로 협력하여 통신하는 일에 유리
◦
단점: 하나의 스레드 문제 → 다른 스레드도 영향
프로세스 간 통신, IPC, Inter-Process Communication
각각의 프로세스는 서로 공유하는 메모리 영역을 두어 데이터를 주고받을 수 있다. 프로세스들이 공유할 수 있는 메모리를 공유 메모리(shared memory)라고 한다.
이 외에도, 소켓, 파이프 등을 통해 통신할 수 있다.