본문 바로가기

[운영체제] 2주차 (2)

여기부터 3장

 

2장에서 제일 중요한 건 System call

 

 

 

Process

실행 중인 프로그램: 디스크에 있는 프로그램 + 프로그램 실행을 위한 resource들

 

Process memory map

Ex) 메모리: Stack, Heap, Text section, Program counter, Data section(전역변수 저장)...

Text: 프로그램 코드

Data: (초기화된)전역변수, 정적 변수 (bss: 초기화되지 않은 전역변수)

Heap: 동적 메모리

Stack: 지역변수나 etc

 

 

 

 

Time shared 에서 관리하는 기본 단위

 

I/O Bound Process: I/O 작업을 많이 하는 프로세스

CPU-Bound process: CPU 작업을 많이 하는 프로세스

 

실행하는 동안 종료 시까지 자신의 상태를 변화시킨다.

- new: 프로세스가 만들어지는 중

- running: 명령어 실행 중

- waiting: 작업 대기

- ready: CPU 할당 대기 (Ready queue에 들어간 상태)

- terminated: 종료

 

Diagram of Process State

< 교수님피셜) 이 그림 중요함 >

 

scheduler dispatch: 스케줄러가 CPU 할당

 

프로세스는 위 5가지 상태에서 변이하며 실행한다

 

 

PCB(Process Control Block)

프로세스와 관련된 모든 정보는 PCB에 저장된다.

 

- 현재 State, 다음 실행할 명령어 주소(Program counter) 등

 

* MMU: Logical address space -> Physical address space 변환 (Page table, Segmentation table)

나중에 배울 거임

 

Context switch diagram

<교수님피셜) 이 그림 중요함>

 

여러 개의 프로세스를 메모리에 올린 후 한 프로세스가 CPU를 사용하다가

I/O 작업을 하게 되거나 time quantum이 끝나면 다른 프로세스에 CPU를 할당해준다.

위 그림이 그 과정.

 

이 작업은 다음과 같이 이루어진다.

 

① $P_0$의 정보를 $P_0$의 PCB($PCB_0$)에 저장한다.

② $P_1$의 작업을 시작해야 하므로 $PCB_1$의 모든 정보(Program counter, Register 값, ...)를 읽어온다.

③ $P_1$ 실행

④ 현재 $P_1$의 상태를 $PCB_1$에 저장한다.

⑤ $PCB_0$의 모든 정보를 읽어온다.

⑥ $P_0$을 실행한다.

 

이런 작업을 Context switch라 한다.

 

 

Process scheduling

Process scheduler는 CPU를 할당할 프로세스를 선택한다.

이 때 선택시간은 아주 짧아야 한다.

-> Scheduling queue

 

OS는 다양한 Scheduling queue를 관리한다.

- Job queue: 메모리에 올라갈 준비가 된 작업

- Ready queue: CPU를 할당받을 준비가 된 프로세스

- Device queue: 각 Device마다 존재, 그 Device를 액세스 하려고 하는 프로세스

 

프로세스는 여러 상태를 전이하며 실행된다 -> 여러가지 scheduling queue를 전이하며 실행된다.

프로세스 생성: new
CPU를 할당받을 준비: Ready queue (State: ready)

CPU 할당받음: (State: running)

Disk로부터 데이터 요청: waiting state(해당하는 device의 device queue에서 대기)

데이터 받음: waiting state 종료, running state로 전환

할당 시간 만료: Ready state로 전환, Ready queue로 전환

fork: 생성된 Child process 역시 다른 프로세스처럼 ready queue로 들어가 ready state가 됨

interrupt 대기: waiting statewaiting state에서

interrupt: ready queue로 이동 (ready state)


Scheduler

- Short-term schduler(CPU scheduler)

ready queue에 있는 프로세스 중 어느 프로세스에 CPU를 할당할까? -> 빈번하게 동작: short-term(수 ms 안에 호출)

 

- Long-term Scheduler(Job schduler)

사용자가 제출한 job 중 어느 job을 ready queue에 올릴까? 수 s, minute 안에 호출

멀티프로그래밍의 정도를 이 스케줄러가 결정함

이 스케줄러가  I/O-bound process와 CPU-bound process를 잘 섞어서 올려야

두 장치를 모두 바쁘게 할 수 있다(둘 중 하나만 올리면 두 장치 중 하나는 놀게 되니까).

즉 process mix를 잘 해야 한다.

 

- Medium-term scheduler

Swapping: 큰 프로세스 실행 시 가용 메모리가 모자랄 경우 이미 할당된 프로세스를 디스크로 옮기고 그 공간을 큰 프로세스에게 할당하는 것

