반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

프로세스 개념, 관리 본문

학교/운영체제

프로세스 개념, 관리

5_hyun 2021. 9. 16. 12:19
  • 프로세스 개념

프로세스: 실행 중인 프로그램
하드디스크에 프로그램이 저장되어 있다.
프로그램을 시작과정
1. 운영체제는 하드디스크에서 찾음
2. 메모리에 올리기 위해 프로세스로 바꿈
3. 메모리에서 비어있는 부분에 할당해서 저장
4. 저장되어있는 상태가 프로세스
5. cpu가 프로그램을 실행을 시켜준다.
6. 프로그램을 계속 실행하면 메모리 빈 공간에 할당한다.
7. 하지만 많이 실행하면 공간이 없다.
8. 그래서 만든 게 swap라는 하드디스크 공간을 만듦
9. 메모리가 꽉 차면 swap를 마치 메모리 같이 운영을 한다. 
10. 제일 만만한 프로세스를 잠시 swap로 옮긴다.
11. 그리고 더블 클릭한 프로세스를 메모리에 실행
12. 옮겨진 프로세스는 영원히 swap에 있을 수 없어서 언젠가 운영체제가 다시 메모리로 보내줌, 프로그램 실행을 하기 위해선 반드시 메모리에 있어야 한다. 하드디스크의 swap에 있으면 실행 불가

PCB(TCB) = process(task) contral block, 사람이 태어나면 주민등록번호를 받는 거처럼 프로세스가 처음 생성될 때 만들어지는 것, process ID(number), process state(상태 정보), program counter, 레지스터의 값들 등이 들어있음

하드디스크에서 프로세스로 되는 건 pcb 만들어지고 메모리에 프로세스가 생성되는 것을 의미

 

리눅스에서 top 명령어를 입력하면 위와 같은 창이 나오고 프로세스의 PCB 정보를 알 수 있다.

 

-브라우저 예시

크롬에서 탭을 여러개 생성

브라우저에서도 프로세스가 사용
성능을 높이고 장애 발생 시 hang(멈춤) 문제 해결하기 위해 각 탭 별로 프로세스를 만듦 -> 운영+안정성
ex) 수강 신청 사이트가 사람이 몰려서 hang이 걸리면 그 탭만 멈추고 다른 탭은 괜찮음

만약 각 탭 별로 프로세스를 나누지 않으면 다른 탭들도 먹통이 된다.
core cpu면 4개의 탭이 각각의 cpu에 할당되어 실행해 성능 향상


-크롬에서 3가지 프로세스
Brower(UI, Disk I/O, Network I/O)
Renderer(HTML, Javascript 처리)
Plug-in
각자 다른 역할을 줘서 하나가 먹통이 되어도 다른 건 사용 가능

 

-Process Image

프로세스 주소공간 구조

1. 스택
바뀌는 부분을 메모리의 나머지 부분에 저장
2. 힙
3. 데이터
4. 텍스트

 

C언어 프로그램 코드

int su;는 전역 변수, 데이터 부분에 저장됨
char *ptr;는 지역 변수, 스택에 저장됨, 지역 변수는 쓰다가 버릴 수 있다. 그래서 스택이라는 임시 저장 공간에 저장(push, pop으로 넣다 뺐다 함)
su = 15;와 ptr = malloc(5);는 코드라 텍스트 영역에 저장
ptr = malloc(5); 이 코드는 동적 할당, 만약 100번지에서 시작되는 주소라면 확보된 공간은 5byte이고 100번지라는 주소는 ptr(지역변수)에 저장, 5byte는 힙에 저장됨

 

코드는 무조건 텍스트 영역에 저장

-프로세스 분류

프로세스는 크게 2가지로 분류
1. 시스템(커널) 프로세스
운영체제를 부팅하면 자기가 해야 할 일을 프로세스로 나눠서 각각에 부여함

2. 사용자 프로세스
사용자가 생성하는 프로세스다.


