딩굴댕굴

운영체제의 기초 - 5. Processes and Threads 2

by jennysgap

BOX

Process Implementation : Process Scheduling

Dispatcher: 유저프로그램과 유저프로그램이 수행되는 중간에 개입을 해서 CPU를 Process A에서 B로 넘겨주는 역할을 함

이때 가장 중요한 것은 Dispatcher가 수행되기 위해서는 CPU를 차지해야 한다는 점임

다시 말해 CPU에 대한 점유권 CPU에 대한 Control이 유저프로그램에서 Dispatcher로 Dispatcher에서 다시 유저프로그램으로 넘어가야 한다.



Dispatcher가 수행된다는 것은 Kernel로 execution control이 진입을 하는 것임

그리고 유저프로그램으로 execution control이 넘어가는 것을 의미함

유저모드에서 커널로 모드 change하려면 interrupt 가 필요



OS는 Kernel mode에서 수행되는 라이브러리(함수들의 Collection이다)



System Call: 운영체제의 커널이 제공하는 서비스를 응용 프로그램의 요청하기 위한 인터페이스

                    즉, OS는 Kernel mode에서 수행되는 라이브러리 함수들의 집합체다.


커널 모드에서 수행되는 라이브러리 함수는 System call 함수 외에 한가지가 더 있음

그것은 interrupt service routine

왜냐? interrupt가 일어나면 모드 change가 일어나고 하드웨어적인 정의에 의해서 해당 interrupt service routine 불려짐


결론

커널 함수라고 하는 것은 System Call을 구현하는 함수들과 interrupt service routine들로 구성되어있다.



커널모드: 보안등급 격상된 수행모드, privileged instruction 수행할 수 있음

               시스템에 존재하는 모든 메모리를 아루런 제약없이 수행할 수 있음

유저모드: 굉장히 제약된, 주어진 메모리에서만 access하고 privileged instruction은 수행시킬 수 없는 환경


프로세스가 커널 모드와 유저 모드를 구분하는 방식

Process Status Word 레지스터 안의 특정 비트를 Mode Bit로 사용한다.

0: 커널모드,  1:유저모드



Dispatcher를 호출하는 방법 (2가지)

1. Non-preemptive(비선점) Scheduling: 프로세스가 자발적으로 CPU를 양보하여 다른 프로세스를 수행하는 스케줄링

2. Preemptive(선점) Scheduling: 운영체제가 강제로 프로세스로부터 CPU를 빼앗아 다른 프로세스를 수행하는 스케줄링


Non-preemptive Scheduling은 I/O block당하는 경우가 대표적

preemptive Scheduling은 Time-sharing OS에서 여러 유저에게 CPU time을 잘게 쪼개어 나눠줌. 나눠준 시간을 다쓰면 OS가 그 유저에게서 CPU를 빼앗음

preemptive Scheduling은 어떻게 구현할까? 타이머 하드웨어를 사용하면 됨

그래서 preemptive Scheduling은 H/W interrupt에서 촉발됨

Non-preemptive Scheduling은 S/W interrupt(Trap)에서 촉발됨

이것이 Dispatcher 단계로 넘어가는 핵심적인 내용



커널함수를 호출하기 위해서 S/W interrupt가 사용되면 system call 발생


Q, Kernel Mode Execution이 일어날 때 수행의 주체가 되는 프로세스는?

A. System Call을 호출한 사용자 프로세스이다.


Process는 2가지 요소가 있음

1. State

2. Execution stream (= Thread of control)




Process Implementation : Context Switching

디스패쳐의 역할

- 디스패쳐는 현재 수행중인 프로세스의 state를 안전한 곳에 대피(중단은 인터럽트로 이미 발생함)

- 스케줄라가 골라준 다음 프로세스의  state를 가져옴

Context Switching현재 수행 중인 프로세스의 state를 저장하고 다음 수행될 프로세스의 state를 불러오는 작업




