티스토리 뷰

CS

운영체제 - 1

kingsubin 2021. 4. 18. 01:21

다룰 내용

  • 운영체제 구조
  • 스케쥴러
  • 프로세스 구조

01. 운영체제 큰 그림 - 1

  • 운영체제 역할
    • 시스템 자원 (System Resource) 관리자
      • 시스템 자원 = 컴퓨터 하드웨어
      • CPU, Memory
      • I/O Devices
      • 저장매체
    • 사용자와 컴퓨터간의 커뮤니케이션 지원
    • 컴퓨터 하드웨어와 응용 프로그램 제어

  • 운영체제 종류
    • Windows OS
    • Mac OS
    • UNIX -> LINUX

02. 운영체제 큰 그림 - 2

  • 응용 프로그램 ?
    • 프로그램 = 소프트웨어
    • 소프트웨어 = 운영체제, 응용 프로그램
    • 응용 프로그램 = Application
  • 운영체제와 응용 프로그램간의 관계
    • 운영체제는 응용 프로그램을 관리
      • 응용 프로그램 실행
      • 응용 프로그램간의 권한 관리
      • 응용 프로그램 사용자 관리
    • 응용 프로그램은 누구나 만들수있음
      • 무한 반복문
      • 프로그램 다운
      • 권한/사용자 관리
      • CPU 사용 관리

그렇기에 운영체제가 응용 프로그램 관리

  • 운영체제의 목표
    • 사용자가 사용하는 응용 프로르램이 효율적으로 적절하게 동작하도록 지원
    • 응용 프로그램이 요청하는 시스템 리소스를 효율적으로 분배

03. 운영체제 핵심 기술

  • 배치 처리 시스템 (batch processing system)
    • 1960년대 초반부
    • 여러 응용 프로그램을 등록 시키면 순차적으로 실행
    • 단점
      • 응답 시간이 오래 걸릴 수 있음. (먼저 실행한 프로그램이 시간을 많이 필요로 할 경우)
      • 실행 시간이 오래 걸릴 수 있음. (CPU 가 필요 없음에도 응용프로그램이 CPU를 점유할 수 있기 때문)
  • 시분할 시스템 (Time Sharing System)
    • 1960년대 후반부
    • 다중 사용자 지원, 컴퓨터 응답 시간을 최소화 하는 시스템
    • 핵심기술: 시간을 잘게 쪼개서, 여러 응용 프로그램을 실행
      • 컴퓨터 응답 시간 줄일 수 있음
      • 전체 응용 프로그램의 실행 시간도 줄일 수 있음
      • 사용자가 느낄때 여러 응용 프로그램이 동시에 실행 되는것 처럼 보인다.
  • 멀티 태스킹 (Multi Tasking)
    • 단일 CPU 에서 여러 응용 프로그램의 병렬 실행을 가능케 하는 시스템
    • 일반적으로 시분할 시스템 = 멀티 태스킹
  • 멀티 프로그래밍
    • 최대한 CPU 를 많이 활용하도록 하는 시스템

04. 운영체제 구조 - 1

  • 쉘 (Shell)
    • 사용자가 운영체제 기능과 서비스를 조작할 수 있도록 인터페이스를 제공하는 프로그램
    • CLI, GUI 환경 두 종류로 분류
  • 운영체제를 만든다면 ?
    • 운영체제 개발 (kernel)
    • 시스템 콜 개발
    • C API (library) 개발
    • Shell 프로그램 개발
    • 응용 프로그램 개발
  • 응용 프로그램이 운영체제 기능을 요청하기 위해서 운영체제는 시스템콜을 제공한다.
    • 시스템 콜: 운영체제 기능을 호출하는 함수
      • 보통 시스템 콜을 직접 사용하기 보다는 시스템 콜을 사용해서 만든 각 언어별 라이브러리를 사용한다.

05. 운영체제 구조 - 2

  • CPU Protection Rings
    • 사용자 모드 (user mode by applications)
    • 커널 모드 (kernel mode by OS): 특권 명령어 실행과 원하는 작업 수행을 위한 자원 접근을 가능케 하는 모드

  • 커널 모드에서만 실행 가능한 기능들이 있는데 커널 모드로 실행 하려면, 반드시 시스템 콜을 사용해야함
  • 시스템 콜은 운영체제 제공