프로세스가 여러 개면 멀티 프로세스, 프로세서가 프로세스들을 실행시켜준다.
p1이 단독 수행할 수도 있고 -> 독립 프로세스
p2, p3가 같이 협력되어 실행할 수도 있다 -> 협동 프로세스

 

-프로세스 상태

모든 프로세스는 상태를 가진다. 
1. PCB를 생성해서 메모리에 저장하고 Ready Queue라는 곳에 가서 운영체제가 줄을 세운다.
줄 서있는 라인을 대기줄(Ready Queue)라고 부른다.
2. cpu의 선택을 기다린다 -> 준비상태 
준비 상태: 프로세스가 아닌 PCB가 줄을 선다. 스캐줄러(디스패처, 선택해서 보내준다)가 PCB 선택을 해서 실행될 수 있도록 cpu에 보내줌, 즉 준비상태에서 실행 상태로 바뀜
3. 간단한 프로그램이면 빠르게 종료되고 PCB가 완료 상태로 바뀌면서 끝난다.
오래 걸리는 프로그램이면 계속 cpu 독점을 하게 할 수 없다. 그래서 뒤에 기다리는 PCB도 돌려야 해서 time out(인터럽트)가 발생해서 프로세스 실행을 중단시키고 강제로 Ready Queue의 마지막으로 보낸다. 그리고 다음 대기 중인 PCB를 cpu에 보내준다. 
강제 종료된 프로세스는 실행 상태 -> 준비 상태로 바뀜

 

실행 도중 입출력 요청이 발생한 상태

모든 프로세스는 레디 큐에 줄을 서고, 큐는 FIFO(first in first out) 특성을 가지고 있다.

1. 프로그램을 더블 클릭하면 프로세스 생성 상태
2. PCB가 신규로 만들어지고 레디큐에 가서 줄 서면 준비상태
3. 디스패치에 의해 PCB 선택이 되어지면 cpu할당을 받고 실행 상태로 전환
4. 특성 시간이 되면 타임 아웃돼서 레디큐의 맨뒤에 가서 줄 서고 준비 상태로 바뀜
5. 실행 도중에 입출력 요청이 발생(예로 read()함수) 기다리는 건 너무 비효율적이다. 시간이 많이 소요되는 입출력이 요청되면 중단시키고 대기 상태(보류)로 빠진다. 그리고 입출력이 완료가 될 때까지 대기 시킴, 준비가 완료되면 다시 레디큐에 가서 줄을 선다. 준비 상태가 되고 다시 디스패치되면 실행 상태로 바뀐다.

이 과정에서 PCB의 state부분의 값이 계속 바뀐다.

 

입출력연산이 지연될 때

swap이 대기실인데 멀리 있는 대기실, swap에 나가면 언제 들어올지 모른다. (입출력 개념이 아니다)
1. 입출력 연상이 장기 지속되거나 swap로 옮겨지면 보류 대기 상태가 된다.
2. 완료되면 보류 준비 상태가 된다 -> swap in(다시 메모리로 들어오는 상태)
3. 그러면 준비 상태로 바뀌고 다시 반복

 

이 과정은 전부 다 운영체제가 컨트롤한다 -> 성능 향상을 시키기 위해 

-프로세스 스케줄링(Process Scheduling)

디스패처가 디스패치라는 액션을 해준다, 프로세스 스케줄러라고도 한다.

레디큐에 있는 프로세스 중에서 프로세서(cpu)를 위해 프로세스를 선택하는 운영체제 프로세스=시스템 프로세스=커널 프로세스이다.
디스패처가 죽으면 어떠한 프로그램도 돌아가지 않는다.

 

-문맥 교환, Context Switch

디스패처가 p1을 선택해서 실행을 시켜줬는데 타임 아웃되면 p2는 실행, p1는 내쫓고 p2는 가져오고 스위치 해준다 이것을 context switth, 문맥 교환이라고 한다.

