초점이 모호해지는 기분이 들어서 질문 다시 올리겠습니다.
제가 궁금한 것에만 포커스를 맞추려고 합니다. 이해 부탁드리고
먼저 이 궁금증의 발단부터 말씀드리겠습니다.
윈도우에서는 멀티-코어(물리적 CPU코어) 를 지원합니다.
그리고 윈도우에서는 하나의 CPU 코어당 하나의 PRCB 라는 프로세서 관리 구조체를 갖습니다.
각각의 PRCB는 자신만의 쓰레드 디스패처 데이터베이스를 갖으며,
PRCB 구조체 내용상 각각의 IDT와 VAD외에 많은 고유한 자료구조를 갖습니다.
-------------------------------------------------------------------------------------------------------------------------------------
정리해서 말하자면 하나의 CPU 는 하나의 PRCB에 대응되며, 각자 자신의 쓰레드 디스패치 데이터베이스를 가지고 쓰레드 디스패칭을 하고 있습니다. 쓰레드를 스케쥴링 함에 있어서 멀티레벨큐 방식을 사용합니다.
제가 궁금한건 이런 이론적인게 아닙니다.
윈도우에서
"PRCB를 코어에 대응되게 만들어놨는데, 이게 어떻게 CPU코어와 대응되어 동작하는지"
가 제 질문의 요지입니다.
다시 말씀드리자면, PRCB하나가 쓰레드를 하나 가져와서 실행합니다.
PRCB 다른 하나도 쓰레드를 하나 가져와서 실행합니다.
근데 여기서 어떻게 PRCB하나가 쓰레드를 하나 동작하는 것과 다른 PRCB가 다른 하나의 쓰레드를 동작하는 것을
CPU Core에 대응되게 동작할 수 있느냐?? 이게 도대체 이해가 안됩니다.
예를 들자면 인터럽트를 처리하는 IOAPIC같은 경우는,
( 물론 IOAPIC에서 어떤 코어에서 이 인터럽트를 처리할지 결정해 그 코어의 Local APIC로 전달해주죠. )
Windows의 IDT 와 대응되기 위해서 물리 메모리에 매핑을 해놓습니다.
이를 토대로 Vector를 얻어서 IDT Entry를 찾아갈 수 있습니다.
하지만 PRCB - Cpu core 간의 관계에서는 어떤 단서도 찾을 수가 없어서 답답해서 질문을 드립니다.
이에 대한 어떤 단서라도 좋습니다. 댓글 부탁드립니다. ㅠㅠ
댓글 14
-
백창우
2010.11.02 01:25
-
박한범
2010.11.02 14:59
.
창우님이 말씀하신 내용은 모두 이해하고 있습니다.
다만 저는 하나의 프로세스에 하나의 PRCB가 생성되는게 의미가 없다고 생각하지 않았습니다.
말씀하신 대로 그리고 정말로 PRCB가 단순히 자료구조라면 왜 코어 수에 대응하는 PRCB를 만들고 각 프로세서 관리 구조체가 제각각의 스케쥴링 디스패치 데이터베이스를 만드는지는 참 의문입니다. 아무 의미도 없는데 말이죠?
해서 저는 이전 경험에 비춰볼때, MSR 와 비슷한, 혹은 APIC의 벡터변환->IDT와 비슷한, 혹은 특정 명령어를 사용한 multi-core 를 제어하기 위한 어떤 특별한 동작원리가 있지 않나 궁금해서 질문드렸습니다.
말씀하신대로 PRCB가 단순한 구조체라고 한다면,
각 PRCB가 각자의 Thread를 처리하는 동안 배정받는 cpu-core도 랜덤하게 들어가게 되겠군요.
답변감사드립니다
-
백창우
2010.11.02 17:01
저는 하나의 프로세스에 하나의 PRCB가 생성되는게 의미가 없다고 생각하지 않았습니다.
- 우선 하나의 processor에 하나의 PRCB가 생성되는건 당연합니다. PRCB는 하나의 core 상태를 나타내는거니깐요.
정말로 PRCB가 단순히 자료구조라면 왜 코어 수에 대응하는 PRCB를 만들고 각 프로세서 관리 구조체가 제각각의 스케쥴링 디스패치 데이터베이스를 만드는지는 참 의문입니다.
- PRCB는 정말 단순한 자료 구조이고, 각 core의 상태를 표현하기에 각 core당 PRCB가 하나씩 존재합니다. PRCB에 각각의 ready queue가 존재하는 이유는 스케줄링할때 cache affinity, load balancing, load unbalancing 등등등과 같은 여러 multi-core 최적화를 하는데 유용하기 때문입니다.
각 PRCB가 각자의 Thread를 처리하는 동안 배정받는 cpu-core도 랜덤하게 들어가게 되겠군요.
이건 무슨 말씀이신지 의미를 잘모르겠군요.
-
백창우
2010.11.03 13:41
우선 잘못 알고 계신점을 지적해드리겠습니다.
1. 모든 processor는 전원이 인가되자마자 수행할 부분이 정해져있고, 전원이 인가되자말자 해당 부분을 수행합니다.
2. "core의 ip"라는 용어는 말씀하신 의미로는 존재하지 않습니다.
3. OS가 관리하기 전까지는 PRCB와 core가 관계가 없는것이 맞습니다.
4. PRCB를 만드는것과 preemption, yield는 직접적인 관련이 없습니다.
5. FS register에 PRCB의 주소를 넣는것과 interrupt 처리는 직접적인 관련이 없습니다.
6. sp2에서도 multi-core interrupt 처리는 잘되었습니다. sp3에서 그렇게 바뀐것은 성능 향상을 위해서거나 보안상 issue일 수 있습니다.
7. cpuid와 windows registry는 관계가 없습니다.
그리고 질문에 대한 답변을 드리면
1. OS에서 multi-core를 제어하기 위해 하는 초기화 단계는 어떤게 있습니까?
각종 H/W 초기화 및 자료구조 초기화 (부팅 단계)로써 끝입니다.
2. cpu 명령어가 현재 core의 넘버와 같은 식별 가능한 값을 얻을 수 있다고 할때, 어떻게 각 core 별로 원하는 코드를 실행할 수 있습니까?
해당 core에서 동작하는 소스에서 cpuid instruction을 발행하면 됩니다.
이전에도 말씀드렸듯이 오해하고 있는 부분은 이 부분입니다.
어떤 code가 동작하는것 자체가 어떤 core에서 동작하는 것입니다.
어떤 core에 어떤 thread를 수행 시킨다는 말의 의미는 해당 core에서 동작하는 OS(scheduler)가 해당 thread를 수행시켜 OS(scheduler) 수행이 끝남과 동시에 해당 thread가 수행된다는 말입니다.
다른 core도 마찬가지 입니다.
코드 덩어리인 OS가 core 내의 수행도 없이 thread를 수행시키고 cpuid instruction을 issue하는 일은 일어나지 않는다는 것입니다.
한번 곰곰히 생각해보시기 바랍니다.
-
김남형
2010.11.03 14:27
잘 모르니 간단히 답변 남겨봅니다.
1. 리눅스에서도 비슷한 개념의 percpu 영역이 존재합니다. 이 영역은 각 CPU의 fs 혹은 gs 레지스터를 통해 접근하며 해당 CPU에 관련된 정보들 만을 모아둡니다. 스케줄링 시 사용하는 runqueue도 percpu 영역에 들어있습니다.
2. C언어에서 제공하는 if-else 혹은 switch-case 문이면 충분하지 않을까요?
-
박한범
2010.11.03 12:05
우선 제가 이해하지 못하겠는것은 "PRCB1에서 Thread1을 가져와서 실행하고 PRCB2에서 Thread2를 가져와서 실행"했으면 당연히 load balancing이 일어나지 않는한 core1과 core2에서 수행되어야지 어떤 core에서 수행될지 알수가 없다는 점이 이해가 가지 않습니다
-> 이 부분에 대한 제 생각은 ,
각 Core가 초기화되서 각자 실행하는 부분이 정해지기 전, 그러니까 OS에서 core를 관리하기 위한 구조체를 설정하고 core의 ip를 초기 값에서 OS가 관리할 수 있는 상태가 되기 전까지는 PRCB와 같은 Processor 관리 구조체와 CPU-core는 관계가 없는 상황이라고 생각했습니다.
나머지는 그저 부속에 지나지 않습니다. 마치 첫 단추가 제대로 안껴지면 나머지 순서도 엉망이 되는 것처럼 말입니다.
굳이 타임인터럽트를 예로 든 이유도 거기에 있습니다.
선점이든, 양보든 모두 OS레벨의 코드이고 이를 수행하기 위해서 기본적으로 PRCB를 만드는데,
PRCB와 코어가 매치가 안된 상황에서 어떤 코드가 의미를 갖을 수 있을까요?
하지만 그간의 내용과 경험상, 백창우님에게는 당연하게 받아들여지는 부분이 저같은 초심자에게는 아닐 수가 있습니다. 그런 차이로 인해서 질문의 요지가 전달이 안되는 것 같습니다. 하지만 백창우님이 당연하지만 저보다 많은 지식과 경험을 가진 선생님의 입장이시니 제가 질문을 해볼까 합니다.
1. OS에서 multi-core를 제어하기 위해 하는 초기화 단계는 어떤게 있습니까?
죄송하지만 또 윈도우를 예로 들어보겠습니다. 윈도우에서는 각 프로세서 별로 인터럽트를 처리하기 위해 FS레지스터에 PRCB의 주소를 넣어놓고 있습니다. sp2에서는 절대주소를 썼지만 sp3에서 바꼈죠. 이제와 생각하는 거지만 이것도 멀티코어를 제어하기 위한 수정이 아닌가 합니다.
2. cpu 명령어가 현재 core의 넘버와 같은 식별 가능한 값을 얻을 수 있다고 할때,
어떻게 각 core 별로 원하는 코드를 실행할 수 있습니까? 예를 들어 CPU0~3이 있다고 하면 CPU0의 레지스트리 세팅, CPU1의 레지스트리 세팅을 해야된다고 한다면 말입니다.
답변 부탁드립니다. ^^; 시간을 너무 뺏는건 아닌지
-
백창우
2010.11.03 03:33
우선 저는 Windows에는 큰 관심이 없어 내부 구조에 대해서 잘 모른다는 말씀을 먼저 드려야 할것 같군요.
지금까지 제가 질문에 답변해드렸던것은 그동안 상용 OS들을 직접 만들어 오면서,
multi-core OS들이 가지고 있는 기본적인 지식들을 바탕으로 답변을 해드렸습니다.
그런데 점점 어긋나고 있는것이 느껴지네요.
우선 제가 이해하지 못하겠는것은 "PRCB1에서 Thread1을 가져와서 실행하고 PRCB2에서 Thread2를 가져와서 실행"했으면 당연히 load balancing이 일어나지 않는한 core1과 core2에서 수행되어야지 어떤 core에서 수행될지 알수가 없다는 점이 이해가 가지 않습니다.
그리고 scheduling은 timer interrupt뿐만 아니라 thread yield, wait, preemption등이 일어날 수 있는 code 곳곳에서 발생할 수 있는 상황인데 왜 굳이 timer interrup만이 가정되어야 하는지도 이해가 가질 않고,,,,
OS는 당연히 PRCB에 있는 정보 또는 cpuid등과 같은 operation을 통해 현재 코드가 동작하고 있는 core를 알 수 있고, 현재 코드가 동작하고 있는 자체가 현재 core에서 동작하는 것인데, 이것을 어떤 core에서 동작하는지 모른다는것 또한 이해가 안가고,,,,
등등 질문을 들으면 들을수록 점점 더 총체적으로 이해가 가지 않네요.
혹시 어떤 code가 어떤 core를 선택해서 수행시켜야 한다고 생각하시는 것인지요?
만약 그렇다면 어떤 code(예를 들면 scheduler code와 해당 scheduler가 수행시키는 thread code)가 동작하는것 자체가 어떤 core에서 동작하는 것이라 말씀드릴수 있을것 같습니다.
-
박한범
2010.11.02 22:57
음.. 뭔가 제 느낌으론 약간 어긋난 부분이 있는것 같습니다.
OS가 각 코어를 관리하기 위한 구조체를 만들고, 각 구조체가 자신들의 ready queue 에서 쓰레들을 가져와서 실행합니다.
이 부분은 정확합니다. 마소에서 나온 Internals 에도 정확히 나와있으니까요.
제가 궁금한 부분은;
코어1 과 코어 2가 있다고 하고, 이에 대응해서 OS가 PRCB 1과 PRCB 2를 만들었다고 가정하고 봤을때,
PRCB1에서 Thread1을 가져와서 실행하고 PRCB2에서 Thread2를 가져와서 실행하는데 이게 코어1-코어2로 분배되어 동작한다는 보장이 없다는 말입니다. PRCB는 말씀하셨듯이 OS에서 프로세스를 관리하기 위해 만든 단순한 구조체입니다. 이 구조체가 쓰레드를 하나 가져와서 실행한다고 해도 그게 CPU 코어에 맞게 배분될 거라고 생각하기 어렵단 말입니다.
물론 가장 이상적인 것은 PRCB1에서 가져온 Thread1이 CPU1에서, PRCB2에서 가져온 Thread2가 CPU2에서 동작하는 것이겠지만 말입니다.
그래서 곰곰히 생각을 해봤습니다.
OS-CPU관계에서 볼때 CPU 독립적인 부분은 외부 IOAPIC에서 오는 인터럽트 신호가 유일합니다. 그 생각이 들자 타임 인터럽트가 떠오르더군요. 인터럽트 신호 0 번으로 윈도우에서는 이 인터럽트 신호에 맞춰 현재 PRCB의 Thread의 퀀텀값을 감소시키고 퀀텀 유무에 따라서 NextThread로 바꿔주는 역활을 합니다.
이런 식으로 각 core가 타임인터럽트에 따른 쓰레드 스케쥴링을 할 수 있다고 한다면? 하고 가정을 해봤습니다.
사실 별 다른 가정도 아닙니다. 스케쥴링은 이렇게 동작하니까요;; 다만 그렇게 생각하기 어려웠던 이유는 결국 풀리지 않는 의문 하나때문입니다. 첫 단계, 그러니까 멀티-코어를 제어하기 위한 첫 단계에 대한 의문입니다. 어쨌든 이 가정대로라면 OS 는 각 core를 제어하는 방법이 있어야만 합니다. 처음부터 제가 의문이었던 것도 이 부분이었구요. 물론 이 가정이 틀리더라도 OS는 각 core를 구분지어서 컨트롤할 수 있는 방법없이는 멀티코어에 맞는 멀티프로세싱이 불가하다는 생각입니다. 만약 그렇지 않다면 위에서 언급했듯 쓰레드는 임의의 core혹은 최악의 경우 하나의 core에서 전부 실행해버리게 되겠죠...
이에 대한 의문은 왠지 메뉴얼에 나와있는 느낌이 들어서 읽어보려고 하고 있습니다 ^^
다시 한번 답변 감사드립니다.
-
myskan
2010.11.03 08:37
PRCB는 말씀하셨듯이 OS에서 프로세스를 관리하기 위해 만든 단순한 구조체입니다. 라는 문장이 보이는데 군데 군데 보면 프로세서와 프로세스가 섞여서 사용되어 내용파악이 어렵습니다.
백창우님은 PRCB가 프로세서를 관리하기 위한 구조체라고 말씀하시고 있고 박한범님은 프로세스를 관리하기 위한 구조체라고 말씀하시고 있는데 (제가 정확히 글들을 이해하고 있다면) 이부분이 두분의 의견차이가 나는 곳이 아닐까 싶습니다.
-
백창우
2010.11.03 10:07
박한범님이 혼용해서 사용하는시것 같아 의미상 맞을것 같은 processor로 해석했습니다. ^^
============ 인용 ============
"하나의 CPU 코어당 하나의 PRCB 라는 프로세서 관리 구조체를 갖습니다."
"왜 코어 수에 대응하는 PRCB를 만들고 각 프로세서 관리 구조체가 제각각의 스케쥴링 디스패치 데이터베이스를 만드는지는 참 의문입니다."
"PRCB는 말씀하셨듯이 OS에서 프로세스를 관리하기 위해 만든 단순한 구조체입니다." -
김남형
2010.11.03 10:56
간단히 정리해보면
코드를 실행하는 주체는 CPU입니다.
CPU에서 실행되는 (OS) 코드는 항상 자신이 몇 번째 CPU인지 알고 있습니다.
스케줄링 시에 CPU는 시스템 전체의 PRCB 중에서 자신의 것에만 접근하여 작업을 가져와서 처리합니다.
실행 도중 새로운 작업이 생기면 시스템 전체의 PRCB 중에서 제일 널널한 곳에 넣어둡니다.
-
박한범
2010.11.03 15:30
흠흠.. 레지스터를 레지스트리라고 오타쳤군요. 죄송합니다.
이제야 어느정도 감을 잡고 있습니다. 물론 이 부분은 문서로도 누가 알려줘서도 아니고 질답 중에 개인적으로 터득한 내용이라 확신이 서진 않습니다. 대화와 토론이란 이래서 좋구나 하는 생각이 드네요.
처음에 제가 원한 답은, 지금 제가 생각하고 있는게 맞다고 가정했을때,
PRCB를 core에 대응되게 끔 해주는 역활을 하는 FS:[1Ch]와 같은 레지스터의 역활이었습니다.
백창우님 말씀대로 CPU 레지스터를 세팅하는 것 만으로도 multi-core에 대한 제어가 가능하다는걸 생각해내는데
한 세월은 걸렸네요 -_-;;
multi-core를 os에서 관리할때 결국은 entry point가 필요한데 그 지점이 어디냐는 의문이 들었는데,
역시 지금 제가 생각하는게 맞다면, FS:[1Ch] = PRCB self pointer 를 세팅함으로서 타임인터럽트에 대한
인터럽트 디스패치 루틴에서 이 역활을 해줄거라고 보입니다.
나머지는 그냥 부속적인 부분입니다.
어쨋든 저도 글쓰는 연습을 많이 해야겠다는 생각이 들긴 하네요.
제가 오해한 부분이 있었는데
sp2든 sp3든 FS레지스터를 참조해서 PRCB를 얻습니다.
절대값으로 매치가 되어 있는 경우는 단 한번도 코어가 2개 이상이 되지 않은 경우네요.
여기서 힌트를 얻을 수 있었습니다.
긴 문답 동안 정말 고생많으셨고 관심 보여주신 분들 모두 감사합니다. ^^
-
박한범
2010.11.04 00:04
흠흠. 예예. 제가 용어 선정에 신중하지 못한 점이 있습니다.
곧 이 부분을 정리해서 다시 올리도록 하겠습니다.
그때도 지금과 같은 답변 부탁드려도 되겠지요? ^^;;
제가 생각하고 있는 것이 '가정'에 지나지 않는다는 걸 잘 알고 있고,
여기서 끝내려는 의미에서 댓글을 단게 아니고 그 전에는 감을 전혀 못 잡고 있었는데,
문답을 하면서 겨우 실마리를 풀어낸 사항에 대해서 정리를 하고 다시 질문을 드리려고 합니다.
감사합니다
-
백창우
2010.11.03 21:09
CPU 레지스터를 세팅하는 것 만으로도 multi-core에 대한 제어가 가능하다는걸 생각해내는데한 세월은 걸렸네요
- 아닙니다. cpuid instruction으로써 cpuid를 읽고 그 값을 percpu와 같은 각 core에 고유한 영역에 저장후 그 값으로써, if ~ else, switch 문 같은 것으로 각 core별 제어를 합니다.
하지만 이것 또한 의문을 가지시는 부분의 답은 아닙니다.
각 core별로 공통의 OS 코드가 제어를 합니다. 해당 core에서 동작하는 OS 코드가 해당 core를 제어한다는 말입니다.
아직도 오해하고 계십니다.
FS:[1Ch] = PRCB self pointer 를 세팅함으로서 타임인터럽트에 대한 인터럽트 디스패치 루틴에서 이 역활을 해줄거라고 보입니다.
이것 역시 아닙니다. OS entry point는 이해하고 계신 entry point가 아닌 그냥 OS 코드에 있는 entry point입니다.
.
ㅋㅋㅋㅋㅋㅋㅋㅋ
관점을 정말 잘못 잡고 계시군요.
이때 PRCB는 무슨 객체가 아닌 그냥 단순한 구조체(?)입니다.
상태를 저장하는 역할만 담당하는 자료구조란 말입니다.
쉽게 예를 들면 PCB 또는 TCB를 예를들수 있겠네요.
Task Management 또는 Scheduler에 의해 process 또는 thread가 running state에서 ready state로 변경되었다고 가정합시다.
해당 process 또는 thread의 state를 변경한 것은 task management code 또는 scheduler code 또는 여러 다른 kernel의 code들에서 변경을 하였겠지요.
여기서 변경을 했다는 말은 해당 context의 PCB 또는 TCB의 state fild에 변경된 값을 넣고, 실제 code 수행흐름, 즉, kernel의 전체 context 상태를 그렇게 만들었다는 것을 의미하지요.
우리는 여기서 "process 또는 thread의 상태가 변경되었다."라고 이야기 하지만 "PCB 또는 TCB가 상태를 변경시켰다."라고는 말하지는 않습니다.
이것과 마찬가지로 PRCB는 core의 상태를 저장하고 있는 자료구조입니다.
core의 각종 상태를 나타내고, kernel의 어떤 코드가 해당 core의 상태를 바꾸면 그것을 기록해놓는 자료구조입니다.
예를 들면 각 core마다 각 PRCB가 있고, 각 PRCB는 내부에 scheduler를 가지고 있겠죠.
어떤 core가 idle state가 되어 scheduler 코드가 호출되면서 새로운 thread를 해당 core에 받아왔습니다.
그러면 PRCB내에 있는 scheduler부분에 해당하는 ready queue에 해당 thread가 등록이 되겠죠.
그리고 해당 thread가 해당 core에서 수행될것 입니다.
여기서 PRCB에 해당 thread가 등록되었다는 말의 의미는 무엇일까요?
PRCB내에 scheduler 영영에 해당하는 ready queue에 해당 thread의 TCB가 등록되었다는것을 의미하죠.
그러면 그건 누가 등록을 시켰을까요?
PRCB가 등록을 시켰을까요? 아니죠. 단순한 자료구조인 PRCB는 어떠한 일도 할수가 없죠.
kernel의 특정 code가 등록을 시켰겠죠. 여기서는 scheduler 코드일겁니다.
그리고 그 정보를 PRCB에 기록했겠죠. 아니면 scheduler 경우와 같이 기록 정보 자체가 등록일수도 있는거고요.
이렇게 PRCB는 해당 core에 관한 상태 정보 및 thread 정보, scheduler 정보등을 kernel의 특정 code가 바꿀때 마다 PRCB에 등록된 정보도 매번 바꾸니, PRCB는 core의 상태를 표현한다고 볼수가 있겠죠.
결론은 PRCB는 각 core마다 존재하는 단순한 자료 구조입니다.
kernel의 코드에서 각 core의 상태를 바꿀때마다 PRCB의 값을 변경합니다.
이로인해 PRCB는 각 core의 현재 상태를 나타내게 됩니다.
이해가 되셨는지요?