어느 프로세스를 swap out(Memory -> Disk)하고 어느 프로세스를 swap in(Disk -> Memory)할 것인가?

-> Medium-term scheduler가 결정

 

Context switch

<교수님피셜) 이거 중요함?>

$A$라는 프로세스와, $B$라는 프로세스가 있다고 하자.

$A$를 실행하고 있다가 $B$로 CPU 할당이 바뀌면 $A$가 실행되고 있던 context를 $PCB_A$에 저장하고,

$PCB_B$에 있던 context를 이용해 $B$를 실행한다. = context가 바뀐다

 

이 작업이 없으면 두 프로세스를 동시에 실행할 수 없음

 

Context switch에 걸리는 시간은 순수한 overhead다

: 이 시간동안은 A의 작업이나 B의 작업이 이루어지지 않는다. -> 짧을수록 좋다

Multitasking 또는 Multiprogramming을 위해 지불해야 하는 비용이라고 보면 될 듯.

 

 

어느 부분은 process에 관계 없이 기계적으로 할 수 있고, 어느 부분은 프로세스에 따라 달라진다.

전자의 경우 하드웨어로 구현하면 빠르게 수행할 수 있다. Ex) ARM processoe

하드웨어로 처리하는 부분이 많을수록 빨라지지만, flexibility가 떨어진다는 단점이 있다.

 

Process Opreation

프로세스 생성(Creation)

프로세스 종료(Termination)

우선순위(Priority) 설정/얻기

Get ID

Get PCB

 

Process creation

프로세스 $A$에서 프로세스 $B$를 생성하면 $A$는 Parent process, $B$는 Child process.

 

일반적으로 각 프로세스는 프로세스 ID(PID, Process IDentifier)로 구분 및 관리된다.

 

부모가 자식을 만들고, 자식이 또 자식을 만드는 트리 구조

 

Option

- 부모 프로세스와 자식 프로세스는 자원을

  ⓐ 공유할 것인가?

  ⓑ 일부만 공유할 것인가,

  ⓒ 공유하지 않을 것인가?

 

- 부모 프로세스는

  ⓐ 자식과 같이(concurrently) 실행할 것인가?

  ⓑ 자식 실행이 끝났을 때만 실행할 것인가?

 

 - 부모와 자식은

  ⓐ 같은 메모리 내용을 가질 것인가?

  ⓑ 전혀 다른 내용을 메모리에 올려 실행할 것인가?

 

Process termination

exit(System call): 부모에서 호출해 자식 실행이 끝날 때까지 기다리려면 wait을 호출

wait을 호출하면 exit의 반환값을 전달할 수 있게 된다

exit 해서 종료되면 그 프로세스의 자원은 모두 release돼서 다른 프로세스에 할당할 수 있게 됨

 

abort: 부모가 자식 프로세스의 실행 종료시킴

부모 종료 시 그 부모가 생성한 자식까지 종료시키는 OS도 있음(Cascaded termination)

 

 

IPC(Inter-Process Communication)

프로세스 간에 데이터를 주고받는 방법.

 

Web server처럼 복잡한 프로그램의 경우 단일 프로세스로 문제를 해결할 수 없을 수 있다.

* 왜 다중 프로세스인가?

속도 상승

프로세스 간 정보 공유

기능 별로 프로세스를 나눠서 구현 ->  전체 SW가 modular하게 구현됨

 

IPC의 대표적인 경우가 Shared memory, Message passing

 

Shared Memory

$A$와 $B$가 공통으로 사용하는 메모리 영역을 정한 후 그 영역에 $A$가 값을 쓰고 $B$가 읽는다.

 

* Producer-Consumer problem

Producer 프로세스는 어떤 작업을 만들어 내고, Consumer 프로세스는 그 작업을 가져와 부가적인 작업을 수행한다.

-> 둘 사이에는 Queue(Buffer)가 존재해 Producer는 이 queue에 쓰고, Consumer는 queue에서 읽어와 후처리를 한다.

 

이 Buffer는 공유되어야 한다 -> 이 버퍼를 공유 메모리 영역에 저장한다.

이 buffer는 bounded 또는 unbounded로 구현될 수 있다.

  

Shared buffer는 두 포인터 $in$과 $out$을 갖는 원형 queue로 구성된다.

$in$은 버퍼 내에서 비어 있는 위치(다음 작업이 들어올 위치)를 가리키고,

$out$은 첫번째로 채워져 있는 위치(다음 빠질 작업의 위치)를 가리킨다.