1. p1이 실행하다가 타임아웃이 일어남, 대책 없이 강제로 쫓아낼 수는 없음
만약 a=3+1, b=a+2가 있는데 a만 실행하고 타임 아웃이 되면 b를 실행시켜줘야 한다. 그러면 a까지 한 것을 기억해야 한다. (PCB에 기록)
2. 타임 아웃이 되면 Context Switch에서는 프로세스의 모든 상태 정보들을 PCB에다가 저장을 한다. cpu 내부에 레지스터들이 있다. 레지스터의 모든 정보가 pcb의 레지스터 부분에 저장된다.
그다음 선택할 p2 프로세스도 어디까지 수행했었는지 알아야 해서 pcb에 저장된 정보를 레지스터에 복원시키고 실행(이전에 실행했던 곳부터 시작)
3. 2번째 프로세스도 타임 아웃이 올 수 도 있다. 그러면 또 반복

 

p1-> 실행 준비 실행
p2-> 준비 실행 준비

-프로세스 교환, context switch가 언제 일어나는지
1) Interrupt: 타임 아웃되어 interrupt가 발생활 때
2) Trap: 하드웨어적인 인터렙, ex) 고장, 하드웨어 문제, 장애 발생, 어떤 걸 0으로 나누는 경우(0으로 나눌 수 없다)
3) System Call: 유저 모드에서 커널 모드로 바뀜, 사용자 프로그램이 실행되다가 시스템 콜을 만나면 커널 쪽의 프로세스가 실행되어야 한다.

context switch가 필요하지만 많이 일어나면 성능 저하가 발생될 수 있다. cpu가 액션을 해야 하기 때문, Context Switch에 많은 시간을 보내면 제 기능을 못한다.

 

-프로세스 구조

계층적 구조

1. 프로세스는 계층적인 구조를 갖는다.
2. 부팅을 하면 처음으로 만들어지는 프로세서가 root 자기의 자식 프로세스들을 만든다.

 

운영체제의 프로세스 관리에서 역할
프로세스 생성, 종료
제거
서스펜드(보류)
재시작
우선순위 변경(디스패처에 의해 선택)
보류(완전히 중단)
깨움

 

-프로세스 관리

사진처럼 프로세스를 프로그램에서도 만들수있다.
fork()는 프로세스 생성함수
함수는 서브 함수가 저장되어 있고 호출되어 실행되는 형태이지만 fork 시스템 콜 함수는 호출을 하면 시스템 콜이라서 커널로 전환되어 실행된다.

새로운 자식 프로세스를 생성해주는 작업을하고 끝나면 리턴한다. 리턴을 한번이 아닌 두번을 한다. 일반 함수는 리턴을 한번한다.
하지만 fork 함수는 2가지 값을 리턴한다. 0값이나 양수 값을 리턴한다. 양수 값은 부모 프로세스가 자식의 프로세스 아이디 값을 가지고 리턴한다(자식을 만들어서 할 일이 끝나서), 0값으로 리턴하는건 만들어진 자식 프로세스가 리턴을 한다.

B가 0을 리턴하면 E에 또 프로세스 생성, 양수를 리턴하면 C에 또 프로세스 생성

 

a는 프로세스라 pcb가 있음 
자식은 b 프로세스가 만들어짐 => 1. pcb를 만드는 것 2. 프로세스 이미지를 만드는 것
a의 이미지를 복사해서 b를 만듬(기본적인 것을 복사)
노란색 E에서 또 다른 자식을 만듬
=> 프로세스는 계층적인 구조를 띈다.

 

-예시

 

유닉스 운영체제 구조

root가 자식 프로세스 3개를 만들어준다, swapper: 메모리에서 하드디스크로 보내고 주는 역할

 

리눅스 운영체제 구조

리눅스도 systemd가 자식을 만들고 자식들이 자식을 만든다.

결국 운영체제 프로세스는 항상 계층적인 구조

 

-프로세스 종료(Termination)

1. 정상적인 종료
exit()라는 시스템 콜 함수가 실행되면 종료된다.
parent 프로세스가 abort()는 시스템 콜, B가 abort()로 종료하면 자식 프로세스도 다 정상 종료된다.

