bdfgdfg
[OS] 프로세스와 쓰레드 본문
프로세스
- 운영체제에서 프로세스는 하나의 작업 단위.
- 우리의 디스크에 저장된 프로그램(exe)을 사용자가 더블클릭하여 실행하면 그 프로그램은 프로세스가 된다.
-> 프로그램은 하드디스크같은 저장장치에 보관된다.
-> 프로그램은 저장장치에 저장되어 있는 정적인 상태이며 프로세스는 실행을 위해 메모리에 올라온 동적인 상태.
- 프로세스를 구성하는 요소 코드영역,데이터영역,힙영역,스택영역
기계어로 번역된 프로그램을 실행하면 프로세스가 되고 프로세스의 구성요소는 위와 같다.
코드 영역 : 실행파일을 구성하는 명령어들이 올라가는 메모리 영역. (즉 우리의 코드가 기계어로 번역된 곳이 올라가는 곳)
데이터 영역 : 전역변수나 static으로 선언한 정적변수들이 올라가는 곳. 프로그램의 실행과 동시에 올라간다.
힙 영역 : malloc함수나 new 연산자를 통해 직접 메모리가 할당되고 free함수나 delete연산자에 의해 해제되는 공간.
스택 영역 : 지역변수,매개변수,함수가 호출된 위치를 가리키는 주소가 담긴 스택 프레임이 형성되는 곳.
현대의 운영체제는 시분할 방식.
일괄처리방식은 하나의 프로세스가 실행되었을 때 그 프로세스가 종료되기전 까지 다른 작업은 불가능하다.
그렇기에 CPU(1개의 cpu,1개의 코어)는 여러개의 프로세스를 동시에 실행시키는 것처럼 보이기 위해서 CPU의 사용시간을 쪼개(타임 슬라이스) 여러 프로세스에 적당히 배분함으로서 동시에 실행하는 것처럼 느껴지는 것.
현대의 운영체제는 시분할 방식을 기본으로 사용하기 때문에 프로세스가 여러 상태를 오가며 실행된다.
운영체제는 프로그램을 실행하면 메모리로 올리게 되고, 그와 동시에 작업 지시서를 만드는데, 이 작업 지시서가
프로세스 제어 블록(Process ontrol Block,PCB).
이 프로세스 제어 블록에는 프로세스를 처리하는 데 필요한 다양한 정보가 들어있다.
-> 요리에서 주문서가 없으면 요리가 진행되지 않듯이 PCB가 없다면 프로그램이 프로세스로 전환되지 못한다.
-> 즉 어떤 프로그램이 프로세스가 되었다는 것은 운영체제로부터 PCB를 할당 받았다는 의미.
프로세스 제어 블록에는 다양한 정보가 들어가있지만 대표적인 세가지는 밑과 같다.
프로세스 구분자(PID) | 메모리에는 여러 프로세스가 올라와있다. 그렇기에 각 프로세스를 구분하는 구분자(ID)가 필요. |
메모리 관련 정보 | CPU는 실행하려는 프로세스가 메모리의 어디에 저장되어 있는지를 알아야 작업이 가능하다. 이를 위해 PCB에는 프로세스의 메모리 위치 정보가 담겨 있다. 또한 메모리 보호를 위한 경계 레지스터와 한계 레지스터도 포함. |
각종 중간값 | PCB에는 프로세스가 사용했던 중간값이 저장된다. (프로그램 카운터★,레지스터 정보(CPU),메모리 관련 정보등) 시분할 시스템에서는 여러 프로세스가 번갈아가며 실행되기 때문에 각 프로세스는 일정 시간 작업을 한 후 다른 프로세스에 CPU를 넘겨준다. ★ 예로들어 프로세스A의 작업이 103번 행까지 처리한 후 다른 프로세스에 CPU사용권을 넘겼다고 보면 다음에 다시 자신의 CPU 사용권을 얻을 때 103번 행 이후의 작업을 처리해야 한다는 것을 기억하고 있어야 한다. (정확히는 다음에 처리해야할 명령어의 위치) 이를 위해 PCB에서는 다음에 작업해야 할 코드의 위치가 담긴 레지스터인 프로그램 카운터가 저장된다. 또한 작업을 처리하던 중간값을 보관 중인 다른 레지스터도 같이 저장된다. 시분할 방식의 운영체제에서 가장 중요. |
이렇게 하나의 프로세스를 실행하기 위해 여러가지 정보를 담기 위해 운영체제로 부터 프로세스 제어 블록을 할당받는 것.
또한 프로세스 제어 블록은 운영체제가 해당 프로세스를 위해 관리하는 자료구조이기 때문에 운영체제 영역에 만들어진다. 프로세스가 종료되면 프로세스가 메모리에서 삭제되고 프로세스 제어 블록도 함께 폐기된다.
프로세스의 상태
운영체제에서는 여러 가지 이유로 프로세스 상태가 변화된다.
시분할 시스템에서의 프로세스 상태는 CPU 사용시간을 잘개 나눠 모든 프로세스를 처리하므로 여러가지 상태가 존재한다.
생성 상태: 프로그램이 메모리에 올라와 실행 주닙를 완료한 상태. 프로세스를 관리하기 위해 필요한 PCB가 생성된다.
준비 상태: 생성된 프로세스가 CPU를 얻을 때까지 기다리는 상태. 즉 CPU의 사용권을 얻기 위해 준비하는 상태이며 자신의 실행 순서가 오기까지 준비 상태에서 기다리는 중.
실행 상태: 준비 상태에 있는 프로세스 중 하나가 CPU를 얻어 실제 작업을 수행하는 상태. 실행 상태에 들어간 프로세스는 일정 시간 동안 CPU를 사용하며 주어진 시간을 다 사용하고도 작업이 끝나지 않았다면 프로세스는 다시 준비상태로 돌아와 자신의 차례를 기다린다. (작업이 끝나기까지 이를 반복) 프로세스 사이의 컨텍스트 스위칭(문맥 교환)이 일어난다.
완료 상태: 실행 상태의 프로세스가 주어진 시간 동안 작업을 마치면 완료 상태로 진입. 완료 상태는 프로세스 제어 블록이 사라진 상태를 의미.
준비 상태에 있는 프로세스 중 다음에 실행할 프로세스를 선정하는 것은 CPU 스케쥴러가 담당한다.
프로세스는 자신에게 배당된 작업 시간(타임 슬라이스)동안 작업을 끝내지 못하면 준비 상태로 돌아가는데 이를 타임 아웃이라 한다. 디스패치는 CPU 스케쥴러에 의해 선택받아 실행 상태에 들어가는 것.
프로세스는 생성,준비,실행,완료라는 네가지 상태만으로 작업을 진행하는 데 큰 문제가 없었지만 오늘날 운영체제의 효율성을 고려해 한가지 상태를 더 만들었다. 바로 대기 상태(Blocking status)
이는 작업을 효율성을 높이기 위해 입출력을 요청한 프로세스를 실행 상태에 두지 않고 대기 상태로 옮기는 것.
-> 대기 상태에 들어간 프로세스는 CPU 사용권을 양보하며 스케쥴러에 의해 선택받지 못하는 상태가 된다.
대기 상태의 프로세스는 요청한 입출력이 완료되면 입출력 관리자로부터 인터럽트를 받는다.
대기 상태의 프로세스는 실행 상태에서 입출력(I/O - Blocking)요청을 받아 대기 상태로 전환되었지만 입출력이 끝났다해서 다시 바로 실행 상태로 돌아가는게 아닌 준비상태로 다시 돌아가게 된다.
컨텍스트 스위칭(문맥 교환) ★
어떤 하나의 프로세스를 실행하고 있는 상태에서 인터럽트 요청에 의해 다음 우선 순위의 프로세스가 실행되어야 할 때 기존의 프로세스의 상태 또는 레지스터 값(Context)을 저장하고 CPU가 다음 프로세스를 수행하도록 새로운 프로세스의 상태 또는 레지스터 값(Context)를 교체하는 작업
CPU내에 존재하는 레지스터들은 현재 실행 중에 있는 프로세스 관련 데이터들로 채워지는데, 현재 프로세스A와 B가 있고 프로세스 A가 실행중인 상태라고 보자.
(CPU 사용권을 얻었고 CPU는 1개,싱글코어) 프로세스 B는 준비상태이며 CPU 스케줄러에 의해 선택받기를 기다리고 있는 상태이다.)
만약 여기서 프로세스A가 입출력이 발생해 대기상태로 빠지던지, 아니면 자기의 CPU 사용시간을 다 사용해 다른 프로세스에게 넘겨줘야할 때가 온다. 그렇다면 이 프로세스A가 지니고 있는 데이터들을 어딘가 저장해야만 한다.
-> 다시 자신(프로세스A)의 차례가 왔을 때 그 정보를 복원하고 다음 작업을 이어서 처리해야하기 때문에.
-> 이때까지의 진행된 모든 작업과 데이터의 정보는 PCB에 저장된다.
-> 쓰레드의 경우 TCB에 저장된다.
보통 TCB는 커널 레벨에서 Context Switching의 기본 단위가 되며, 같은 프로세스에서의 스위칭에 대해서는 TCB 정보만 저장하면 된다.
하지만 다른 프로세스 간의 스위칭을 할 때에는 PCB / TCB 정보를 모두 저장해야 한다.
프로세스A가 어떠한 이유에 의해 실행상태에서 나가게 된다면, 프로세스B가 실행상태에 올라가게 될 것이고, 프로세스B와 관련된 데이터 정보들로 채워진다. 이 과정을 컨텍스트 스위칭(문맥 교환)이라 한다.
실행중인 프로세스의 상태 변화는 시스템에 많은 부하를 가져다 준다.
이는 레지스터 개수가 많은 시스템일수록, 프로세스별로 관리되어야 할 데이터 종류가 많을수록 더하다.
이것이 멀티 프로세스 운영체제의 단점.
쓰레드 ★
쓰레드는 프로세스내에 존재하는 실제로 작업을 실행하는 단위,흐름이다.
현대의 운영체제는 프로세스의 낭비 요소를 제거하고 프로세스 작업의 유연성을 얻기 위해 멀티쓰레드를 사용.
멀티 프로세스 방식에서 두 가지 이상의 일을 동시에 처리하기 위해 추가적으로 프로세스를 생성(자식 프로세스)하는 것은 부담이 된다. 많은 수의 프로세스 생성은 빈번한 컨텍스트 스위칭으로 이어져 성능에 영향을 미치기에.
-> 또한 프로세스 자체가 운영체제로 부터 자원을 할당받아 메모리에 올라오기에 가벼운 작업이 아니다.
-> 물론 멀티 쓰레드에서 쓰레드간의 컨텍스트 스위칭이 가벼운 작업이라는 것은 아니다. 상대적으로는 가볍다.
컨텍스트 스위칭에 소요되는 시간을 줄이는 건 성능에도 많은 연관이 있기에 줄이는 방법을 생각해야한다.
그것이 바로 저장하고 복원하는 컨텍스트 정보의 개수를 줄여주는 것.
-> 컨텍스트 정보란 프로세스의 상태 정보와 관련이 있으므로 결국은 프로세스 상태 정보를 줄여야 한다는 결론이 나온다.
컨텍스트 스위칭이 느린 가장 근본적인 이유는 프로세스들이 서로 완전히 독립적이기 떄문이다.
부모 자식관계의 프로세스라 하더라도, 메모리에 독립적으로 올라가 별도의 자원으로 할당되기 떄문.
-> 쓰레드는 공유
-> 프로세스간에서 통신을 하기위해 IPC기법이 사용되며 가장 기본적인 것은 별도의 메모리 버퍼(파이프)를 통해 통신.
동영상 플레이어 프로그램과 게임 프로그램은 별도의 프로그램을 동시에 실행하기 위해서는 어쩔 수 없이 독립된 프로세스 구조가 필요하다.
하지만 하나의 프로세스내에서 둘 이상의 실행 흐름을 두기 위해서 모든 것을 독립시키는 구조(자식 프로세스 생성)로는 갈 필요가 없다. 여기서 등장한게 바로 쓰레드.
부모와 자식 프로세스의 관계 구조를 나타내는 그림.
부모 프로세스에서 별도의 흐름을 처리하기 위해 자식 프로세스를 두 개를 생성했다.
하지만 부모 프로세스를 통해 해당 프로세스들이 생성되었다 한들 메모리 구조상에서 보면 생성 이후에는 아무런 관계가 없다. (프로세스는 항상 별도로 독립적인 메모리) 그렇기에 프로세스간 통신에서는 IPC기법이 필요한 것.
위 그림은 하나의 프로세스 내에서 별도의 쓰레드를 하나 더 생성한 모습.
-> 프로세스가 생성될 때 main함수에 진입하는 쓰레드가 하나 할당된다. 이를 메인 쓰레드라 한다.
위 그림을 보면 쓰레드가 생성되면 해당 쓰레드만을 위한 독립적인 스택 공간만을 할당할 뿐 그 이외의 영역은 프로세스 스 영역을 공유하고 있다. (코드,데이터,힙)
쓰레드가 프로세스의 메모리 영역을 공유하는데 스택공간만 별도로 할당되는 이유가 무엇일까.
스택영역은 함수 호출 시 전달되는 인자, 함수 호출을 한 곳으 되돌아갈 주소값 및 지역변수등의 스택 프레임이 형성되는 공간이다. 간단히 말하자면 함수 호출 시 필요한 메모리 영역이라는 것.
즉 스택영역이 독립적이라는 것은 독립적인 함수 호출이 가능하며 독립적인 실행흐름이 가능하다는 의미.
또한 쓰레드는 데이터 영역과 힙영역을 공유하게 된다.
따라서 전역변수,정적변수,malloc등으로 동적할당된 메모리 공간은 쓰레드간 공유가 가능하다는 의미.
-> 공유된다는게 만능은 아니다. 멀티 코어 환경에서는 가시성 문제가 있고, 경쟁상태(data-race)의 문제로 인한 동기화처리가 필요하다.
Windows에서의 프로세스와 쓰레드
Windows입장에서 프로세스는 단순히 쓰레드를 담는 상자에 지나지 않는다.
때문에 실제 프로그램의 흐름을 형성하는 것은 쓰레드이며 스케쥴러에의해 선택되는 것도 프로세스가 아닌 쓰레드.
-> Windows에서 프로세스는 상태(Running,Ready,Blocked)를 지니지 않는다.
-> 스케쥴러,스케줄링 알고리즘은 다음에
그렇다해서 앞서 배운 프로세스 컨텍스트 스위칭이 의미없는건 아니다. 메모리에는 여러개의 프로세스가 올라와있고, 프로세스A에서 프로세스B에서의 전환은 결국 프로세스 컨텍스트 스위칭.
-> Windows에서도 프로세스 컨텍스트 스위칭이 존재한다고 말하며 이는 서로 다른 프로세스간의 컨텍스트 스위칭을 말한다.
(물론 정확히는 쓰레드간 컨텍스트 스위칭이긴 하지만, 프로세스는 무조건 하나의 쓰레드를 가지고 있으며 서로 다른 프로세스의 쓰레드간 전환을 의미한다.)
-> 하나의 프로세스 내에서 둘 이상의 쓰레드가 있을 떄 해당 쓰레드간의 컨텍스트 스위칭의 비용보다 서로 다른 프로세스간의 컨텍스트 스위칭의 비용이 더 높다.
프로세스 VS 스레드.
프로세스는 운영체제로 부터 자원을 할당받고 독립적인 형태로 메모리에 올라온다.
이러한 특징때문에 다른 프로세스의 메모리 영역에 접근할수가 없다.
하지만 스레드는 프로세스내의 실제 실행의 흐름. 스레드는 별도로 스택 메모리를 가지며 그 외의 해당 프로세스의 코드,데이터,힙영역을 공유하게 된다.
-> 공유변수 조심.
'CS > 운영체제' 카테고리의 다른 글
[OS] 가상 메모리 (0) | 2022.04.09 |
---|---|
[OS] 스레드 동기화와 교착 상태(Deadlock) (0) | 2022.04.06 |
[OS] 스케줄링 알고리즘과 우선순위 (0) | 2022.04.04 |
[OS] 컴퓨터 구조 개요 (0) | 2022.03.30 |
[OS] 운영체제 개요 (0) | 2022.03.30 |