각각 원형 queue에서 $front$와 $rear$의 역할을 한다고 보면 된다.

즉 버퍼가 비어 있으면 $in\,==\,out$이고 버퍼가 가득 차 있으면 $((in+1)%BUFFER\_SIZE)\,==\,out$이다.

따라서 최대 $BUFFER\_SIZE-1$개의 작업만 저장할 수 있다.

 

이 방식에서는 동기화(Synchronization) 문제가 존재한다

= Producer와 Consumer가 동시에(concurrently) Shared data를 write할 경우 문제가 발생한다(데이터가 '깨진다').

 

 

Message passing

프로세스 $A$와 $B$가 $M$이라는 데이터를 주고받는다고 하자.

A -(M)-> 커널 -(M)-> B

 

$send(msg)$

$receive(msg)$

이 때 $message size$는 고정일 수도, 가변적일 수도 있다.

 

Producer(이하 $P$)와 Consumer(이하 $C$)가 communicate 하려면 둘 사이의 link가 성립되어야 한다.

-> Implementation note follows as:

언제 link가 수립되는가?

여러 개의 $P(P_1,\; P_2,\; \cdots,\; P_n)$와 여러 개의 $Q(Q_1,\; Q_2,\;, \cdots,\; Q_k)$가 하나의 link를 공유할 수 있는가?

두 프로세스 사이에는 link가 몇 개까지 성립될 수 있는가?

한 번에 메시지를 얼만큼 보낼 수있는가?

메시지의 크기는 가변적으로 할 것인가, 고정으로 할 것인가?

link 하나로 주고받을 것인가(양방향), 받는 link와 주는 link를 별개로 한 것인가(단방향)?

 

데이터를 주고받는 방식에는 Direct communication과 Indirect communication 방식의 두 가지가 있다.

Direct communictaion

데이터를 주는/받는 프로세스를 명시한다.

$send(P, message)$: $P$에게 보낸다

$receive(Q, message)$: $Q$에게서 받는다.

-> API 호출 시 링크가 자동으로 수립된다.

링크는 정확히 두 프로세스로 연결된다

링크는 구현에 따라 양방향일 수도, 단방향일 수도 있다.

 

Indirect communication

Mailbox라는 중간 매개체를 통해 보낸다.

 

각 메일박스는 ID를 가지며 메일박스를 공유한 프로세스끼리만 데이터를 주고받는다.

-> 메일박스를 공유하면 링크가 수립된다.

 

여러 개의 프로세스가 동일한 메일박스를 공유하면 여러 개의 링크가 수립될 수 있으며

단방향으로 구현될 수도 있고 양방향으로 구현될 수도 있다.

 

- Opreation

ⓐ Create/Destroy mailbox

ⓑ send/receive through mailbox -> $send(MAILBOX, message),\; receive(MAILBOX, message)$

 

- Design choice

$P_1,\;P_2,\; P_3$가 메일박스 $M$을 공유하고 있다고 하자.

$P_1$이 보내는 메시지는 $P_2$가 받을까, $P_3$이 받을까? 아니면 둘 다 받을까?

-> 구현에 따라 달라짐

 

Synchronazation

- Blocking(Synchronous)

데이터를 보내는 프로세스는 받는 프로세스가 받을 때까지 기다린다.

받는 프로세스 역시 받을 때까지 기다린다.

 

- Non-blocking(Asynchronous)

데이터를 보내는 프로세스는 받는 프로세스가 데이터를 받지 않아도 동작을 끝내고

받는 프로세스 역시 데이터를 못 받아도 동작이 끝난다.

 

 

Buffering

메시지를 받는 프로세스가 받는 속도보다 메시지를 주는 속도가 빠르면 queue에 메시지가 저장된다.

-> Queue에 얼마나 저장할 것인가?

- Zero capacity

받는 프로세스가 받을 때까지 줄 수 없다 (Sender는 반드시 Receiver를 기다린다 - rendezvous)

 

- Bounded capacity (finite length))

Queue가 꽉 차있으면 받는 프로세스가 받을 때까지 줄 수 없다(Sender는 Queue가 꽉 차있으면 기다린다)

 

- Unbounded capacity(Infinite length)

그냥 준다(Sender가 기다리지 않는다)

 

* 기다린다 = blocked

 

 

Communicatios in Client-Server Systems

Socket

IP와 port으로 구분되는 통신의 endpoint.

 

직접 IP와 port를 이용해, 주는 소켓과 받는 소켓 간 링크를 수립한 후 Byte stream을 통해 데이터를 주고받는다.

 

