Loading [MathJax]/jax/output/CommonHTML/jax.js
본문 바로가기

[운영체제] 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를 할당해준다.

위 그림이 그 과정.

 

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

 

P0의 정보를 P0의 PCB(PCB0)에 저장한다.

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

P1 실행

④ 현재 P1의 상태를 PCB1에 저장한다.

PCB0의 모든 정보를 읽어온다.

P0을 실행한다.

 

이런 작업을 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를 PCBA에 저장하고,

PCBB에 있던 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

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

 

* Producer-Consumer problem

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

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

 

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

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

  

Shared buffer는 두 포인터 inout을 갖는 원형 queue로 구성된다.

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

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

각각 원형 queue에서 frontrear의 역할을 한다고 보면 된다.

즉 버퍼가 비어 있으면 in==out이고 버퍼가 가득 차 있으면 ((in+1)이다.

따라서 최대 BUFFER_SIZE1개의 작업만 저장할 수 있다.

 

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

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

 

 

Message passing

프로세스 ABM이라는 데이터를 주고받는다고 하자.

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

 

send(msg)

receive(msg)

이 때 messagesize는 고정일 수도, 가변적일 수도 있다.

 

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

-> Implementation note follows as:

언제 link가 수립되는가?

여러 개의 P(P1,P2,,Pn)와 여러 개의 Q(Q1,Q2,,,Qk)가 하나의 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

P1,P2,P3가 메일박스 M을 공유하고 있다고 하자.

P1이 보내는 메시지는 P2가 받을까, P3이 받을까? 아니면 둘 다 받을까?

-> 구현에 따라 달라짐

 

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처럼 데이터를 주고받는다

 

프로세스 PQ가 있다 하자.

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