## 목차 ##
## 1. 프로세스 개요 ##
(1) 프로세스의 개념
- 프로세스는 프로그램이 메모리에 올라와 실행중인 동적인 상태를 의미한다. 즉, 프로그램을 실행시켜 프로세스를 생성한다.
(2) 프로그램에서 프로세스로의 전환
프로그램이 메모리에 올라와서 실행되면 '프로세스 제어 블록'이 생성된다.
프로세스 제어 블록(Process Control Block - PCB)은 프로세스를 처리하는데 필요한 정보들이 들어있는 자료구조이다.
- 프로세스 구분자(PID - Process Identification)
- 메모리 관련 정보(프로세스의 메모리상 위치, 경계 레지스터와 한계 레지스터)
- 각종 중간값(프로세스가 어디까지 진행되었는지 등을 위한 레지스터 값들)
- 기타등등
운영체제 커널은 프로세스 제어블록(PCB)를 참고하여 프로세스를 관리한다.
(3) 프로세스의 상태
생성(create, new)
- 프로그램이 메모리에 올라와 프로세스가 되고 프로세스 제어 블록이 생성된다.
- 생성이 완료되면 프로세스 제어 블록을 준비 큐에 삽입하여 준비상태로 옮긴다.
준비(ready)
- CPU를 할당받을 때 까지 기다리는 상태이다.
- CPU 스케줄러는 준비상태에 있는 프로세스들 중 다음에 실행할 프로세스를 선택하고 디스패치(dispatch)하여 실행시킨다.
- 제어 블록은 준비 큐(ready queue)에서 다음 실행을 기다린다.
- CPU 스케줄러가 준비상태에 있는 프로세스를
dispatch(PID)
명령으로 처리하여 실행한다.
실행(running)
- 프로세스가 CPU를 얻어 실제 작업을 수행하는 상태이다.
- 타임 슬라이스 혹은 타임 퀀텀만큼 CPU를 사용할 수 있는 시간이 할당된다.
- 타임 슬라이스가 초과하면 클럭이 CPU에 타임아웃 인터럽트를 보낸다.
- 타임아웃이 되면 아직 완료되지 않은 프로세스는 다시 준비상태로 옮겨진다.
- 타임아웃이 되었을 때 완료된 프로세스는 종료상태로 옮겨진다.
- 실행 중 프로세스가 입출력을 요청하면 CPU가 입출력 관리자에게 요청을 전달하고 프로세스를 대기상태로 옮겨진다.
종료(terminate)
- 프로세스 작업이 완료되면 제어 블록이 사라지고 메모리에서 해당 프로세스가 해제된다.
대기(wating)
- 프로세스가 입출력장치나 네트워크에 데이터를 요청할 때 발생한다.
- 입출력이 완료될 때 까지 아무것도 하지않고 기다리는것은 비효율적이다.
- 따라서 입출력을 요청한 프로세스는 대기상태로 들어가고 다른 프로세스에게 CPU 사용권한을 넘긴다.
- 입출력이 완료되면 입출력장치 제어기가 인터럽트를 보내고 프로세스는 준비상태로 들어가 다음 CPU 선점을 기다린다.
- 휴식상태와 보류상태
- 프로그램이 일시중지 된 상태이다.
- 휴식상태는 일시중지되었지만 프로세스가 메모리에 그대로 남아있다.
- 유닉스에서 ctrl+Z를 누르면 휴식상태로 들어간다.
- 보류상태는 메모리에서 쫓겨나 데이터가 스왑영역(swap area)에 보관된다.
- 보류상태는 메모리가 꽉 차거나 프로세스에 오류가 있는경우, 혹은 프로세스가 요청한 입출력이 계속 지연되는 등의 이유로 발생한다.
## 2. 프로세스 제어 블록과 문맥 교환 ##
(1) 프로세스 제어블록 구성
포인터
- 부모 프로세스 포인터(부모 프로세스의 주소)
- 자식 프로세스 포인터(자식 프로세스의 주소)
- 프로세스 자신의 포인터(프로세스가 있는 메모리의 주소)
- 할당된 자원에 대한 포인터(프로세스가 사용중인 혹은 입출력을 요구한 자원의 주소)
- 프로세스가 입출력 요구로 대기상태로 들어갈 때 각 자원의 대기 큐에 PCB이 추가되는데 이 때 입출력장치는 PCB의 포인터를 확인하고 프로세스에 완료 인터럽트를 보낸다.
프로세스 상태
- 프로세스의 현재 상태
프로세스 구분자
- 여러 프로세스를 구분하기 위한 프로세스 고유의 ID
프로그램 카운터
- 다음에 실행될 명령어의 위치를 기억하기 위한 레지스터
프로세스 우선순위
- 프로세스의 우선순위
- 프로세스별로 우선순위가 다르다.
- 커널 프로세스 같이 중요한 프로세스가 일반 사용자 프로세스보다 우선순위가 높다.
- 우선순위별로 준비 큐가 따로 운영된다.
레지스터 정보
- 프로세스들이 CPU를 돌려쓰기 때문에 준비 상태로 가기 전 실행중일 때의 레지스터 정보를 저장한다.
- 프로세스의 다음 CPU 선점 때 레지스터 정보를 다시 불러와서 이어서 실행한다.
메모리 관리 정보
- 프로세스가 할당된 메모리 위치
- 메모리 보호를 위한 경계 레지스터값, 한계 레지스터값
- 세그멘테이션 테이블, 페이지 테이블 등
할당된 자원 정보
- 프로세스가 사용하려는 하드웨어 자원(디스크의 파일, 사운드카드 등)의 정보를 저장한다.
계정 보호
- 계정 번호, CPU 할당 시간, CPU 사용 시간 등
부모 프로세스와 자식 프로세스 구분자
- 부모 프로세스 구분자(PPID)
- 자식 프로세스 구분자(CPID)
(2) 문맥 교환(context switching)
CPU를 차지하던 프로세스가 준비상태로 가고 새로운 프로세스를 실행상태로 옮기는 작업
- 실행 -> 준비로 옮기는 프로세스의 제어블록에 지금까지의 작업 내용을 저장한다.
- 준비 -> 실행으로 옮기는 프로세스의 제어블록 내용을 가지고 CPU 레지스터가 세팅된다.
문맥 교환 원인
- 타임아웃에 의한 CPU 스케줄러의 명령
- 경계 레지스터 범위를 넘어선 메모리 접근과 그에따른 인터럽트
- 인터럽트가 발생하면 인터럽트 관리 프로세스가 실행상태로 들어간다.
## 3. 프로세스의 연산 ##
(1) 프로세스 메모리 구조
프로세스는 메모리 영역을 4가지로 구분하여 사용한다.
코드(code) 영역
- 프로그램의 실행 코드와 매크로 상수 등
- 컴파일시에 결정된다.
- 프세스 실행중에는 바꿀수 없도록 read-only로 지정되어있다.
데이터(data) 영역
- 전역변수, static 변수 등
- read-write 가능
스택(stack) 영역
- 지역변수, 매개변수, 리턴값, 함수 호출이 끝난 뒤 돌아올 주소
- 컴파일 시에 크기가 정해진다.
- 지역변수가 너무 많거나 재귀호출이 여러번 반복되어 스택영역을 벗어나 넘치면 stack-overflow 에러가 발생한다.
힙(heap) 영역
- 프로그래머가 직접 할당하고 해제하는 메모리 영역
- C언어의 경우 malloc과 calloc으로 할당하고 해제할 수 있다.
- 런타임(runtime)시에 결정된다.
- Java와 같이 명시적 메모리 할당/해제를 막아놓은 언어로 작성된 프로그램의 경우 JVM이 대신 이 영역의 할당/해제를 한다.
(2) 프로세스의 생성과 복사
fork()
- 커널에서 제공하는 시스템 호출 함수이다.
- 실행중인 프로세스로부터 새롱누 프로세스를 복사하는 함수
- ex) 웹 브라우저를 실행하는중에 새로운 웹 브라우저를 하나 더 실행하면 새로운 프로세스가 생성되지 않고 기존 웹 브라우저를 fork()하여 만들어진다.
- fork()는 새로 프로세스를 생성하는 것보다 빠르다.
- 기존 프로세스는 부모 프로세스이고 새로운 프로세스는 자식 프로세스이다.
fork() 호출 동작 과정
- 부모 프로세스의 제어블록 대부분이 복사되어 자식 프로세스 제어블록이 만들어진다.
- 프로세스 구분자(PID), 메모리 정보는 바뀐다.
fork()의 장점
- 프로세스 생성 속도가 빠르다.(하드디스크로부터 새로 프로그램을 가져오지 않고 메모리에서 복사하기 때문)
- 추가 작업 없이 자원을 상속할 수 있다.(부모가 만들어놓은 자원을 그대로 사용할 수 있어 효율적)
- 자식 프로세스가 종료되면 부모프로세스가 메모리, 하드웨어 자원, 파일등을 대신 정리하므로 효율적이다.
- fork()문을 기준으로 부모 프로세스와 자식 프로세스가 갈라진다.
- 부모 프로세스에서는 fork()가 자식 프로세스의 PID를 리턴한다.
- 자식 프로세스에서는 fork()가 0을 리턴한다.
- 음수를 리턴하면 자식 프로세스 생성이 실패한 것이다.
int main()
{
int pid = fork();
if(pid > 0)
printf("%s", "parent");
else if(pid == 0)
printf("%s", "child");
else
printf("%s", "error");
return 0;
}
위 코드에서는 fork()가 성공하면 결국 "parent"와 "child"가 모두 출력된다. 그러나 부모 프로세스와 자식 프로세스는 서로 독립적이라 무엇이 먼저 출력될지는 알 수 없다.
(3) 프로세스의 전환
exec()
- 기존의 프로세스를 덮어쓰는 새로운 프로세스 생성
- fork()가 기존 프로세스를 그대로 둔 채 새로운 프로세스를 복사하는 것과 다르게 exec()은 현재 프로세스를 완전히 다른 프로세스로 전환한다.
- 프로세스의 구조를 재활용하기 위해 사용한다.
exec() 호출 동작 과정
- 코드 영역을 지우고 새로운 코드로 바꾼다.
- 데이터 영역이 새로운 변수로 채워진다.
- 스택 영역은 리셋된다.
- PID, PPID, CPID는 유지된다.
- 프로세스 생성과정을 처음부터 거치는 것이 비효율적이기 때문에 기존에 확보한 메모리 영역을 그대로 쓰기위해 사용하는 시스템 호출 함수이다.
(4) 유닉스 프로세스의 계층 구조
유닉스가 부팅되면 init이라는 커널관련 프로세스가 생성되며 이 프로세스는 모든 프로세스의 부모이다.
사용자별로 login 프로세스를 실행시킬 때는 기존 login 프로세스를 fork()한다.
login이 끝나면 shell을 새로 실행시키는 것이 아닌 login 프로세스를 exec()하여 shell을 만든다.
- 자원 사용이 효율적이게 된다.
shell에서 명령어를 통해 새로운 프로그램을 실행시키면 shell은 fork()를 통해 프로세스를 복사하고 이를 exec()하여 새로운 프로세스를 생성한다.
- ex) shell에서 웹브라우저를 실행시키면 shell을 fork()하여 새로운 shell을 만들고 이것을 exec()하여 웹브라우저 프로세스로 덮어쓴다.
계층구조를 사용하면 자원 회수가 용이하다.
- 모든 자식 프로세스가 종료될 때는 부모 프로세스가 자원을 회수하므로 운영체제의 부담이 줄어든다.
미아 프로세스
- 부모 프로세스가 먼저 종료된 경우
- 자식 프로세스가 비정상 종료되어 부모 프로세스가 미처 자원을 회수하지 못한 경우
- 자원 낭비가 발생한다.
## 4. 스레드 ##
(1) 스레드의 개념
스레드의 정의
- CPU 스케줄러는 프로세스가 해야할 일을 CPU에 전달하고 실제 작업은 CPU가 수행한다.
- CPU 스케줄러가 CPU에 전달하는 '일 하나'가 스레드이다.
- CPU가 처리하는 작업 단위가 프로세스로부터 전달받은 스레드이다.
- 운영체제 입장에서의 작업 단위가 프로세스라면 CPU 입장에서의 작업 단위는 스레드이다.
멀티 스레드
- 프로세스 내 작업을 여러개로 분할하여 동시에 실행
멀티 태스킹
- 멀티 스레드에서 여러 스레드에 잘게 시간을 배분하여 CPU를 할당하여 여러 일을 동시에 처리하는 것
멀티 프로세스
- CPU를 여러개 혹은 코어를 여러개 사용하여 여러 프로세스를 동시에 실행하는것
- 슈퍼스칼라
CPU 멀티스레드
- 파이프라이닝을 통하여 하나의 CPU에서 여러 스레드를 동시에 처리하는 병렬처리 기법
(2) 멀티 스레드의 구조
동시 처리를 위해 fork()를 사용하면 코드 영역과 데이터 영역이 새로 할당되고 그 중 일부가 메모리에 중복되어 존재하게 되어 낭비를 불러온다.
같은 프로세스의 스레드끼리는 코드영역과 데이터영역을 공유하므로 자원 낭비가 없어 효율성이 올라간다.
(3) 멀티스레드의 장단점
장점
응답성 향상
- 입출력과 다른 부분을 멀티스레드로 나누면 입출력 요청이 발생해 해당 스레드가 대기상태로 들어가더라도 나머지 스레드는 실행상태에 있을 수 있다.
자원 공유
- 자원 공유로 인한 메모리 효율성이 증가한다.
다중 CPU 지원
- 여러 CPU나 코어를 가진 컴퓨터의 경우 여러 스레드가 동시에 처리될 수 있다.
- 단점
- 자원을 공유하므로 하나의 스레드에 문제가 생기면 같은 프로세스 내의 다른 스레드와 상관없이 프로세스 전체에 문제가 발생한다.
- ex) 인터넷 익스플로러는 멀티탭을 멀티 스레딩으로 구현하여 하나의 탭에서 문제가 생겨 종료하면 익스플로러 전체가 종료된다. 구글 크롬은 멀티 프로세싱 방식으로 멀티탭을 구현했다.
(4) 멀티스레드 모델
- 사용자 레벨 스레드
- 초기의 스레드 시스템
- OS가 멀티스레드를 지원하지 않아 만들어 사용하는 방식
- 라이브러리를 사용하여 사용자 레벨에서 직접 구현
- 커널 입장에서 이 스레드는 하나의 프로세스로 보인다.
- 하나의 커널 스레드와 사용자의 여러 스레드가 연결되는 1 to N 모델
- 문맥 교환이 필요없어 효율적
- 전체 프로세스에 배정받는 하나의 타임 슬라이스를 공유하므로 CPU 점유시간이 작다.
- 하나의 스레드가 입출력 요청을 하면 전체 스레드가 묶여서 대기상태로 옮겨진다.
- 커널 레벨 스레드
- 커널이 지원해주는 멀티스레드
- 하나의 커널 스레드가 하나의 사용자 스레드와 연결되는 1 to 1 모델
- 커널 레벨 스레드는 독립적으로 스케줄링된다.
- 하나의 사용자 스레드가 대기상태에 들어가도 프로세스의 나머지 스레드는 실행 가능
- 스레드별로 문맥교환이 발생하여 자원 측면에서는 사용자 레벨 스레드에 비해 비효율적이다.
- 멀티 레벨 스레드(하이브리드 스레드)
- 사용자 레벨 스레드와 커널 레벨 스레드를 혼합한 방식
- 하나의 커널 레벨 스레드가 대기상태에 들어가면 다른 커널레벨 스레드가 대신 작업
- 문맥 교환에 의한 오버헤드는 사용자 레벨 스레드보다 크고 커널 레벨 스레드보다는 작다
'CS > 운영체제' 카테고리의 다른 글
(운영체제) 6 - 교착 상태(데드락) (0) | 2020.05.15 |
---|---|
(운영체제) 5 - 프로세스 동기화 (0) | 2020.05.15 |
(운영체제) 4 - CPU 스케줄링 (0) | 2020.05.15 |
(운영체제) 2 - 컴퓨터의 구조와 성능 향상 (0) | 2020.05.15 |
(운영체제) 1 - 운영체제 개요 (0) | 2020.05.15 |