06. 프로세스 스케쥴링 - 1

  • 배치 처리 시스템 (일괄처리, 배치처리, batch processing)
    • 실행 요청 순서에 따라 순차적으로 프로그램을 실행하는 방식 
  • 시분할 시스템
    • 다중 사용자 지원을 위해 컴퓨터 응답 시간을 최소화 하는 시스템
  • 멀티 태스킹
    • 단일 CPU 에서 여러 응용 프로그램이 동시에 실행 되는것 처럼 보이도록 하는 시스템
    • 실제로는 대략 10~20ms 단위로 실행 응용 프로그램이 바뀌면서 사용자에게는 동시에 실행되는 것처럼 보임
  • 멀티 프로세싱
    • 멀티태스킹의 경우는 단일 CPU, 멀티 프로세싱의 경우는 여러 CPU에 하나의 프로그램을 병렬로 실행해서 실행 속도를 극대화시키는 시스템

07. 프로세스 스케쥴링 - 2

  • 멀티 프로그래밍
    • 최대한 CPU를 많이 활용하도록 하는 시스템
      • 시간 대비 CPU 활용도 높이기
      • 응용 프로그램을 짧은 시간안에 실행 완료 시킬 수 있음

실제로는 시분할 시스템, 멀티 프로그래밍, 멀티 태스킹이 유사한 의미로 통용됨

  • 정리
    • 시분할 시스템: 다중 사용자 지원, 응답시간 최소화
    • 멀티 태스킹: 단일 CPU 에서 여러 응용 프로그램을 동시에 실행하는 것처럼 보이게 하는 시스템
    • 멀티 프로세싱: 여러 CPU에서 하나의 응용 프로그램을 병렬로 실행하게 해서, 실행 속도를 높이는 기법
    • 멀티 프로그래밍: 최대한 CPU를 일정 시간당 많이 활용하는 시스템

08. 스케쥴링 알고리즘 - 1

  • 프로세스 (process)
    • 메모리에 올려져서 실행중인 프로그램

응용 프로그램은 프로세스가 아니다.
응용 프로그램은 여러 개의 프로세스로 이루어질 수 있음

  • 누가 프로세스 실행을 관리 ? -> 스케쥴러
  • 스케쥴링 알고리즘의 목표
    • 시분할 시스템 ex) 프로세스 응답 시간을 가능한 짧게
    • 멀티 프로그래밍 ex) CPU 활용도 최대로 높혀서, 프로세스를 빨리 실행
  • 스케쥴링 알고리즘 종류
    • FIFO 스케쥴러
      • 가장 간단한 스케쥴러 (배치 처리 시스템)
      • FCFS (First Come First Served) 스케쥴러 라고도 함
    • SJF (Shortest Job First) 스케쥴러
      • 가장 프로세스 실행 시간이 짧은 프로세스부터 먼저 실행 시키는 알고리즘
    • 우선순위 기반 (Priority-Based) 스케쥴러
      • 정적 우선순위: 우선순위를 미리 지정
      • 동적 우선순위: 상황에따라 스케쥴러가 우선순위를 동적으로 변경
    • Round Robin 스케쥴러
      • 시분할 시스템 기반
      • 준비 큐에 있는 프로세스를 짧은 시간동안 번갈아 처리하고 다시 큐에 넣는 방식

RealTime OS (RTOS): 응용 프로그램 실시간 성능 보장을 목표로 하는 OS
정확하게 프로그램 시작, 완료 시간을 보장
Hardware RTOS, Software RTOS

General Purpose OS (GPOS)
프로세스 실행 시간에 민감하지않고 일반적인 목적으로 사용되는 OS ex) Windows, Linux

  • 프로세스 상태
    • running state: 현재 CPU 에서 실행 상태
    • ready state: CPU에서 실행 가능 상태 (대기)
    • block state: 특정 이벤트 발생 대기 (ex: 프린팅)

