Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

TH3 6R3@T H@CK

프로세스와 스레드 본문

Study/CS

프로세스와 스레드

vvh0am1 2023. 10. 14. 16:49

※ 운영체제 수업 내용 복습
 
 

프로그램

저장장치에 저장되어 있는 정적인 상태

애플리케이션
컴퓨터 디스크에 저장되어 있는 상태
 
 

프로세스

실행을 위해 메모리에 올라온 동적인 상태

폰노이만 구조에 따라 CPU가 프로그램에 적혀 있는 코드를 line by line으로 실행하기 위해, 디스크에 저장되어 있는 코드나 데이터 등이 메모리에 실질적으로 적재되어 있는 상태
 
 

프로세스(Process)란?  "실행 중인 프로그램"

프로그램과 달리, 프로세스는 메모리에 주소 공간을 갖는 능동적 개체
∙ CPU 스케줄링을 할 때의 기본 처리 단위 → 프로세스 단위
∙ 프로세스 관리는 운영체제 입장에서 굉장히 중요한 일임
 
 

프로세스 제어 블록 (Process Control Block: PCB)

∙ 프로세스 관리를 위해 유지되는 레코드 데이터 블록으로, 메타데이터라고 볼 수 있음
→ 프로세스 관련 주요 정보들을 저장해 놓은 데이터 객체
∙ 프로세스는 고유의 PCB를 가짐
→ 프로세스별로 메타 정보들이 다르기 때
∙ CPU에서 수행 프로세스가 바뀔 때, 문맥 교환이 발생하는데, 이때 PCB 정보를 활용
프로세스 = 프로그램 + PCB
애플리케이션 = 파일 시스템에 저장되어 있는 코드나 데이터 + 메타 정보
 

프로세스 제어 블록: 프로세스 구조체 형태로 정의

∙ 이 구조체들의 연결 리스트를 통해 프로세스 간 관계를 유지
 
pid t pid; /* 프로세스 ID */
long state; /* 프로세스 상태 */
unsigned int time slice /* 스케줄링 정보 */
struct task struct *parent; /* 부모프로세스 */
struct list head children; /* 자식 프로세스 리스트 */
struct files struct *files; /* 오픈 파일 리스트 */
struct mm struct *mm; /* 프로세스 주소 공간 */
→ mm: memory management
 
* cf. task_struct 같은 데이터 구조체들을 grab 명령어로 정보 확인할 수 있음
 
 

프로세스 제어 블록의 구성

포인터: 준비 상태나 대기 상태의 큐를 구현할 때 사용
→ 특정 메모리 주소를 가리키는 형태의 변수
프로세스 상태: 프로세스가 현재 어떤 상태에 있는지를 나타내는 정보
프로세스 구분자: 운영체제 내에 있는 여러 프로세스를 구현하기 위한 구분자
→ pid (프로세스 id)
프로그램 카운터: 다음에 실행될 명령어의 위치를 가리키는 프로그램 카운터의 값
→ 다양한 컴퓨터 레지스터 중 하나
프로세스 우선순위: 프로세스의 실행 순서를 결정하는 우선순위
각종 레지스터 정보: 프로세스가 실행되는 중에 사용하던 레지스터의 값
→ PCB에 저장되어 있음
메모리 관리 정보: 프로세스가 메모리의 어디에 있는지 나타내는 메모리 위치 정보, 메모리 보호를 위해 사용하는 경계 레지스터 값과 한계 레지스터 값 등
할당된 자원 정보: 프로세스를 실행하기 위해 사용하는 입출력 자원이나 오픈 파일 등에 대한 정보
→ ex. fd(file descripter) 정보, 소켓 id 
계정 정보: 계정 번호, CPU 할당 시간, CPU 사용 시간 등
부모 프로세스 구분자와 자식 프로세스 구분자: 부모 프로세스를 가리키는 PPID와 자식 프로세스를 가리키는 CPID 정보
 
* 리눅스 환경에서 실행 중인 프로세스 정보를 확인하고 싶을 때 → ps command 이용
 
 

프로세스 실행 정보의 확인

Process Explorer, Sysinternals 등을 활용
→ 심층적인 정보 분석 가능
→ 윈도우에서 사용
 
 


프로세스의 상태

생성 상태

프로그램이 메모리에 올라오고 운영체제로부터 프로세스 제어 블록(PCB)을 할당받은 상태
→ 사용자의 애플리케이션 실행 행위를 통해 프로세스가 운영체제에 의해 생성
생성된 프로세스는 바로 실행되는 것이 아니라 준비 상태에서 자기 순서를 기다리며, 프로세스 제어 블록도 같이 준비 상태로 옮겨짐
 
 

준비 상태