Context saving: 지금 중단된 프로세스의 state들을 안전한 곳으로 대피시키는 것


state의 의미 3가지 (혼동하지 말기!)

- Context표현: 프로세스가 기억하고 있는 모든 정보들 <-> 상태의미: 현재 프로세스가 어떤 상황인지(running, waiting...)

1. Memory Context (메모리에 쌓아놓는 state): code, data, stack, heap

2. H/W Context: CPU Register들, I/O Controller Register Value들

3. Kernel Context 또는 System Context: OS가 프로세스를 위해서 내부적으로 커널내부에 담고 있는 정보들


- 일단 CPU레지스터들을 대피 (다음 프로세스가 사용할테니까)

- 커널 data structure 프로세스 별로 다른 항목이기 때문에 override 안되니 신경안써도 됨

- 메모리는? 3가지 옵션이 있음


1. 전혀 대피시키지 않는다 (ex: Multiprogrammed batch system)

   - CPU를 빼앗긴다 하더라도 메모리값은 유지되기 때문에 전혀 문제 안됨

   - 지금 당장 고민해야할 이슈는 아님


2. 전부 대피시키는 방법 (ex: unit programming할 때)

    - 메인 메모리에 하나의 프로세스만 올라가기 때문에 disk에서 나가고 새로운 프로세스가 들어옴

    - 속도 굉장히 느림


3. 메모리만 충분하다면 대피시킬 필요가 없지만, 가끔 over commit 됐을 때 (degree of multiprogramming 이 너무 큼)

    - 어쩔 수 없이 메모리 공간을 비우기 위해서 선택된 일부를 Disk로 보냄 (swap out)


3가지 중 H/W Context는 반드시 대피(CPU), 메모리는 필요한 경우 부분적으로 대패, 커널 Context는 냅둬도 된다


Q. CPU Register는 Disk로 대피시키는 것인가?

A. 일반적으로 한 단계 아래의 저장 장치로 데이터를 대피시키기 때문에 CPU Register는 Main Memory로 대피시킨다.



interrupt processing을 예로들어 stack을 설명

- 유저프로그램 수행: ADD instruction 수행 중간에 interrupt 발생

- 먼저 ADD instruction 수행은 끝마침. 끝나고 interrupt check

- PSW(Program Status Word)의 mode bit가 0으로 바뀜

- 마이크로 프로세스는 IRQ number를 확인해서 interrupt source를 확인(시작주소 확인)하고 jump

- 점프하면 interrupt service routine 이 수행 됨

