프로세스와 스케줄러의 이해
프로세스(Process)의 이해
프로세스란 무엇인가?
프로세스란 메인 메모리로 이동하여 실행 중인 프로그램을 의미한다.
- .exe를 더블 클릭 했을 때 윈도우 상에 떠있는 창이 프로세스…?
- 메인 메모리가 프로세스…?
- 메인 메모리에 올라와서 실제 실행중인 코드가 프로세스...?
- 실제로 메인 메모리가 256M이고 실행 파일의 크기가 1GB라면 256M에 올라가 있는 코드만 프로세스냐…?
예를 들어서, 벽돌깨기 게임이 하드디스크에 저장되어 있고 이 게임의 실행파일 이름을 block.exe 라고 한다면 이것을 보통은 프로그램이라 한다. 이제 게임을 즐기기 위해 실행파일인 block.exe 를 더블 클릭한다. 이 순간 클릭한 프로그램의 실행을 위해 메모리 할당이 이뤄지고, 이 메모리 공간으로 바이너리 코드가 올라가게 된다. 이 순간부터 프로그램은 프로세스라고 불리게 된다.
프로세스(Process)의 구체적인 이해 - 프로세스의 범위
메모리 구조 + 레지스터 set
프로그램이 실행됨 -> CPU에 연산 장치인 ALU가 있어 CPU가 프로그램을 실행시킨다고 말함
ALU가 연산을 하게끔 도와주는 레지스터 Set이 중요하다.
레지스터 Set을 보면 현재 실행중인 프로그램 정보들로 가득 채워진다.
프로세스 별 독립적인 대상은 프로세스의 범주에 포함시킬 수 있다.
프로세스를 구성하는 범주는 프로세스 별로 독립적으로 할당받는 리소스다.
메모리 공간, 가상 메모리 공간도 프로세스의 범주에 포함이 되고 프로세스별로 독립적으로 사용하게 되는(독립적으로 사용한다는 것은 A라는 프로세스가 사용중일 때는 B라는 프로세스가 사용 못하고 B가 쓰면은 A가 못쓰는 거를 말함) 레지스터 Set도 프로세스 범주에 포함시킬 수 있다.
예를들어 A라는 프로세스가 레지스터의 r1, r2, r3을 사용해서 ADD 연산을 처리하고 있다고 하자.
근데 A 프로세스가 시간이 다되서 실행의 우선권을 B 프로세스에 넘겨줄 때 B에도 자기만의 연산이 존재한다.
근데 연산을 할려면 레지스터를 사용해야 한다. 그래서 A라는 프로세스의 정보로 가득 차있는 레지스터의 정보는 어딘가에 저장되고 레지스터에 B 프로세스의 정보들로 차게 된다.
위와 같은 과정을 컨텍스트 스위칭이라고 부른다.
1초에 최소한 수십 번 컨텍스트 스위칭이 발생한다. 그래서 마치 하나의 CPU가 두 개의 프로그램을 실행시키는 것처럼 보여준다. 그래서 C.S가 부담스러운 작업이여서 아래와 같은 기법을 사용하기도 한다.
- 프로세스 중에서는 레지스터 Set을 여러개 가진다.
- A, B, C 레지스터 Set이 존재하고 프로세스가 3개 실행 중이면 각 프로세스에 레지스터 Set을 아예 할당을 해버린다.
- 이러면 프로세스마다 나만의 레지스터 Set을 가지고 있기 때문에 C.S가 일어날 때 레지스터 Set을 바꿀필요가 없다. 그래서 멀티 프로세스 환경에서 성능을 높이기 위한 여러 가지 기법이 존재한다.
프로세스를 구성하는 요소
Execution of "C" Program
기본적으로 전역변수나 static 변수의 할당을 위해 존재하는 Data 영역, 지역변수 할당과 함수 호출 시 전달되는 인자값들의 저장을 위해 존재하는 Stack 영역 , 그리고 동적 할당을 위해 존재하는 Heap 영역으로 구성된다.
프로그램을 실행시키면, 실행 파일 내에 존재하는 명령어들이 메모리상에 올라가서 순차적으로 실행된다. 이렇게 실행파일을 구성하는 명령어들이 올라가는 메모리 영역을 Code 영역이라 한다.
위 그림은 프로세스 생성 시 만들어지는 메모리 구조이다.
프로세스 생성 시 만들어지는 메모리 자체를 프로세스라고 표현하기도 한다. 왜냐하면 프로그램 실행을 위해서 명령어들이 메모리 공간에 올라와 있는 상태이고, 프로그램 실행을 위해서 필요한 메모리 공간이 할당되어 있는 상태이기 때문이다. 위와 같은 메모리 구조는 실행되고 있는 프로세스 개수만큼 생성된다.
Resister Set
프로세스를 구성하는 요소로 더불어 생각해봐야 하는 것은 CPU 내에 존재하는 레지스터들이다.
프로그램 실행을 위해서는 레지스터들이 절대적으로 필요하다.
예를 들어, CPU가 현재 block.exe를 실행 중에 있다면, CPU를 구성하는 레지스터들은 block.exe의 실행을 위해 필요한 데이터들로 채워지게 된다. 이렇듯 CPU 내에 존재하는 레지스터들은 현재 실행 중인 프로그램을 위한 데이터들로 채워진다. 따라서, 레지스터들의 상태까지도 프로세스의 일부로 포함시켜 말할 수 있다.
프로세스 스케줄러
스케줄러는 하드웨어적인 장치가 아니라 윈도우 라는 운영체제에서 제공해 주는 소프트웨어적으로 구현되어 있는 장치다.
프로세스 스케줄러라는 것은 프로세스를 스케줄링해주는 거다. 이런 게 필요한 이유는 다음과 같다.
CPU는 하나지만 프로세스를 여러 개 실행시킨다.
- 그 이유는 하나의 CPU가 여러 개의 프로세스를 번갈아 가면서 실행하기 때문이다.
- 다행히도 CPU는 아주 빠르기 때문에 하나의 CPU가 여러 프로세스를 고속으로 번갈아 가며 실행시킬 경우, 프로그램 사용자들은 CPU가 동시에 여러 개의 프로그램을 실행시킨다고 느끼게 된다.
- 결국 우리가 사용하는 멀티 프로세스 운영체제에서 여러 개의 프로세스가 실행되는 것처럼 보이는 이유는 여러 개의 프로세스들이 CPU 할당 시간을 나누기 때문이다.
CPU는 한순간에 하나의 프로세스만 실행시킬 수 있기에 스케줄러가 CPU에게 실행시킬 프로세스를 가져다준다.
실행시킬 프로세스 순서를 정해줘서 CPU에 의해서 공평하게 프로세스들이 실행될 수 있도록 정책을 결정하고 관리를 해주는 게 스케줄러다. CPU 입장에서는 스케줄러도 하나의 소프트웨어다. 스케줄러가 동작하는 그 순간에도 프로세스들은 동작하지 못한다. 그러면 넓은 관점에서 봤을 때 스케줄러도 하나의 프로세스로 인식할 수 있다. 따라서 스케줄러가 자주 동작하면 동작시키길 원하는 프로세스들이 그만큼 실행의 순서를 많이 얻지 못해 하나의 이슈가 될 수 있다.
프로세스 스케줄러 기능
둘 이상의 프로세스가 적절히 실행되도록 컨트롤
스케줄링 방법
스케줄링 알고리즘에 따라 다양함
스케줄러에 의한 프로세스 관리
1. 여러 개의 프로세스들이 존재
- Ready 상태인 프로세스들
2. 이 중에서 실행시킬 프로세스를 선택해서 실행되게끔 함
- 프로세스의 상태가 Running 상태로 바뀜
3. 현재 실행 중이었던 프로세스는 Ready 상태로 바뀜
프로세스의 CPU 할당 순서 및 방법을 결정짓는 일을 가리켜 스케줄링이라 한다. 이때 사용되는 알고리즘을 스케줄링 알고리즘이라고 한다. 또한 스케줄링 알고리즘을 적용해서 실제로 프로세스를 관리하는 운영체제 요소(모듈)를 가리켜 스케줄러라고 한다.
프로세스의 상태
위 그림에서 S와 E는 START와 END를 의미한다.
프로세스에는 여러 상태가 존재한다. 어떠한 경우에 저런 상태들이 되는지를 아는 게 중요하다.
각각의 상태의 특성, 상태 간 이동의 조건이 중요하다.
Running
Running 상태는 CPU에 의해서 실행 중인 상태이다.
CPU 안에 있는 CORE가 하나면 Running 상태의 프로세스의 개수는 최대 1개다.
Ready
Running 하고 싶은 상태이다.
프로세스는 Running 하는데에 있어서 준비가 끝나있다.
Ready 상태에서 Running 상태로 옮겨주는 거를 스케줄러가 해준다.
Ready 상태는 스케줄러가 본인을 선택하기를 기다리고 있는 상태이다.
A라는 프로세스를 실행시키기 위해 A.exe를 더블 클릭을 했다고 해서 바로 Running 상태로 가는 게 아니다.
반드시 스케줄러에 의해서 선택되어야지만 Running 상태가 될 수 있다.
- 그래서 실행시키는 모든 프로세스는 곧바로 Ready 상태가 된다. 이것이 바로 첫 번째로 일어나는 일이다.
- 스케줄러에 의해 선택이 됐을 때 Running 상태가 된다
연산중에서 CPU에 의존적인 연산이 있고 CPU에 의존적이지 않은 연산이 있다.
- CPU에 의존적인 연산
- ALU
- CPU에 의존적이지 않은 연산
- I/O 연산
그래서 I/O 연산과 CPU에 의존적인 연산은 병행이 가능하다.
일반적인 프로그램은 대부분 I/O 연산을 한다. 파일 I/O, 네트워크 상의 I/O 등 무수히 많다
현재 Running 상태의 프로세스가 I/O 연산을 시작했는데 그 연산이 오래 걸린다고 가정하자
그렇다면 해당 프로세스는 I/O 연산이 끝날 때까지 잠시 셔도 된다.
그래서 이 프로세스가 Ready 상태로 갈지 아니면 Block 상태로 갈지 고민을 해봐야 한다.
만약 프로세스가 Ready 상태로 가면 해당 프로세스는 스케줄러에 의해 다시 선택돼서 실행될 수 있는 프로세스다.
그래서 I/O 작업을 하고 있는 프로세스가 Ready 상태로 가서 다시 Running 상태가 됐는데 아직도 I/O 작업을 하고 있다면 굉장한 낭비다. 따라서 Ready 상태가 아닌 Blocked 상태로 가야 한다. 이처럼 별도의 I/O 작업을 하고 있는 프로세스를 위해서 Blocked라는 상태가 존재한다. 일반적으로 I/O 연산을 하고 있는 프로세스는 Blocked 상태에 가게 된다. Blocked 상태로 간 프로세스가 I/O 연산이 끝나게 되면 Ready 상태로 가야한다.
정리
I/O 연산과 같은 CPU의 도움을 크게 요구하지 않는 연산은 Blocked 상태가 되고 Blocked 상태에서 I/O 연산이 끝났을 때 경우에 Ready 상태가 된다.
- CPU가 고속으로 여러 개의 프로세스를 실행 중인 경우
- 현재 실행중인 프로세스가 I/O 연산을 하는 거는 아니지만 연산 시간이 길어져 다른 프로세스가 실행되어야 할 경우 Running 상태에서 Ready 상태로 가게 된다.
- I/O 연산 때문에 바뀌는 게 아니다.
ALU가 연산을 하기 위해서는 지극히 레지스터에 의존적이다.
현재 Running 상태의 프로세스 정보로 레지스터는 채워져 있다.
그런데 스케줄러가 B 프로세스를 실행시키려고 한다고 해보자
그러면 B 프로세스가 실행되기 위한 조건을 갖춰야 한다.
그 첫 번째 조건은 A 프로세스의 실행을 위해 레지스터 Set에 채워진 정보를 하드디스크나 메모리 영역에 저장하고 B 프로세스를 위해 저장되어 있던 데이터를 다시 레지스터 Set에 복원한다.
위 과정을 컨텍스트 스위칭이라 한다.
실행 중인 프로세스가 바뀔 때마다 빈번하게 일어나는 작업이다.
컨텍스트 스위칭(Context Switching)
여러 개의 프로세스들이 CPU 실행시간을 나누는 방식으로 동시 실행되는 효과를 얻고 있고 프로그램 실행의 상당 시간을 I/O 에 소모하기 때문에 둘 이상의 프로세스 실행은 CPU의 활용도를 높여 성능 향상까지 가져온다는 결론을 내릴 수 있다.
하지만 실행 중인 프로세스(Running 상태의 프로세스)의 변경은 시스템에 많은 부하를 가져다주기도 한다.
"CPU 내에 존재하는 레지스터들은 현재 실행 중인 프로세스 관련 데이터들로 채워진다."
그렇다면 우리는 한 가지 고민을 하지 않을 수 없다.
실행 중인 프로세스가 변경되면 CPU 내에 존재하는 레지스터들의 값이 변경되기 때문이다.
예를 들어 프로세스 A가 실행 중에 있다. 일정 시간이 지나서 이제 프로세스 B를 실행해야 한다.
그렇다고 프로세스 A의 실행이 완전히 끝난 것은 아니다. 잠시 후에 다시 실행되어야 한다.
따라서 프로세스 B가 실행되기 전에 현재 레지스터들이 지니고 있는 데이터들을 어딘가에 저장해야 한다.
이 데이터들은 프로세스 A가 실행을 이어서 진행할 경우 필요한 데이터들이기 때문이다.
어디 그뿐이랴? 프로세스 B도 새롭게 실행되는 프로세스가 아니라면, 이전에 실행될 때 레지스터들이 지니고 있던 데이터들을 어딘가에 저장해 놨을 것이다. 이 데이터들을 다시 레지스터에 복원시켜줘야만 한다. 그래야 프로세스 B의 작업이 멈춰진 부분에서부터 이어질 수 있다.
위의 그림은 프로세스 A가 실행 중인 상태를 보여준다.
프로세스 B는 실행되는 도중에 프로세스 A의 실행을 위해서 잠시 Ready 상태로 물러나있다.
현재 프로세스 A가 실행 중에 있고, 그러다 보니 레지스터 안에는 프로세스 A와 관련된 정보들로 채워져 있다.
반면 프로세스 B는 현재 Ready 상태에 있으며, 프로세스 B와 관련된 레지스터 정보가 메모리에 저장(Backup : 백업)되어 있다. 프로세스 B가 다시 Running 상태가 될 경우, 이 데이터들로 레지스터를 채워야만 한다.
그래야 프로세스 B는 마지막 실행 이후를 이어서 실행하게 된다.
위 그림이 보여주는 작업을 가리켜 컨텍스트 스위칭이라 한다.
프로세스 A 관련 레지스터 정보는 메모리에 저장되고, 프로세스 B 관련 레지스터 정보는 CPU의 레지스터에 복원시키고 있다.
여기서 중요한 사실!!
"실행되는 프로세스의 변경과정에서 발생하는 컨텍스트 스위칭은 시스템에 많은 부담을 준다."
이는 레지스터 개수가 많은 시스템일수록 그리고 프로세스 별로 관리되어야 할 데이터 종류가 많을수록 더하다.
이것이 바로 멀티 프로세스 운영체제의 단점이다.
그래서 시스템을 디자인하는 데 있어서, 이러한 컨텍스트 스위칭 부담을 최소화하기 위해 많은 노력을 기울이기도 한다.
따라서 두 가지를 동시에 고려해야 한다.
프로그램 실행과정에서 발생하는 I/O를 고려해보면 , 멀티 프로세스 기반의 프로그램 실행은 많은 부분 성능 향상에 도움이 된다.
하지만 컨텍스트 스위칭이 미치는 영향을 고려할 경우, 오히려 성능에 저하를 가져올 수도 있다.
성능과 관련된 이 두가지 사항을 결코 잊어서는 안 된다.
프로세스의 생성
프로세스를 생성하는 가장 쉬운 방법은 실행파일을 더블클릭해서 독립적으로 실행하는 것이다. 그러나 시스템 프로그래머는 또 다른 방법으로 프로세스를 생성할 수 있다.
"프로그램 실행 중에 또 하나의 프로세스 생성"
CreateProcess 함수의 이해
Windows는 프로세스 생성을 돕기 위해서 CreateProcess 함수를 제공하고 있다. 이때 CreateProcess 함수를 호출하는 프로세스를 가리켜 부모 프로세스라 하고, CreateProcess 함수 호출에 의해 생성된 프로세스를 가리켜 자식 프로세스라 한다.
프로세스를 실행하는 방법
- 바탕화면에 있는 실행 파일을 더블 클릭
- 바탕화면(부모 프로세스) → 더블 클릭한 프로그램(자식 프로세스)
- 프로그램상에서 프로그래밍을 통해 프로세스를 실행
- A 프로세스(부모) → B 프로세스(자식)
위 두 방식의 실행되는 과정은 완전히 같다.
CreateProcess 함수를 통해 프로세스를 생성하는 것은 마치 부모 프로세스가 더블클릭을 감지하고 자식 프로세스를 생성하는 것과 같다.
바탕화면을 관리하는 프로그램 코드에는 CreateProcess 가 있을 수 있다.
프로세스 생성 함수
CreateProcess 함수를 호출하기 위해서는 LPSTARTUPINFO와 LPPROCESS_INFORMATION 2개의 구조체를 선언해야 한다.
LPSTARTUPINFO 구조체를 통해서 생성하고자 원하는 프로세스 특성 정보를 여기에 설정하면서 인자를 전달함으로 CreateProcess 함수를 호출한다.
CreateProcess 함수는 인자로 전달한 정보를 참조해서 요구사항에 맞게 프로세스를 생성한다.
생성된 프로세스에 대한 정보를 반환해야 하는데 LPPROCESS_INFORMATION 구조체 변수를 선언해서 그 변수 정보를 CreateProcess 함수에 동시전달하면 LPPROCESS_INFORMATION 구조체에 생성된 프로세스 정보를 채워준다. 즉 LPSTARTUPINFO 구조체는 정보를 전달하기 위한 구조체이고
LPPROCESS_INFORMATION 구조체는 정보를 얻기 위한 구조체이다.
CreateProcess 함수는 프로세스가 별도의 프로세스를 생성하는 함수다
이때 프로세스를 생성하는 프로세스가 부모이고 부모 프로세스에 의해 생성된 프로세스는 자식 프로세스라 한다.
ipApplicationName
- 실행파일의 이름을 여기에 지정해 준다.
ipCommandLine
- main 함수 실행할 때 문자열로 매개변수를 전달해 주는데 이때 매개변수를 전달해주는 놈이다
- 실행파일의 이름과 매개변수 정보를 묶어서 하나로 ipCommandLine에 표현할 수 있다
cb
- 구조체 변수의 크기
- 구조체가 정해져 있는데 왜 크기를 인자로 전달해줘야 하는가?
- CreateProcess의 9번째 전달 인자는 정해져 있다.
- 근데 다른 게 오도록 개편하면 기존의 것과 구분하기 위한 정보가 필요하다
- 첫 번째 전달 인자(cb)를 통해서 그 구조체가 뭔지 구분 짓게 다는 의미다.
'운영체제 > 뇌를 자극하는 윈도우즈 시스템 프로그래밍' 카테고리의 다른 글
뇌를 자극하는 윈도우즈 시스템 프로그래밍 7장 (0) | 2024.09.05 |
---|---|
뇌를 자극하는 윈도우즈 시스템 프로그래밍 6장 (0) | 2024.09.05 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 4장 (0) | 2024.05.04 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 3장 (0) | 2024.05.03 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 2장 (0) | 2024.05.03 |