실행 대기 중인 모든 프로세스가 자기 순서를 기다리는 상태
프로세스 제어 블록은 준비 큐에서 기다리며 CPU 스케줄러에 의해 관리
CPU 스케줄러는 준비 상태에서 큐를 몇 개 운영할지 큐에 있는 어떤 프로세스의 프로세스 제어 블록을 실행 상태로 보낼지 결정 → 프로세스 우선순위 값 고려 등
∙ CPU 스케줄러가 어떤 프로세스 제어 블록을 선택하는 작업은 dispatch(PID) 명령으로 처리
CPU 스케줄러가 dispatch(PID)를 실행하면 해당 프로세스가 준비 상태에서 실행 상태로 바뀌어 작업이 이루어짐
 
 

실행 상태

∙ 프로세스가 CPU를 할당 받아 실행되는 상태
→ 프로그램에 해당되는 코드들이 CPU 사이클에 맞춰 실행되는 상태
∙ 실행 상태에 있는 프로세스는 자신에게 주어진 시간, 즉 타임 슬라이스 동안 작업할 수 있음
→ 타임 슬라이스는 CPU 스케줄러 동작 방식에 따라 달라짐
그 시간을 다 사용하면 timeout(PID)가 실행되어 or 실행 과정 중 인터럽트가 발생하면 실행 상태에서 준비 상태로 옮김
실행 상태 동안 작업이 완료되면 exit(PID)가 실행되어 프로세스가 정상 종료
실행 상태에 있는 프로세스가 입출력을 요청하면 CPU는 입출력 관리자에게 입출력을 요청하고 block(PID)를 실행
block(PID)는 입출력이 완료될 때까지 작업을 진행할 수 없기 때문에 해당 프로세스를 대기 상태로 옮기고 CPU 스케줄러는 새로운 프로세스를 실행 상태로 가져옴
 

디스패치

∙ 준비 상태의 프로세스 중 하나를 골라 실행 상태로 바꾸는 CPU 스케줄러의 작업
 

타임아웃

∙ 프로세스가 자신에게 주어진 하나의 타임 슬라이스 동안 작업을 끝내지 못하면 다시 준비 상태로 돌아가는 것
 
 

대기 상태

실행 상태에 있는 프로세스가 입출력을 요청하면 입출력이 완료될 때까지 기다리는 상태
대기 상태의 프로세스는 입출력장치별로 마련된 큐에서 기다리다가 완료되면 인터럽트가 발생하고, 대기 상태에 있는 여러 프로세스 중 해당 인터럽트로 깨어날 프로세스를 찾는데 이것이 wakeup(PID)
wakeup(PID)로 해당 프로세스의 프로세스 제어 블록이 준비 상태로 이동
 

포인터

∙ 대기 상태에는 같은 입출력을 요구한 프로세스끼리 연결할 때 포인터 사용
 
 

완료 상태

∙ 프로세스가 종료되는 상태
코드와 사용했던 데이터를 메모리에서 삭제하고 프로세스 제어 블록(PCB)을 폐기
→ 운영체제 입장에서 실행이 끝난 프로세스를 위한 메타 정보를 관리하는 것은 비효율적임
정상적인 종료는 간단히 exit()로 처리
오류나 다른 프로세스에 의해 비정상적으로 종료되는 강제 종료를 만나면 디버깅하기 위해 종료 직전의 메모리 상태를 저장장치로 옮기는데 이를 코어 덤프(core dump)라고 함
→ ex. segmantation fault 발생 시
 
 

보류 상태

∙ 프로세스가 메모리에서 잠시 쫓겨난 상태
∙ 프로세스는 다음과 같은 경우에 보류 상태가 됨
    ∙ 메모리가 꽉 차서 일부 프로세스를 메모리 밖으로 내보낼 때 → 디스크로 잠깐 내보냄 (스왑 상태)
    ∙ 프로그램에 오류가 있어서 실행을 미루어야 할 때
    ∙ 바이러스와 같이 악의적인 공격을 하는 프로세스라고 판단될 때
    ∙ 매우 긴 주기로 반복되는 프로세스라 메모리 밖으로 쫓아내도 큰 문제가 없을 때
    ∙ 입출력을 기다리는 프로세스의 입출력이 계속 지연될 때
 
 


문맥 교환

∙ context switch (≒ 상태 교환)
CPU를 차지하던 프로세스가 나가고 새로운 프로세스를 받아들이는 작업
∙ 실행 상태에서 나가는 프로세스 제어 블록에는 지금까지의 작업 내용을 저장하고, 반대로 실행 상태로 들어오는 프로세스 제어 블록의 내용으로 CPU가 다시 세팅 (준비 상태 ↔ 실행 상태)
∙ 문맥 교환이 너무 빠르게 이루어지면 비효율적이고, 너무 느리게 이루어지면 아사 현상 발
Q. 문맥 교환이 너무 빠르게 이루어지면 비효율적인 이유? 시간 단축 효과가 있는 게 아닌지
A. ??
 
 


