안녕하세요. 오늘은 process에 대해 알아보는 2번째 시간입니다. 저번 포스팅에서는 프로그램과 프로세스, linking에 대해 알아보았는데요.
2021.11.12 - [학부공부/운영체제] - 10. Process(1)
이번 시간에는 Context switch, Process state, Process control block인 PCB에 대해 알아볼까 합니다.
Linux에서
ps aux
라는 명령어를 통해 프로세스의 목록을 확인하실 수 있는데요. 직접 해보시면 proess 1번은 init이라는 uniq한 특성을 갖는 process가 표시될 것입니다.(init process에 대해선 곧 설명할 time이 올 것입니다.) k로 시작하는 process는 kernel에서 돌고 있는 프로세스입니다. 사실 CLI(Command Line Interface)에서 ps라는 명령어를 입력해서 shall이 받으면 해당하는 명령어에 맞추어 프로세스를 형성합니다.(이 부분과 관련해서는 fork(), exec()에 대한 설명을 보고 이해하실 수 있을 겁니다.) Windows에서는 Ctrl+alt+delete 조합을 통해 실행할 수 있는 작업관리자에서 프로세스 목록을 볼 수 있죠.(저의 경우 지금 이 시점에 앱이 3개, 백그라운드 프로세스가 155개 열려있다고 뜨는군요. 한참 내리니 Windows 프로세스가 101개 더 있습니다. 노트북이 주인을 잘못만나 고생하나보네요.) 자, 이렇게 ps명령어는 동작중인 프로세스에 관한 여러가지 정보를 알 수 있는데요.(참고로 ps는 Process Status의 약자입니다.)
ps 명령어(Interesting topic to study)
그럼 이렇게 많은 프로세스가 1s time quantum을 사용한다고 생각해볼까요? 극단적으로 CPU가 single core이고 1 core당 1개의 process만 가능하다고 가정하겠습니다.(물론 과거 코어 개수 = 스레드 개수가 만족할 때도 있었지만 하이퍼스레딩이 도입되고 multi core CPU가 대중화된 현재와는 전혀 동떨어진 가정입니다.) 계산하기 편하게 240개의 프로세스가 있다하더라도 1개의 프로세스당 4분에 1s만 사용할 수 있게 됩니다. 얼마나 끔찍합니까. 그렇다면 우리는 HW를 바꿀 수 없다면 time quauntum을 줄이는 방법을 생각하게 됩니다. 0.001s(= 1ms)로 바꾼다면 약 0.25s 만에 우리는 정말(?) 필요한 프로세스를 사용할 수 있게 됩니다. Concurrency측면에서 time quantum을 줄이는게 좋겠다는 결론에 도달했죠.(빠른 속도로 job을 바꿔가며 실행하면 우리에게는 실시간처럼 동작하는 것으로 느껴지겠네요.)
왜 위와 같이 말도 안되는 이야기를 하냐고요? 그만큼 실제 CPU에서 수행되는 프로세스는 빈번하게 바뀐다는 것을 이야기하고 싶었습니다.
12.01. Context switch
CPU에서 수행되는 프로세스가 바뀌는 것을 문맥전환(Context switch)이라고 합니다.
Time quantum expires, I/O Call
Timer quantum이 종료되어 timer 인터럽트가 들어오거나 멀티프로그래밍에서 언급했던 바와 같이 I/O 호출할 때, volutary하게 CPU를 내주는 경우 등이 있습니다.(다른 경우에 대해서 생각해보는 것도 좋을 것입니다. 예를 들면 mode(user, kernel)가 전환될 때도 발생하겠군요. 또 다른 종류의 인터럽트 중 문맥전환이 필요한 경우가 있을 수도 있습니다.) 커널의 dispatcher가 문맥 교환을 담당합니다. (디스패처는 나중에 이야기 할 State transition을 수행합니다.)
위의 모식도가 한번에 잘 정리해주는 것 같습니다. idle 또는 wait는 대부분 sleep state라고 생각하시면 됩니다. 그럼 이런 질문이 있을 수 있겠죠. P_new는 누가 결정하느냐? 그것은 지금 다루는 topic과 관련이 없습니다. 제가 저번2021.11.08 - [학부공부/운영체제] - 09. 운영체제와 컴퓨터 구조(2)
포스팅의 09.03. DMA(Direct Memory Access)_I/O 처리 기법을 소개하면서 인터럽트가 발생하면 스케쥴러가 어떻게 할지 결정한다 하였습니다. 여기서도 마찬가지 입니다. P_new로 들어올 프로세스가 2개 이상이라면 스케쥴링 되어서 들어옵니다. 이것은 인터럽트 이슈가 아니라 스케쥴링 이슈죠. 이런 설계 포인트를 통해 우리는 한가지 질문에 더 답변할 수 있을 것입니다. P_old가 P_new를 호출할까요?
No. 커널이 그 역할을 할 것입니다. 이전 포스팅에서 protection domain에 대해 배웠습니다. P_old가 P_new를 호출할 수 없는 이유 중 하나입니다. 즉, ISR은 idspatcher를 호출하고 끝납니다. 이러한 방식은 ISR이 짧아야하기 때문이기도 합니다.(자세히 보면 위의 모식도에는 ISR이 없군요.)
12.02. Process control block(PCB)
그렇다면 PCB에 대해 알아보겠습니다. 각 프로세스의 상태는 PCB로 표현될 수 있습니다. 커널 메모리에 위치하고 있고요.
Process state, PC(Program counter), CPU registers, CPU scheduling information, Memory-management information, Accounting information, I/O status information...
(pointer, process number, memory limits, list of open files...)
언뜻 봐도 많은 정보가 PCB에 포함됩니다.(컴퓨터 구조과목의 이해가 필요한 시점이네요.) 따라서 Context switching에는 overhead가 존재합니다. CPU에서 PCB로 저장해줘야 하기 때문이죠.
PCB의 Size는 얼마나 될까?
확실히 답변드리긴 힘들지만 Size 제한이 있을 거라는 것은 확실합니다. 커널 메모리에 존재하기 때문이죠. System이 booting하면서 커널 메모리를 initialize하는데 이때 configuration으로 file open 가능한 수 등이 정해져 있습니다. 그만큼 할당이 되는거죠. 또한 커널 메모리 전체가 dynamic하게 할당되기엔 기술적으로 어려움이 있을 것 같습니다. 만약 굳이 늘려야 한다면 linked list 형태 등으로 가능하긴 할 것 같습니다.(이 부분에 대해 자세히 아는 분이 계시다면 댓글 부탁드립니다.)
12.03. Context swtich_additional issue
그럼 문맥전환(문맥교환이라고도 표현하는 곳도 있네요. 제가 섞어 사용하더라도 양해 부탁드립니다.)과 관련하여 추가적인 이슈를 살펴보겠습니다.
12.03.1. System call은 문맥교환이 필요한가?
No. 지난번에도 설명한 적이 있는 것 같습니다. System call handler를 통해 kernel에서 System call을 수행하더라도 프로세스 ontext를 그대로 가져갑니다. 우리는 하나의 질문에 더 답할 수 있겠군요. 이러한 관점에서 볼 때 시스템 콜은 overhead가 인터럽트에 비해 작다고 생각할 수 있습니다.
12.03.2. CISC VS RISC
컴퓨터 구조 과목에서 배우셨을 텐데요. 간단하게 설명하고 가겠습니다.
CISC(Complexed instruction set computer) : 다양한 길이의 LOAD /STORE, 레지스터와 메모리의 명령어 형식을 제공합니다. 명령어의 길이가 달라서 동시의 여러개의 명령처리는 어렵죠. 하나의 명령어가 복잡하여 해석(디코딩)에 시간이 오래걸리며, 해석에 필요한 회로가 복잡합니다.
ex) Intel pentium processor
RISC(Reduced instruction set computer) : 1개의 instruction을 단순화한 것으로 pipeline구조에서 유리합니다.(pipeline 구조란 : 한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조를 가리킵니다. 이렇게 연결된 데이터 처리 단계는 한 여러 단계가 서로 동시에, 또는 병렬적으로 수행될 수 있어 효율성의 향상을 꾀할 수 있죠. 설계가 간단해 버그 존재 가능성 Down. compiler들이 소수의 명령어만 사용하므로 효율적인 코드를 생산할 수 있습니다.) 다만 RISC는 executable size가 더 크다는 것이 단점입니다.
ex) Arm processor
Clock 속도 : RISC > CISC
명령어 개수(decoding time) : CISC > RISC
문맥전환관점에서 볼까요. RISC에 초점을 맞추어 설명할 예정입니다. 최근에는 순수한 CISC를 찾아보기 힘들기 때문이죠.(성능향상에 유리한 것이 RISC이기 대문입니다. 하드웨어 관점에서 생각해보시면 됩니다. CPU clock 속도 향상에 물리적 한계가 있는 상황에서 명령어 병렬 처리는 엄청난 이득이죠.)
RISC는 물리적 공간을 CISC에 비해 절약하였기 때문에 register의 size가 더 큽니다.(executable size가 더 크죠.) 실제로 더 커야 합니다. 왜 커야할까요?
곱하기 같은 경우만 생각해보더라도 CISC와 같이 HW multiplier가 있으면 바로 나옵니다. 없으면 덧셈으로 구현되고 값을 계속 저장해야겠죠.
그럼 어떻게 해결할 수 있을까요?(Overhead가 있다면 어떻게 줄일 수 있을지 고민하는 것은 즐거운 일입니다. 말랑한 사고를 하게 해주죠.)
먼저 하드웨어적으로 레지스터를 jump하는 방법이 있겠죠. 1개씩 옮기는 것보다 이러한 instruction을 만들어 사용하면 됩니다. 실제로 대부분 사용하는 방법입니다.(하드웨어 문제는 하드웨어적으로 처리해야지 소프트웨어적으로 처리하면 오히려 오버헤드가 증가합니다.) 또 다른 방법으로는 레지스터를 많이 만들어서 복사 자체가 필요없게 만들어도 되겠지만 이 경우 cost문제가 있을겁니다.
12.04. Process state
Process state의 transition을 한눈에 알아볼 수 있는 좋은 자료가 있더군요.
New는 프로세스가 만들어지는 것이고 running은 실행되고 있는 상태, Sleep은 프로세스가 I/O completion 발생과 같이 어떠한 이벤트를 기다리는 상태, Ready는 프로세스가 dispatched되는 것을 기다리는 상태, Terminate는 실행이 종료된 상태를 의미합니다. 여기서 볼 수 있는 각 queue들은 커널 내부의 data structure입니다.
그럼 앞서 Context switch에서 보았던 idle 상태는 무엇일까요?
Idle 상태는 power save mode(cpu sleep)도 아니고 packet도 들어오지 않고 아무것도 안합니다. 그럼 컴퓨터가 쉰다는 것은 무엇을 의미할까요? CPU가 쉴 수 있을까요?
CPU 전압과 clock 속도를 낮추면 됩니다. idle을 일단 ready queue에 있는 상태라고 생각하면 됩니다.
오늘은 프로세스와 관련하여 Context switch를 중심으로 살펴보았습니다. 실제로 프로세스가 어떻게 생성되고 종료되는 지에 대해서는 따로 살펴볼 기회가 있을 겁니다. 질문, 후기 등 댓글은 언제나 환영입니다. 함께 고민해볼 이슈를 던져주시면 정말 감사할 것 같습니다. 이 세상에 쓸모없는 질문은 없습니다. 전혀 무관해 보이는 질문이 새로운 아이디어의 원천이 될 때도 있죠. 독학이라 아직 많이 부족하지만 나중에 이 과목을 수강하고 나서 포스팅의 오류를 찾아내는 세션을 가지는 것도 재미난 시간이 될 것 같습니다. 긴 글 읽어주셔서 감사합니다.
'학부공부 > OS_운영체제' 카테고리의 다른 글
14. Process(3) (0) | 2021.11.17 |
---|---|
13. Garbage collector [Interesting topic to study] (0) | 2021.11.15 |
11. bss [Interesting topic to study] (0) | 2021.11.12 |
10. Process(1) (0) | 2021.11.12 |
09. 운영체제와 컴퓨터 구조(2) (0) | 2021.11.08 |
댓글