소켓은 구조화되지 않은 바이트스트림만으로 통신하기 때문에 이런 원시적인 데이터를 구조화+해석하는 것은

클라이언트와 서버(각 소켓)의 몫이 된다. -> 비효율적

 

Remote Procedure call

함수 call처럼 데이터를 주고받는다

 

프로세스 $P$와 $Q$가 있다 하자.

$P$는 로컬에 있는 함수를 호출하듯이 $Q$를 호출하고, 원격지에 있는 함수가 호출돼서 해당하는 작업이 수행

중간에 proxy가 있어서 이 proxy가 네트워크를 통해 원격지에 있는 함수를 호출하게 된다.

 

이 클라이언트 쪽(Client-side stub)에서는 marshallling을 해야 한다.

$P$는 Unix에서 동작하고, $Q$는 Inix라는 운영체제에서 동작한다고 하자.

-> 둘의 Computer archiutecture가 다르다.

$P$는 Big-Endian 방식이면서 int형이 4바이트고 $Q$는 Little-Endian 방식이면서 64바이트라면

둘을 일치시켜야 한다.

이 일치시키는 작업이 marshalling이다.

 

서버쪽에도 이런 stub(Server-side stub)가 있다.

서버에는 서버에서 제공하는 어떤 함수들이 있고 그 함수들을 원격지 클라이언트 쪽에서 호출하게 되는 것이다.

그러면 서버에서 제공하는 함수에 어떤 것들이 있고 어떤 파라미터를 제공해야 되는지를 MIDL(Microsoft Interface Definition Language, XML같은 언어)을 통해 서술할 수 있다. 이 MIDL을 컴파일하면 스켈레톤 코드가 만들어진다.

 

 

Server는 MIDL을 이용해 어떤 함수의 formal prototype을 선언

 

Compiler는 prototype을 그 함수에 대한 skeleton code로 변환

-> Server는 함수의 body만 구현하면 ㅇㅋ

 

Client가 MIDL로 만들어진 걸 컴파일러로 호출하면 header file(어떤 함수를 어떻게 호출해야하는가)이 만들어짐

그에 맞게 호출만 하면 호출한 내용이 stub에 의해 필요한 data format으로 변환돼서 해당하는 server로 metadata를 주게 됨

 

Skeleton은 이 metadata를 서버에 맞게 변환해서 사용하게 됨

 

stub와 skeleton은 RPC를 제공하는 플랫폼에서 컴파일러가 만들어줌

-> 우리는 body만 채우면 ㅇㅋ

 

 

Pipes

Java에서의 stream이라 보면 됨

stream을 보내는 도구

 

- 양방향, 단방향 가능

- 반이중, 전이중 가능

  반이중(Half duplex: 한 순간에 한 방향 전송만 가능)

  전이중(Full duplex: 동시에 양방향 전송 가능)

네트워크 간 통신, 같은 machine 내 통신 둘 다 가능

 

 

- Ordinary pipes

두 프로세스가 데이터를 주고받기 위한 대표적인 방법

단방향: 주는 파이프, 받는 파이프 따로 사용

파이프를 생성한 프로세스가 종료되면 파이프도 존재하지 않게 됨

 

- Name pipes

Mailbox처럼 데이터를 주고받을 수 있게 해주는 매개체

Linux의 경우 file의 형태로 제공

 

 

 

Message passing vs. Pipes

Message passing: 이미 message format이 고정되어 있어서 그 format에 따라 message를 주고받음

Pipes: 비트 스트림을 주고 받는 쪽에서 원하는 대로 재구성

 

 

Summary

Process: 실행 중인 프로그램, 문맥은 PCB에 저장

Process states: 프로세스는 생성부터 소멸까지 이벤트에 의해 상태가 전이되며 실행된다

Context switch: 프로세스에서 다른 프로세스로 전환, 순수 overhead

Schduling: 프로세스 대기 - Job queue, Ready queue, Device queue

Short-term scheduler: 누구에게 CPU를 할당할 것인가

Long-term scheduler: 어느 job을 메모리에 올릴 것인가 - Process mix

Medium-term scheduler: Swapping - 어느 프로세스를 swap in/out 할 것인가

IPC: Message passing / Shared memory / Socket, RPC, Pipes

'강의노트 > 운영체제' 카테고리의 다른 글

[운영체제] 3주차: Review (1)  (0) 2021.03.22
[운영체제] 2주차 (3)  (0) 2021.03.14
[운영체제] 2주차 (1)  (0) 2021.03.12
[운영체제] 1주차 (3)  (0) 2021.03.08
[운영체제] 1주차 (2)  (0) 2021.03.07