2. 비정상적인 종료
타임 아웃되서 종료되는 경우 -> 하드웨어적인 타임아웃, 파일 입출력 실패, 오류, 0으로 나눈경우, 메모리를 침범한 경우, 데이터 강제 접근시, 메모리 부족
비정상 종료되면 운영체제가 책임지고 후처리를 해줘야한다.

-비정상 종료시 문제점
정상적 시나리오: B 프로세스가 자식 E을 만듬, 부모 프로세스는 대부분 자식 프로세스를 만들고 일거리를 주고 결과를 보고받음 -> E가 일을 하고 B에게 보고


E가 비정상적 종료가 되면 B한테 결과 보고를 못함, B입장에선 E가 아직 살아있는줄 알음 -> E 프로세스를 좀비 프로세스라고 부른다.
좀비 프로세스는 메모리는 차지하만 실행은 안된다. 운영체제 입장에선 좀비 프로세스가 있으면 안된다. 좀비 프로세스를 주기적으로 찾아서 정리를 해야한다. 좀비 프로세스는 프로그램을 짜다가도 발생가능

B가 E를 만들고 B가 비정상적으로 죽은 경우: 모든 프로세스는 계층적이라서 부모가 없어지면 E가 단독으로 존재 불가, E는 고아 프로세스라고 부른다 =>계층적인 구조를 깨버림


운영체제별 해결방법

1. vms: B가 죽으면 자식을 다 죽인다.(=cascading termination)
2. 유닉스: 새로운 부모를 찾아서 입양 시켜줌, B 부모의 부모인 A를 새로운 부모로 연결해서 입양시켜준다.
3. 리눅스: 최상의 프로세스를 부모로 정해줌, 따라서 새로운 부모는 A가된다.
4. 모바일 안드로이드: 자원을 많이 사용하는 덜 중요한 프로세스부터 종료시켜준다.

 

-프로세스 우선순위(Priority)와 관리

PCB 내부에 우선순위 필드가 있다. cpu가 사용하기 위해 PCB가 줄을 서고 디스패처가 선택해준다. 이때 PCB의 우선순위를 보고 가장 우선 순위가높은 것을 선택한다. 숫자 낮은게 우선순위 높다고 가정하면 B 프로세스에게 가장 먼저 선택권을 준다.

우선순위는 운영체제가 결정을 해준다. 기본값+알파로해서 우선순위를 정해준다. 알파 값을 리눅스에서는 nice value라고 한다.

기본값 알파값 둘다 운영체제에서 정해주지만 알파값은 관리자가 변경이 가능하다. 기본값이 우선순위의 핵심이다.

 

-스레드(Thread)

프로세스 p1, p2, p3가 있다(멀티 프로세스) 디스패처가 프로세스를 선택해서 cpu로 보냄, 
코드 내용을 보니까 A줄은 B와 C에 영향을 안줌, B와 C도 다른 코드에 영행을 안준다.
그러면 A B C 를 각각 cpu1 cpu2 cpu3에 보내서 동시 실행하면 빨라짐 => 성능향상
a b c 를 조각으로 만드는 것을 스레드라고 부른다. 
process->threads로 더 잘게 분리

 

-스레드의 구조

스레드 1 2 3...n으로 쪼갬
내부를 보면 스레드 실행 환경 정보(레지스터 정보가 있다), 스택까지 하나의 스레드이고 이어서 프로그램 코드, 전역데이터, 힙으로 구성된다. 즉, 점선으로 된 것이 하나의 스레드
스레드2도 오른쪽 점선을 포함한것
오른쪽 코드, 전역 데이터, 힙 부분은 스레드끼리 공유를한다.

 

스레드의 실질적 구조
데이터 부분에 전역변수 저장
텍스트 부분에 프로그램 코드 저장(스레드별 코드 부별을 위해 포인터가 존재한다)
힙에 동적메모리 할당용으로 사용
같은 프로세스의 스레드들은 스레드끼리 주소공간 공유

나머지는 스레드 영역과 스택으로 구성

 

-스레드의 병렬수행