09. 스케쥴링 알고리즘 - 2

  • 선점형 스케쥴러 (Preemptive Scheduling)
    • 하나의 프로세스가 다른 프로세스 대신에 CPU를 차지할 수 있음
    • 프로세스 running 중에 스케쥴러가 이를 중단시키고 다른 프로세스로 교체 가능
  • 비선점형 스케쥴러 (Non-preemptive Scheduling)
    • 하나의 프로세스가 끝나지 않으면 다른 CPU를 사용할 수 없음
    • 프로세스가 자발적으로 block state 가 되거나 실행이 끝났을 때만, 다른 프로세스로 교체 가능

10. 인터럽트

  • 인터럽트: CPU가 프로그램을 실행하고 있을 때, 입출력 하드웨어 등의 장치에서 예외상황이 발생하여 처리가 필요할 경우 CPU 에 알려서 처리하는 기술
  • 왜 필요한가 ?
    • 선점형 스케쥴러 구현
      • 프로세스 running 중 스케쥴러가 이를 중단시키고, 다른 프로세스로 교체하기 위해, 현재 프로세스를 중단시킴
      • 그러려면 스케쥴러가 작동해서 현 프로세스를 중지시켜야함
    • IO Device와의 커뮤니케이션
      • 저장매체에서 데이터 처리 완료시 프로세스를 깨워야함 (block state -> ready state)
    • 예외 상황 핸들링
      • CPU가 프로그램 실행하고 있을때, 예외 상황이 발생할 경우 CPU가 처리할 수 있도록 알려줘야 함

인터럽트는 일종의 이벤트로 불림
이벤트에 맞게 운영체제가 처리

  • 주요 인터럽트 (Interrupt)
    • 내부 인터럽트 (Software Interrupt)
      • 0으로 나누는 코드 (Divide-by-Zero)
      • 사용자 모드에서 허용되지 않은 명령 또는 공간 접근시
      • 계산결과 Overflow, Underflow
    • 외부 인터럽트 (Hardware Interrupt)
      • 주로 하드웨어 발생 이벤트
      • 전원이상, 기계 문제,
      • 입출력 인터럽트 (IO Interrupt)
      • 타이머 인터럽트 (Timer Interrupt)
        • 선점형 스케쥴러를 위해 필요
        • 하드웨어로부터 일정 시간마다 타이머 인터럽트를 운영체제에 알려줌
  • 시스템콜 인터럽트
    • 시스템콜을 싱행하기 위해서는 강제로 코드에 인터럽트 명령을 넣어 CPU에게 실행 시킨다.
    • 시스템콜 실제 코드
      • eax 레지스터에 시스템 콜 번호
      • ebx 레지스터에 해당하는 인자값
      • 소프트웨어 인터럽트 명령 호출하면서 0x80값 넘겨주기
  • 인터럽트와 IDT
    • 인터럽트는 미리 정의되어 각각 번호와 실행 코드를 가리키는 주소가 기록되어 있음
      • 어디 ? IDT (Interrupt Descriptor Table)
      • 언제 ? 컴퓨터 부팅시 운영체제가 기록
      • 어떤코드 ? 운영체제 내부 코드
    • ex) 리눅스
      • 0~31: 예외상황 인터럽트
      • 32~47: 하드웨어 인터럽트
      • 128: 시스템 콜

11. 프로세스 구조

  • 프로세스 (process)의 일반적인 구성
    • text(CODE)
    • data: 변수/초기화된 데이터
      • BSS: 초기화되지 않은 데이터
      • DATA: 초기화된 데이터
    • stack: 임시 데이터 (함수호출, 로컬변수 등)
    • heap: 코드에서 동적으로 만들어지는 데이터

12. 프로세스 구조와 컨텍스트 스위칭

  • PCB (Process Control Block, Process Context Block)
    • PC, SP 를 저장하는 공간
      • Process ID
      • Register 값 (PC, CP 등)
      • Scheduling Info (Process State)
      • Memory Info (메모리 사이즈 limit)
      • … 이 저장되어있음

ex) 리눅스에서의 PCB 예시

  • Context Switching: CPU에 실행할 프로세스를 교체하는 기술
    1. 실행 중지할 프로세스 정보를 해당 프로세스의 PCB 에 업데이트해서 메인 메모리에 저장
    2. 다음 실행할 프로세스 정보를 메인 메모리에 있는 해당 PCB 정보 (PC, SP) 를 CPU 의 레지스터에 넣고 실행