프로세스의 구조

코드 영역: 프로그램 코드가 저장되는 영역
데이터 영역: 전역 변수가 저장되는 영역
스택 영역: 함수 호출 과정에서 사용되는 지역 변수와 매개 변수가 저장되는 영역, 위에서 아래로 자람, last in first out 구조를 따름
힙 영역: 동적으로 사용자가 필요할 때 할당했다가 회수하는 용도로 쓰이는 영역, 아래에서 위로 자람
 
 

Last-In-First-Out 원리를 따르는 데이터 구조

스택에 데이터를 넣는 것을 Push, 빼는 것을 Pop
 
 

데이터, 코드 영역 외에 스택과 힙 영역이 있음

스택 영역: 함수 호출 시 생성되는 지역 변수 및 매개 변수가 저장
힙 영역: 동적으로 할당된 메모리를 관리
힙은 위로 (낮은 메모리주소에서 높은 주소), 스택은 아래로 (높은 주소에서 낮은 주소) 자란다
 
 


fork() 시스템 호출의 개념

실행 중인 프로세스로부터 새로운 프로세스를 복사하는 함수
실행 중인 프로세스와 똑같은 프로세스가 하나 더 만들어짐
→ 부모 프로세스를 fork()하면 똑같이 생긴 자식 프로세스 하나 생성
→ 똑같이 생겼지만 다른 PID 값을 가짐
 
 

fork() 시스템 호출의 동작 과정

fork() 시스템 호출을 하면 프로세스 제어 블록을 포함한 부모 프로세스 영역의 대부분이 자식 프로세스에 복사되어 똑같은 프로세스가 만들어짐
단, 프로세스 제어 블록의 내용 중 다음이 변경됨
    부모 프로세스 구분자와 자식 프로세스 구분자
    프로세스 구분자
    메모리 관련 정보
 
 

fork() 시스템 호출의 장점

∙ 프로세스의 생성 속도가 빠름
∙ 추가 작업 없이 자원을 상속할 수 있음
∙ 시스템 관리를 효율적으로 할 수 있음
 
 

fork() 시스템 호출의 예시

∙ 부모 프로세스의 코드가 실행되어 fork()를 만나면 똑같은 내용의 자식 프로세스를 하나 생성
∙ 이때 fork() 문은 부모 프로세스에 0보다 큰 값을 반환하고 자식 프로세스에 0을 반환
∙ 만약 0보다 작은 값을 반환하면 자식 프로세스가 생성되지 않은 것으로 여겨 'Error'를 출력
 
 

exec() 시스템 호출의 개념

∙ 기존의 프로세스를 새로운 프로세스로 전환(재사용)하는 함수
    ∙ fork(): 새로운 프로세스를 복사하는 시스템 호출
    ∙ exec(): 프로세스는 그대로 둔 채 내용만 바꾸는 시스템 호출
    → fork()를 해서 복사한 다음에 자식 프로세스에서 실행할 내용을 알려주는 형태의 시스템 호출
 
 

exec() 시스템 호출의 동작 과정

exec() 시스템 호출을 하면 코드 영역에 있는 기존의 내용을 지우고 새로운 코드로 바꿔버림
∙ 데이터 영역이 새로운 변수로 채워지고 스택 영역이 리셋
프로세스 제어 블록의 내용 중 프로세스 구분자, 부모 프로세스 구분자, 자식 프로세스 구분자, 메모리 관련 사항 등은 변하지 않지만 프로그램 카운터 레지스터 값을 비롯한 각종 레지스터와 사용한 파일 정보가 모두 리셋
 
 

exit() 시스템 호출

작업의 종료를 알려주는 시스템 호출
∙ exit() 함수를 선언함으로써 부모 프로세스는 자식 프로세스가 사용하던 자원을 빨리 거둬 갈 수 있음
exit() 함수는 전달하는 인자를 확인하여 자식 프로세스가 어떤 상태로 종료 되었는지를 알려 주는데, 인자가 0이면 정상 종료이고 -1이면 비정상 종료
 
 

wait() 시스템 호출

자식 프로세스가 끝나기를 기다렸다가 자식 프로세스가 종료되면 다음 문장을 실행하는 시스템 호출
부모 프로세스와 자식 프로세스 간 동기화에도 사용
 
 

유닉스의 프로세스 계층 구조

∙ 유닉스의 모든 프로세스는 init 프로세스의 자식이 되어 트리 구조를 이룸
 
 

프로세스 계층 구조의 장점

여러 작업을 동시에 처리할 수 있음
프로세스의 재사용이 용이
자원 회수가 쉬움
    프로세스를 계층 구조로 만들면 프로세스 간의 책임 관계가 분명해져서 시스템을 관리하기가 수월
 
 