- interrupt 수행이 끝나면 다시 복귀 (ADD instruction 다음 주소지로 복귀(return from interrupt수행)

- 그 주소ProgramCount(PC값)를 안전하게 대피시켜야 함 (stack의 top에 return주소를 대피시켜놨다가 인터럽트 끝나면 pop)

- 내 모드가 유저였는지 커널인지 알아야 회복시킴 (PSW의 값도 저장 시켜야 함!)

- PSW와 리턴주소값은 누가 넣을까? H/W

   interrupt service routine의 첫번째가 가장 먼저 수행되기 때문에 그 전의 값들은 Stack에 넣어야 한다

- interrupt service routine의 초반부에서 그 프로세스의 CPU Register값들을 대피시킴 (stack에)


정리

디스패쳐가 수행되려면 인터럽트가 반드시 필요

- 인터럽트가 걸리면 스택에 PSW, PC(리턴주소)값이 저장됨

- interrupt service routine이 수행됨

- interrupt service routine이 맨 처음 하는 일은 현재 프로세스의 CPU값들을 전부 Stack에 대피시킴


OS 안에는 global 변수가 하나 있음 (OSPCBCur)

- OS: OS변수라는 것을 뜻함

- PCB(Process Control Block)

- Cur: 현재

즉, 현재 수행되고 있는 프로세스의 PCB를 가리키는 global 변수다


PCB에 저장된 정보: ProcessID, 스케쥴링에 관한정보, Context Switching을 하는데 필요한 정보(stackPtr-스택포인터필드)


인터럽트가 걸린 상황 설명


- stack의 top에 PSW가 저장

- return address 저장

- 해당 interrupt service routine으로 jump

- CPU Register값 전부를 스택에 대피 (intel은 pushAll() 함수를 제공)

- Context save는 여기서 다 끝남 (CPU Register값이 스택에 다 대피됐기 때문)


이 인터럽트가 왜 발생했는지? 설명

- time-sharing OS에 timeout interrupt가 발생 그러면 스케줄러(다음 돌아야할 프로세스가 누구냐?) 호출

- 다음 돌아야할 프로세스의 PCB의 포인터를 interrupt service routine한테 전달해 줌

- PCB에서 얻어온 레지스터 값을 return from interrupt를 통해 context switching이 발생


Q. ARM 프로세서처럼 Link Register가 별도로 존재하면 Memory에 리턴 주소를 저장하지 않아도 되는가?

A. 그렇다. 개념적으로 리턴 주소를 다른 곳에 저장해야 하지만 마이크로 프로세서에 따라 저장 위치는 달라질 수 있다.


Q. PUSHA이 꼭 필요하다면 Hardware가 직접 하면 되지 않는가?

A. 프로그래밍 상황에 따라 일부 레지스터는 대피하지 않아도 되는 상황이 발생할 수 있기 때문에 Software 적으로 구현한다.


이 게임의 법칙에서 동작하지 않는 예외의 상황이 딱 하나 있다. 언제일까?

이 게임에 참가하려면 process는 반드시 적어도 1번은 Context Switching을 당해야 한다

그래야만 자기의 스택이 위처럼 만들어짐

그런데 그렇지 않고 이 게임에 참가하는 경우가 있죠

처음 프로세스가 만들어졌을 때

이런 경우에는 fake stack을 OS가 만들어줘야 함

OS이 어떤 프로세스를 생성하게 되면 그 프로세스의 스택을 마치 context switching을 한번이라도 당한 것처럼 만들어 줘야함




마치 인터럽트를 당한 것처럼 PSW와 return address를 넣었음

그렇다면 PSW에 뭘 넣어야 될까?

mode bit를 1로 세트(유저모드로)하고 interrupt를 enable시키고 이런 것들을 이용해 PSW값을 초기화 시킴

return address 값으로는 뭘 넣어야 할까?

그 프로세스의 시작주소를 넣으면 됨 (아직 아무것도 시작이 안됐으니)

그 다음 register들을 쭈욱 채워넣어야 하는데 이 register들은 뭘 넣으면 좋을까?

이것은 아무 값이나 넣어도 상관없음(왜냐하면 다 overwrite되기 때문)

그래도 깔끔한게 좋기 때문에 0으로 다 넣으면 됨

그리고 마지막으로 TCP-StackPtr(스택포인터필드)에 이 스택의 top 주소를 포인팅 하게 되도록 하면 됨!!!


이로써 Context Switching을 공부하게 됐음

이 스택은 어디에 있게 되는 거죠????

이 스택은 메인메모리에 있는 것임

메인 메모리 아무곳에 있음

그리고 각 프로세스 별로 전부 1개씩 스택을 갖고 있음 

메인메모리를 보면 스택이 여러개가 있고 단지 Active한 stack은 1개가 있다라는 점



정리

- OS 스케쥴러는 Policy부분과 공통적인 메커니즘 부분이 있다

- 메커니즘 부분이 바로 Context Switching을 담당하는 디스패쳐다

- 그 디스패쳐가 수행이 되려면 유저프로그램과 유저프로그램 사이에 mode change가 나서 수행이 되야 한다





출처 - http://snui.snu.ac.kr/ocw/index.php?mode=view&id=637

출처 - http://snui.snu.ac.kr/ocw/index.php?mode=view&id=638

반응형

블로그의 정보

jennysgap

jennysgap

활동하기