디스패치 (dispatch): ready 상태의 프로세스를 running 상태로 바꾸는 것

컨텍스트 스위칭은 매우 빈번하게 굉장히 짧은 시간 단위로 일어나기에 이 작업이 오래걸리면 안되기에 최대한 짧게 만들려고 노력한다.
그래서 리눅스의 경우 이식성이 떨어지더라도 어셈블리어로 작성한다.

  • 컴파일러
    • 초기 컴퓨터 프로그램들은 어셈블리어로 작성
      • 서로 다른 CPU 아키텍쳐가 등장할 때마다 매번 똑같은 프로그램 작성
      • 어셈블리어는 작성 속도가 매우 떨어짐
    • 컴파일러 등장
      • CPU 아키텍쳐에 따라서는 컴파일러 프로그램만 만들면 됨, 기존코드 재작성 필요 없음
      • 그러나 어셈블리어로 작성한 코드보다는 속도가 떨어짐

13. 프로세스간 커뮤니케이션 (IPC)

  • 프로세스는 다른 프로세스의 공간에 접근 할 수 없다.
  • 서로의 공간을 쉽게 접근한다면 ? -> 데이터/코드가 바뀔수 있으니 위험하다.

프로세스간에 커뮤니케이션을 해야한다면 어떤식으로 할까 ?
프로세스간 통신 방법을 제공함.
IPC (InterProcess Communication)

  • 위험하다면서 왜 통신이 필요한가 ?
    • 성능을 높이기 위해 여러 프로세스를 만들어서 동시 실행
    • 이 때 프로세스간 상태 확인 및 데이터 송수신이 필요

Ex)

  • 예를들어 1 ~ 10,000 까지 더하기 라는 작업이 10초가 걸린다고 하고, CPU 코어가 10개면
  • fork() 함수로 프로세스를 10개로 만들어 CPU 코어가 각자 수행하라고 한다.
  • 이후에 각자 더한 값을 합하는 식으로하면 10초 걸릴일을 1~2초에 수행 가능
    • 근데 이때 각 프로세스가 더한 값을 수집해야하니까 프로세스간 통신이 필요
  • 웹서버를 예시로 들면 클라이언트 -> 웹서버로 요청을 보내는데 모든 사용자 요청을 하나로 처리하자면 오래 걸리니까 새로운 사용자 요청이 올 때마다, fork() 함수로 새로운 프로세스를 만들고, 각 사용자 요청에 대응하게 해준다.
  • 실제 프로세스: 리눅스 예
    • 프로세스간 공간은 완전히 분리되어 있다.

  • 0부터 3gb 은 user space이고 3~4 gb는 kernel space

  • Kernel Space 는 공유한다.
  • IPC 종류
  1. file을 사용한 커뮤니케이션: 간단히 다른 프로세스에 전달할 내용을 파일에 쓰고, 다른 프로세스가 해당 파일을 읽으면 됨

-> 근데 실시간으로 직접 데이터 전달이 어려움
-> 왜냐면 해당 프로세스가 파일을 읽는데 계속 실시간으로 읽고만 있어야하니까
-> 게다가 파일 읽기같은거는 시간을 오래 잡아먹음

2. Message Queue
3. Shared Memory
4. Pipe
5. Signal
6. Semaphore
7. Socket
8. …


-> 2번 부터는 모두 커널 공간을 사용하는 것이 핵심 -> 왜냐면 커널공간은 공유하니까

 

 

  • Pipe (파이프)
    • 기본 파이프는 단방향 통신
    • fork()로 자식 프로세스 만들었을때, 부모와 자식간의 통신
  • Message Queue
    • key value 느낌으로 저장함
    • 양방향 통신 가능
    • 부모 자식간이 아니라도 가능
  • Shared Memory
    • 커널공간에 메모리 공간을 만들어두고, 해당 공간을 변수처럼 쓰는 방식
    • Message Queue 처럼 FIFO 가 아니라, 해당 메모리 주소를 마치 변수처럼 접근하는 방식
    • 공유 메모리 key 를 가지고 여러 프로세스가 접근 가능