스레드의 정의

CPU 스케줄러가 CPU에 전달하는 일 하나
CPU가 처리하는 작업의 단위는 프로세스로부터 전달받은 스레드
→ 스레드: 하나의 프로세스 내에서 프로세스를 여러 개의 하위 작업으로 쪼갠 하나하나를 부르는 명칭
    운영체제 입장에서의 작업 단위는 프로세스
    CPU 입장에서의 작업 단위는 스레드
 
 

프로세스와 스레드의 차이

∙ 프로세스끼리는 약하게 연결되어 있는 반면 스레드끼리는 강하게 연결되어 있음
→ 스레드는 하나의 프로세스 안에서 나눠져 있기 때문에 코드 영역, 소켓 디스크립터, 파일 디스크립터, 전역 변수 등을 서로 공유함
 

멀티태스크와 멀티스레드의 차이

멀티태스크: 여러 개의 프로세스로 구성된 것
멀티스레드: 하나의 프로세스에 여러 개의 스레드로 구성된 것
 
 

멀티스레드

프로세스 내 작업을 여러 개의 스레드로 분할함으로써 작업의 부담을 줄이는 프로세스 운영 기법
→ 애플리케이션을 구현하는 방법
 

멀티태스킹

운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법
 
 

멀티프로세싱

CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경
 
 

멀티태스킹의 낭비 요소

∙ fork() 시스템 호출로 프로세스를 복사하면 코드 영역과 데이터 영역의 일부가 메모리에 중복되어 존재하며, 부모-자식 관계이지만 서로 독립적인 프로세스이므로 이러한 낭비 요소를 제거할 수 없음
 
 

멀티태스킹과 멀티스레드의 차이

∙ fork() 시스템 호출로 여러 개의 프로세스를 만들면 필요 없는 정적 영역이 여러 개가 됨
∙ 멀티스레드는 코드, 파일 등의 자원을 공유함으로써 자원의 낭비를 막고 효율성 향상
 
 

멀티스레드의 장점

응답성 향상
자원 공유
효율성 향상
다중 CPU 지원
 
 

멀티스레드의 단점

모든 스레드가 자원을 공유하기 때문에 한 스레드에 문제가 생기면 전체 프로세스에 영향을 미침
인터넷 익스플로러에서 여러 개의 화면을 동시에 띄웠는데 그중 하나에 문제가 생기면 인터넷 익스플?
 
 

커널 스레드와 사용자 스레드

커널 스레드: 커널이 직접 생성하고 관리하는 스레드
사용자 스레드: 라이브러리에 의해 구현된 일반적인 스레드 
 
 

사용자 스레드

∙ 사용자 프로세스 내에 여러 개의 스레드가 커널의 스레드 하나와 연결 (1 to N 모델)
∙ 라이브러리가 직접 스케줄링을 하고 작업에 필요한 정보를 처리하기 때문에 문맥 교환이 필요 없음
∙ 커널 스레드가 입출력 작업을 위해 대기 상태에 들어가면 모든 사용자 스레드가 같이 대기하게 됨
∙ 한 프로세스의 타임 슬라이스를 여러 스레드가 공유하기 때문에 여러 개의 CPU를 동시에 사용할 수 없음
 
 

커널 스레드

∙ 하나의 사용자 스레드가 하나의 커널 스레드와 연결 (1 to 1 모델)
∙ 독립적으로 스케줄링이 되므로 특정 스레드가 대기 상태에 들어가도 다른 스레드는 작업을 계속할 수 있음
∙ 커널 레벨에서 모든 작업을 지원하기 때문에 멀티 CPU를 사용할 수 있음
∙ 하나의 스레드가 대기 상태에 있어도 다른 스레드는 작업을 계속할 수 있음
∙ 커널의 기능을 사용하므로 보안에 강하고 안정적으로 작동
∙ 문맥 교환할 때 오버헤드 때문에 느리게 작동
 
 

멀티레벨 스레드

∙ 사용자 스레드와 커널 스레드를 혼합한 방식 (M to N 모델)
∙ 커널 스레드가 대기 상태에 들어가면 다른 커널 스레드가 대신 작업을 하여 사용자 스레드보다 유연하게 작업을 처리할 수 있음
∙ 커널 스레드를 같이 사용하기 때문에 여전히 문맥 교환 시 오버헤드가 있어 사용자 스레드만큼 빠르지 않음
∙ 빠르게 움직여야 하는 스레드는 사용자 스레드로 작동하고, 안정적으로 움직여야 하는 스레드는 커널 스레드로 작동

'Study > CS' 카테고리의 다른 글

CPU 스케줄링  (0) 2023.10.14
컴퓨터 구조  (0) 2023.10.11