[혼공컴운] Ch10. 프로세스와 스레드
강민철 - 혼자 공부하는 컴퓨터구조 운영체제
책을 읽으며 개인적으로 정리한 내용입니다.
목차
- 프로세스 개요
- 프로세스 직접 확인하기
- 프로세스 제어 블록
- 문맥 교환
- 프로세스의 메모리 영역
- 프로세스 상태와 계층 구조
- 프로세스 상태
- 프로세스 계층 구조
- 프로세스 생성 기법
- 스레드
- 프로세스와 스레드
- 멀티프로세스와 멀티스레드
✅ 프로세스 개요
프로세스 : 실행중인 프로그램
보조기억장치에 저장된 프로그램을 메모리에 적재하고, 실행하면
프로그램은 프로세스가 된다. (프로세스를 생성한다고 표현)
⏺ 프로세스 직접 확인하기
컴퓨터 부팅 순간부터 수많은 프로세스가 실행된다.
윈도우의 작업관리자나 유닉스계열의 ps 명령어로 확인 가능하다
✔️ 포그라운드 프로세스
(사용자가 볼 수 있는) 앞에서 실행되는 프로세스
✔️ 백그라운드 프로세스
(사용자가 볼 수 없는) 뒤에서 실행되는 프로세스
유닉스 계열에서는 = 데몬 이라고 부른다.
윈도우 OS에서는 = 서비스 라고 부른다.
⏺ 프로세스 제어 블록
모든 프로세스는 실행을 위해 CPU가 필요하다
그러나 CPU 자원은 한정되어 있다. (모든 프로세스가 동시에 CPU를 사용하는건 불가능)
프로세스는 차례대로 돌아가면서 한정된 시간을 CPU를 이용하는데,
1) 시간만큼 CPU 이용
2) 타이머 인터럽트 (끝나는걸 알려줌) 가 발생
3) 그만 사용하고, 다음 자기 차례가 올 때까지 기다린다.
⬛️ PCB
운영체제는 프로세스 제어 블록 Process Control Block을 이용한다.
- 프로세스 실행 순서를 관리
- 자원 배분을 위해
PCB : 프로세스와 관련된 정보를 저장하는 자료구조
메모리는 커널/사용자 영역으로 나뉘어있는데 (커널영역이 CPU에 접근하는 영역)
PCB는 커널 영역에 생성된다.
✔️ PID : 프로세스 아이디 (식별자)
같은 프로그램이더라도 두번 실행되면 PID가 다른 두개의 프로세스가 생성된다.
✔️ 레지스터 값
프로세스는 실행차례가 돌아오면 이전까지 사용했던 레지스터의 중간값을 복원한다.
이전 작업을 이어받아 뒤를 처리하기 위함.
(사용했던 프로그램 카운터와 레지스터 값들..)
✔️ 프로세스 상태
프로세스가 어떤 상태인지 기록되어야한다.
- 입출력장치를 사용하기 위해 기다리고 있는 상태인지
- CPU 이용하고 있는 상태인지
- CPU를 기다리고 있는 상태인지 ... 등
✔️ CPU 스케쥴링 정보
프로세스가 언제 어떤 순서로 CPU를 할당 받을지에 대한 정보
✔️ 메모리 관리 정보
프로세스마다 메모리에 저장된 위치는 다르다.
(그래서 어느 주소에 저장되어있는지 정보가 필요함)
- 베이스 레지스터, 한계레지스터, ...
- 페이지 테이블 정보 등
✔️ 사용한 파일, 입출력장치 목록
- 어떤걸 사용했었는지, 어떤 파일을 열었었는지 등
⏺ 문맥 교환
A 프로세스에서 B 프로세스로 실행순서가 넘어가면 발생하는 일을 보면
프로그램 카운터, 레지스터값, 메모리정보, 실행위해 열었던 파일이나 입출력장치 정보를 백업한다.
이런 정보들을 문맥 (Context)라고 한다.
하나의 프로세스 문맥은 해당 프로세스 PCB에 표현되어 있으며, PCB에 기록되는 정보들이 곧 문맥이다.
⬛️ 문맥교환
1) 프로세스A에서 인터럽트 발생시 A 문맥 백업
2) 다음 실행될 프로세스 B의 문맥복구
* 문맥교환이 너무 자주 발생하면 오버헤드가 발생할 수 있다.
* 오버헤드 : 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리
⏺ 프로세스의 메모리 영역
프로세스 생성되면
> 커널 영역에 PCB가 생성되는데
> 사용자 영역에는 프로세스가 어떻게 배치될까?
각영역에 대해 알아보자!!! 중요한 개념!!!
✔️ 코드영역
실행할 수 있는 코드(기계어 명령어) 저장
> 데이터가 아닌 CPU가 실행할 명령어가 저장되어있어서 Write는 금지된다.
Read- Only 공간
✔️ 데이터영역
잠깐 썼다가 없앨 데이터가 아닌,
프로그램이 실행되는 동안 유지할 데이터가 저장된다.
- 전역변수 static
** 코드 영역과 데이터영역은 크기가 고정된 영역 (정적할당영역)이다.
✔️ 힙영역
프로그래머가 직접 할당 할 수 있는 저장공간
프로그래밍 중 힙영역에 메모리 공간을 할당했다면 해당공간을 반환해야한다.
> 더이상 이 메모리 공간을 사용하지 않겠다고 OS한테 말하는 것임
만약 메모리 공간 반환 안하면 메모리 내에 계속 남아 메모리 낭비가 초래된다.
* 이를 메모리 누수 라고 한다.
✔️ 스택영역
데이터를 일시적으로 저장하는 공간
잠깐 쓰다가 말 값들이 저장된다.
- 매개변수. 지역변수
** 힙 영역과 스택 영역은 실시간으로 그 크기가 변할 수 있어서 동적할당영역이다.
이러한 이유로 힙과 스택영역은 주소가 겹치지 않기 위해
힙영역은 낮은 주소부터 높은 주소로 할당
스택 영역은 높은 주소부터 낮은 주소로 할당된다.
✅ 프로세스 상태와 계층 구조
여러 프로세스들은 빠르게 번갈아 가며 실행되는데
이 과정속에서 프로세스는 여러가지 상태를 거치며 실행된다.
운영체제마다 상태 표현 방식은 다르다)
⏺ 프로세스 상태
✔️ 생성 (new)
프로세스 생성중 상태
막 메모리에 적재되어 pcb 할당받은 상태
생성상태를 거치고 실행 준비가 된 프로세스는 곧바로 실행되지 않고, 준비상태로 된다. (CPU 할당을 기다린다)
✔️ 준비 (ready)
당장이라도 CPU를 할당받아 실행 가능하지만, 아직 자신의 차례가 아니다.
* 디스패치 : 준비 상태인 프로세스가 실행상태로 변하는것
✔️ 실행 (running)
CPU를 할당받아 실행중인 상태
할당된 일정 시간 동안만 CPU를 사용할 수 있다.
- 할당 시간 모두 사용으로 타이머 인터럽트 발생시 준비 상태로 변경된다.
- 실행중 입출력장치 사용시 입출력 장치 작업이 끝날떄까지 기다리는, 대기 상태가 된다.
✔️ 대기 (blocked)
입출력작업은 CPU에 비해 처리 속도가 느리다.
따라서 프로세스 실행 중 입출력 작업에 들어갔다면 , 입출력 완료 인터럽트를 받을 떄 까지 기다린다.
입출력 작업이 완료되면 준비 상태로 되며 CPU할당을 기다린다.
✔️ 종료 (terminated)
프로세스가 종료된 상태
PCB와 사용한 메모리를 정리한다.
⏺ 프로세스 계층 구조
부모 프로세스와 자식 프로세스
프로세스는 시스템 호출을 통해 다른 프로세스를 생성할 수 있다.
다른 프로세스라서 다른 PID를 가진다.
PPID : Parent PID 가 기록되기도 한다 (일부 운영체제)
실행되는 최초의 프로세스가 자식 프로세스들을 생성하고, 자식 프로세스들이 새로운 프로세스들을 실행하다보면...
다음과 같은 계층 구조 (트리구조)가 되고, 여러 프로세스들은 동시에 실행된다.
example
컴퓨터 키고 로그인 창을 통해 로그인해서 bash 셸로 VIM(문서 편집기)을 실행함
1) 컴퓨터 킨 순간의 최초 프로세스는 로그인 담당 프로세스를 자식으로 생성
2) 로그인 프로세스는 사용자 인터페이스 bash 셸을 자식으로 생성
3) bash셸은 Vim프로세스를 자식으로 생성
모든 프로세스 가장 위에 있는 최초의 프로세스
pid가 1번이다.
- 유닉스 init
- 리눅스 systemd
- mac launchd
⏺ 프로세스 생성 기법
부모는 어떻게 자식 프로세스를 만들어낼까?
또 자식은 어떻게 자신의 코드를 실행할까?
자식 프로세스는 fork(복제), exec(옷갈아입기)를 통해 실행된다.
둘다 시스템 호출이다!
✔️ fork
자기 자신의 복사본을 만드는 시스템 호출
복사본이 자식 프로세스!
부모는 fork를 통해 자신의 복사본을 자식 프로세스로 생성한다.
복사본은 부모 프로세스의 자원, 메모리 내용, 열린 파일등을 갖고 있고,
이 내용들은 자식 프로세스에 상속된다.
✔️ exec
자신의 메모리 공간을 새로운 프로그램으로 덮어쓰기
새로운 프로그램 내용으로 전환해 실행한다.
- 코드영역, 데이터영역이 실행할 프로그램의 내용으로 변경
- 나머지 영역은 초기화
즉 자식 pid를 받고, 이내용이 초기화 되면서 새로운 프로그램이 로딩되는것..
✅ 스레드
프로세스를 구성하는 실행의 흐름 단위
하나의 프로세스는 여러개의 스레드를 가질 수 있다.
!!!크롬창에 여러개의 창을 띄울수 있는것!!!
스레드, 멀티스레드, 멀티프로세스까지 알아보자.
⏺ 프로세스와 스레드
전통적인 관점에서 하나의 프로세스가 하나의 일만 처리했었음 (단일 스레드 프로세스)
스레드라는 개념이 도입되며 하나의 프로세스는 한번의 여러개의 일을 처리할 수 있게 됨
스레드는 프로세스 내에서 각자의 스레드ID, PC, 레지스터값, 스택으로 구성된다
프로세스의 스레드들은 실행에 필요한 최소한의 정보만을 유지한 채 프로세스 자원을 공유하며 실행된다.
코드/데이터/힙영역은 스레드 123이 공유하고 있다.
⏺ 멀티프로세스와 멀티스레드
멀티프로세스 : 여러개의 프로세스를 동시에 실행
멀티스레드 : 여러개의 스레드로 프로세스를 동시에 실행
아래를 보자
1) 한개의 프로세스를 fork하여 실행하면 3번 hello가 출력된다.
2) 스레드를 세개 만들어 실행해도 hello는 3번 출력된다.
둘의 차이는 <자원의 공유>여부이다.
fork를 한후 동시 실행하면
코드/데이터/힙/등 모든 자원이 메모리에 적재되며 동일한 내용들이 메모리에 중복해 존재하게 된다. (낭비)
* 쓰기시 복사 (copy on write) 기법도 있다.
스레드들은 프로세스가 가진 자원을 공유하기 떄문에 메모리를 더 효율적으로 사용할 수 있다.
서로 협력하고 통신하는 것에도 유리하다.
단 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 생길수 있다는 단점도 있다.
references
혼자 공부하는 컴퓨터구조 운영체제 (강민철)