스레드는 궁극적으로 병렬 수행을 하기 위해 만듬
a. 프로세스 하나 안에 스레드 하나 -> 싱글 프로세스 싱글 스레드
b. 프로세스 하나 스레드 여러개 -> 싱글 프로세스 멀티 스레드
c. 프로세스 여러개 스레드 하나 -> 멀티 프로세스 싱글 스레드

b. 프로세스 여러개 스레드 여러개 -> 멀티 프로세스 멀티 스레드

가장 성능이 좋은 것은 d 멀티 프로세스 멀티 스레드이다.

장점
응답성 좋아짐 빠른 결과 보여줌
공유하면 따로 가지는 거보다 싸다 -> 경제성 좋음
고성능, 고효율

 

-단일 스레드 VS 다중 스레드

1. 싱글 프로세스 싱글 스레드
1code + resigters +stack 필요

2. 멀티 스레드 프로세스
맨위는 스레드 끼리 공유, 세로로 스레드 3개
1code+(registers+stack는 여러개 필요)


어떤 편집기 프로그램에서 내용을 보면 키보드 치는 부분과 디스크 i/o하는 부분 화면에 그리는 부분이 있다.
이걸 각각 따로 하기위해 스레드 3개를 만들어 각자 다른 임무를 준다. 스레드를 동시에 실행 시킬수있음

연관관계가 없어야 스레드로 분할할 수 있다. 만약 연관관계가 있는데 분리하면 오히려 비효율적

 

-Thread usage

 

-스레드 상태

스레드는 프로세스와 동일하게 상태 값이 있다, 프로세스와 거의 비슷하다
준비 -> 실행하면 실행상태 -> i/o하면 대기상태 반복하다 종료된다.

 

-Thread Control Block(스레드 제어 블록)

스레드 컨트롤 블록이 필요하다 프로세스에선(PCB), TCB에서 내용 정보를 저장
스레드는 프로그래머가 만들수있고 커널이 만들수있다. 프로세스도 마찬가지, 스레드도 fork 이용

 

-User level thread

프로그래머가 스레드를 만들어서 프로그램을 짜서 프로세스로 실행시킬떄 스레드를 유저 레벨 스레드라고 부른다.
만든 사람이 책임 져야함 따라서 사용자가 스레드 테이블을 만들고 TCB 정보를 저장하고 관리해야한다. 그러면 커널은 프로세스만 관리하게 된다. TCB를 프로세스 테이블에 저장하고 관리

사용자 스레드가 커널 스레드와 매핑 되어야 함 => n:1, 1:n 다대일 스레드 매핑이라 부른다
스레드가 커널 영역 개입없이 사용자 영역에서 실행되어야함

kernel level thread 보다 성능이 좋다

 

-Kernel level thread

커널에서도 쓰레드를 만든다, 사용자가 만들어 놓은 스레드를 커널에서 관리할 수 있다.
TCB를 스레드 테이블에 저장하고 관리 => 커널 레벨 스레드
대부분의 운영체제가 지원한다.
사용자가 스레드 만들면 커널도 스레드 만들어서 1:1 매핑을 시켜준다. 

문제점
사용자가 스레드를 만듬 -> 멀티 프로세스라 각각에서 스레드를 만들면 커널도 스레드를 계속 만들어야함-> 많이 만들면 커널 입장에선 성능 저하가 오히려 올 수 있다. 자원이 소모되기 때문이다.

 

-혼합형 방식(Hybird level thread)

커널 레벨 스레드+유저 레벨 스레드를 합친 버전
사용자가 스레드를 만듬 ->커널에선 사용자가 원하는데로 만들었다간 자기가 힘듬 -> 커널입장에선 최대 개수를 정해놓음

커널은 스레드를 미리 정해진 개수 만큼 만든다
미리 만들어진 커널스레드와 매핑을 시켜준다.
더이상 필요없으면 매핑을 끊음 ->커널이 남는다 -> 다른 필요한 스레드와 연결시켜줌
자원의 낭비 줄이고 효율적인 처리 가능
=> 역할을 경량 프로세스 스레드가 담당하게 만들어 놓음, n:m구조를 가질 수 있다.

 

 

728x90
반응형
Comments