다시 정리하는 흐름 

헷갈려서 다시 보고 흐름 정리했다.

 

예제

 

1. 프로그램을 작성하고 컴파일 하면 실행파일이 생긴다.

2. 실행파일을 실행한다. (일반사용자: 쉘 인터페이스를 사용하여 OS에 실행해달라고 요청)

 

3. (그림1) 실행파일은 이런 구조로 이루어져있다.

4. 먼저 코드들은 TEXT 영역에 들어간다.

 

5. (예제1) int fd 는 전역변수가 아닌 main 이라는 함수 안에 들어가있는 변수이므로 data 영역에 저장되지 않고 스택에서 진행되는 부분이다.

6. (그림2) 우선 실행파일 구조가 만들어지고 ready state 에 들어가있다.

7. 스케쥴링 알고리즘에 따라 어떻게 running state 로 바꿔줄지가 다르다.

(예시로 선점형 스케쥴러로 0.05초마다 컨텍스트 스위칭이 일어나는 스케쥴링 알고리즘이라고 한다.)

 

( ex)0.05초가 지나 timer 인터럽트가 발생했고 치겠다.)

8. 사용자 모드를 커널 모드로 바꿔준다.

9. IDT (Interrupt Descriptor Table) 에서 timer 인터럽트 번호에 해당하는 주소를 찾아서 커널 함수를 실행한다.

 

10. ready state 에 있는 프로세스가 running state 로 바뀐다. (컨텍스트 스위칭)

( ex) 현재 실행중인 프로세스를 프로세스1, 바꿀 프로세스를 프로세스2 라고 한다.)

11. 프로세스1 의 정보를 PCB 에 담아 메인 메모리에 저장한다. (대표적으로 PC, SP 가 있다) -> ready state로 변경

12. 프로세스2 의 정보를 담고있는 PCB 를 가져와서 실행한다.

 

13. 이제 실행한다치면 메인 리턴부터 스택에 담긴다.

14. 예제의 시작부분을 보면 open() 이라는 함수가있다. 

15. open 은 헤더 파일에 unistd.h 라는 라이브러리에서 시스템콜을 사용할 수 있게 제공해준다.

16. 안에 들여다보면 결과적으로 (그림3) 의 구조로 되어있다.

17. open() -> 시스템 콜인데 이걸 처리하기위해 이러한 구조로 되어있음.

18. 저 코드에서 eax: 시스템콜 번호, ebx: 시스템콜 인자, int: CPU가 제공하는 opcode (CPU 명령어, 0x80은 인터럽트 번호) 이다.

 

19. 시스템콜 open 함수를 실행하게 되면 그 프로세스는 waiting state 로 들어가게된다. (저장매체 갓다오는건 오래걸림)

20. 그 동안 ready state에 있는 다른 프로세스를 running 할 수 있다.

21. 다 처리가 되었다고 인터럽트가 발생해서 알려주면 waiting 에 있던 프로세스를 다시 ready 로 바꿔준다.

22. 이렇게 반복하다가 코드가 끝나면 running 에서 terminated 로 들어가서 끝나게된다.

 

(그림4) 를 보면 저장매체를 처리하는건 레지스터를 처리하는것과는 엄청난 시간차이가 있다.

IO 관련 처리는 수많은 인터럽트와 시스템콜, 스케쥴러, 하드웨어 등 많은것이 필요함.

-> IO 처리를 최소화 하자. 빈번한 IO 처리는 엄청난 시간을 필요로 한다.

 

 

 

 

 

그림1
그림2

 

그림3

 

그림4

 

 


※ 출처

패스트캠퍼스 컴퓨터 공학 강의

'CS' 카테고리의 다른 글

시스템 프로그래밍 - 쉘, 쉘스크립트  (0) 2021.05.09
운영체제 - 2  (0) 2021.04.24
리눅스 중요 명령어  (0) 2021.01.16
HTTP 8. 캐시와 조건부 요청  (0) 2021.01.08
HTTP 7. HTTP 일반 헤더  (0) 2021.01.07