[OS] 프로세스와 스레드
프로세스의 개념
프로세스 : 메모리에 적재되어 CPU에서 실행중인 프로그램
프로그램에서 프로세스로의 전환
프로세스 제어 블록; Process Control Block (PCB)
특정한 프로세스를 관리한 필요가 있는 정보를 포함하는 운영체제 커널의 자료구조. PCB는 운영 체제가 프로세스를 표현한 것이라 할 수 있음.
프로세스는 고유의 프로세스 제어 블록을 가짐
다음과 같은 항목을 저장하고 있다.
- Process Id : 프로세스의 고유 번호
- Process State : ready, wait, running 등의 실행 상태
- Program Counter(PC) : 프로그램 카운터, 다음 실행될 명령의 포인터
- CPU registers : CPU 레지스터
- CPU scheduling information : CPU 스케줄링 정보
- Memory-management information : 할당된 자원 정보
- Accounting information : CPU 사용시간 등
- I/O status information : 입출력 상태 정보
프로세스의 네 가지 상태
- 생성 상태 create status : 프로세스가 메모리에 올라와 실행 준비를 완료한 상태, PCB가 생성
- 준비 상태 ready status : 생성된 프로세스가 CPU를 얻을 때까지 기다리는 상태 준비 상태의 여러 프로세스 중 다음에 실행할 프로세스를 선정하는 일은 CPU 스케줄러가 담당
- 디스패치 dispatch : 준비 -> 실행 상태로 바꾸는 CPU 스케줄러의 작업
- 타임 아웃 time out : 프로세스에 배당된 작업 시간인 타임 슬라이스(타임 퀀텀) 내에 작업을 끝내지 못해 다시 준비 상태로 돌아가는 것 -> 클록으로부터의 인터럽트
- 실행 상태 running status : 준비 상태에 있는 프로세스 중 하나가 CPU를 얻어 실제 작업을 수행하는 상태, 주어진 시간 내에 작업을 끝내지 못하면 준비 상태로 돌아감
- 완료 상태 terminate status : 실행 상태의 프로세스가 주어진 시간 내에 작업을 마치면 완료 상태로 진입, PCB가 사라진 상태
프로세스의 다섯 가지 상태
- 생성 상태 create status : OS로부터 PCB를 할당 받은 상태
- 준비 상태 ready status : PCB는 준비 큐에서 기다리며 CPU 스케줄러에 의해 관리
- 실행 상태 running status : 프로세스가 CPU를 할당받아 실행되는 상태, 타임 슬라이스 동안 작업
- 대기 상태 blocking status : 실행 상태에 있는 프로세스가 입출력을 요청하면 입출력이 완료될 때까지 기다리는 상태, 입출력장치별로 마련된 큐에서 대기
- 완료 상태 terminate status : 프로세스가 종료되는 상태, 코드와 데이터를 메모리에서 삭제하고 PCB를 폐기
- 코어 덤프 core dump : 비정상적으로 종료되는 강제 종료를 만나면 디버깅하기 위해 강제 종료 직전의 메모리 상태를 저장장치로 옮기는 것
휴식 상태
프로세스가 작업을 일시적으로 쉬고 있는 상태. 메인 메모리에 PCB도 그대로 있고 프로세스의 데이터도 유지되기 때문에 resume 명령어를 통해서 재시작할 수 있다.
보류 상태
프로세스가 메모리에서 잠시 쫓겨난 상태
- 메모리가 꽉 차서 일부 프로세스를 메모리 밖으로 내보낼 때
- 프로그램에 오류가 있어서 실행을 미루어야 할 때
- 바이러스와 같이 악의적인 공격을 하는 프로세스라고 판단될 때
- 매우 긴 주기로 반복되는 프로세스라 메로리 밖으로 쫓아내도 큰 문제가 없을 때
- 입출력을 기다리는 프로세스의 입출력이 계속 지연될 때
보류 상태를 포함한 프로세스의 상태
문맥 교환 (Context Switching)
CPU가 현재 작업 중인 프로세스에서 다른 프로세스로 넘어갈 때 지금까지의 프로세스의 상태를 저장하고, 새 프로세스의 저장된 상태를 다시 적재하는 작업을 Context Switch(문맥 교환)이라 한다. (프로세스의 정보는 PCB에 저장된다.)
문맥 교환 과정
- 요청 발생: 인터럽트 또는 트랩에 의한 요청이 발생.(트랩은 소프트웨어 인터럽트)
- PCB에 저장: 운영체제는 현재 실행중인 프로세스(P0)의 정보를 PCB에 저장.
- CPU 할당: 운영체제는 다음 프로세스(P1)의 정보를 PCB에서 가져와 CPU를 할당.
위 과정을 반복적으로 수행한다. Context Switching하는 동안 CPU는 아무일도 하지않는 시간이 발생하는데 이를 오버헤드(Overhead)라 하고 오버헤드가 잦아지면 성능이 떨어질수 있다.
프로세스의 구조
- data: 전역 변수/초기화된 데이터가 저장되는 영역
- stack: 임시 데이터(함수 호출, 로컬 변수 등)가 저장되는 영역
- heap: 코드에서 동적으로 생성되는 데이터가 저장되는 영역
프로세스의 생성과 복사
fork
fork() 시스템 콜이 실행되면, 해당 프로세스와 거의 동일한 프로세스가 복제됨. 결과적으로 원본 프로세스 부모 프로세스, 복제된 프로세스는 자식 프로세스가 되며 fork() 이후부터 다시 순서대로 코드가 실행됨.
fork 장점
프로세스 생성 속도가 빠르다. (새로 프로그램을 가져오지 않고 기존 메모리에서 복사하기 때문)
추가 작업 없이 자원을 상속할 수 있다.
시스템 관리를 효율적으로 할 수 있다.
자식 프로세스가 종료하면 자식이 사용하던 자원을 부모 프로세스가 정리할 수 있다. 서로 연결되어 있기 때문인데, 정리를 부모 프로세스에 맡김으로써 시스템이 효율적으로 관리된다.
프로세스의 전환
exec()
exec 시스템 콜은 fork() 처럼 새로운 프로세스를 위한 메모리를 할당하지 않고 exec()를 호출한 프로세스의 메모리에 새로운 프로세스의 코드를 덮어씌워 버린다. 따라서 exec를 호출한 프로세스가 아닌 exec에 의해 호출된 프로세스만 메모리에 남게 된다. 간단히 말하면, fork의 결과는 프로세스가 하나 더 생기는 것이다. 물론, 프로세스 id(pid)도 완전히 다른 또 하나의 프로세스가 생긴다. 반면, exec 실행의 결과 생성되는 새로운 프로세스는 없다. exec를 호출한 프로세스의 pid가 그대로 새로운 프로세스에 적용이 되며, exec를 호출한 프로세스는 새로운 프로세스에 의해 덮어 쓰여지게 된다.
프로세스 계층 구조
유닉스 시스템의 일반적인 프로세스 계층 구조
부모 프로세스가 여러 개의 자식 포레스를 생성하면 계층 구조를 형성함
프로세스 계층 구조의 장점
- 여러 작업을 동시에 처리할 수 있다.
- 프로세스의 재사용이 용이하다.
- 자원 회수가 쉽다. - 프로세스를 계층 구조로 만들면 프로세스 간의 책임 관계가 분명해져서 시스템을 관리하기가 수월
고아 프로세스
- 부모 프로세스가 자식 프로세스보다 먼저 종료되는 경우 부모 프로세스가 없는 자식 프로세스를 말합니다.
- 운영체제는 이러한 고아 프로세스를 허용하지 않으며 부모 프로세스가 먼저 종료되면 자식 프로세스의 새로운 부모 프로세스로 init(PID = 1)가 설정됩니다.
- init 프로세스는 자식 프로세스가 종료될 때까지 기다린 후 wait 함수를 호출하여 고아 프로세스의 종료 상태를 회수하여 좀비 프로세스가 되는 것을 방지합니다.
- 고아 프로세스는 프로세스 자신이 시스템의 자원을 낭비할 수 있고, 시스템이 프로세스가 종료될 때까지 추적을 해야 하기 때문에 성능 저하의 원인이 됩니다.
스레드의 개념
스레드의 정의
프로세스 내에서 작업을 수행하는 주체
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스라 함
프로세스와 스레드의 차이
운영체제가 프로세스에게 Code/Data/Stack/Heap 메모리 영역을 할당해 주고 최소 작업 단위로 삼는 반면, 스레드는 프로세스 내에서 Stack 메모리 영역을 제외한 다른 메모리 영역을 같은 프로세스 내 다른 스레드와 공유한다.
프로세스는 다른 프로세스와 정보를 공유하려면 IPC를 사용하는 등의 번거로운 과정을 거쳐야 하지만, 스레드는 기본 구조 자체가 메모리를 공유하는 구조이기 때문에 다른 스레드와 정보 공유가 쉽다. 때문에 멀티태스킹보다 멀티스레드가 자원을 아낄 수 있게 된다. 다만 스레드의 스케줄링은 운영체제가 처리하지 않기 때문에 프로그래머가 직접 동기화 문제에 대응할 수 있어야 한다.
멀티태스크와 멀티스레드
- 멀티태스크
여러 개의 프로세스로 구성된 것 - 멀티태스킹
운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법 - 멀티스레드
하나의 프로세스에 여러 개의 스레드로 구성된 것
프로세스 내 작업을 여러 개의 스레드로 분할함으로써 작업의 부담을 줄이는 프로세스 운영 기법 - 멀티프로세싱
CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경
멀티스레드 장점
- 장점
응답성 : 프로그램의 일부분(스레드)이 중단되거나 긴 작업을 수행하더라도 프로그램의 수행이 계속 되어 사용자에 대한 응답성이 증가한다.
ex) 멀티 스레드가 적용된 웹 브라우저 프로그램에서 하나의 스레드가 이미지 파일을 로드하고 있는 동안, 다른 스레드에서 사용자와 상호작용 가능
경제성 : 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 공간과 시스템 자원 소모가 줄어든다. 스레드 간 통신이 필요한 경우에도 쉽게 데이터를 주고 받을 수 있으며, 프로세스의 context switching과 달리 스레드 간의 context switching은 캐시 메모리를 비울 필요가 없기 때문에 더 빠르다.
멀티프로세서 활용 : 다중 CPU 구조에서는 각각의 스레드가 다른 프로세서에서 병렬로 수행될 수 있으므로 병렬성이 증가한다.
- 단점
임계 영역(Critical Section)? 둘 이상의 스레드가 동시에 실행하면 문제를 일으키는 코드 블록. 공유하는 자원에 동시에 접근하는 경우, 프로세스와는 달리 스레드는 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다. 따라서 동기화가 필요!
동기화를 통해 스레드의 작업 처리 순서와 공유 자원에 대한 접근을 컨트롤할 수 있다. (Java에서 synchronized 키워드) 그러나 불필요한 부분까지 동기화를 하는 경우, 과도한 lock으로 인해 병목 현상을 발생시켜 성능이 저하될 가능성이 높기 때문에 주의해야 한다. 동기화 방법에는 뮤텍스와 세마포어가 있다. context switching, 동기화 등의 이유 때문에 싱글 코어 멀티 스레딩은 스레드 생성 시간이 오히려 오버헤드로 작용해 단일 스레드보다 느리다.
프로세스의 동적 할당 영역
- TEXT(코드) 영역 : 프로그램의 본체가 있는 곳
- 데이터 영역 : 프로그램이 사용하려고 정의한 변수와 데이터가 있는 곳
- 스택 영역과 힙 영역 : 프로세스가 실행되는 동안 만들어지는 영역으로, 그 크기가 늘어났다 줄어들기도 하는 동적 할당 영역
Leave a comment