9 분 소요

1) 운영체제란 무엇인가

: Operating System. OS. (윈도우, UNIX 계열, 리눅스, MacOS 등…)
사용자의 하드웨어, 시스템 리소스를 제어하고 프로그램에 대한 일반적인 서비스를 지원하는 시스템 소프트웨어.

  • 더 정확하게는 커널(kernel)이 OS이지만, 일반적으로는 커널에 여러가지가 추가된 상태를 통칭함.

  • Operating_system_placement_kor

    *안드로이드는 OS? - 안드로이드는 리눅스 커널 위에 라이브러리와 안드로이드 응용프로그램이 올라간다. 즉, 정확하게는 OS가 아니다.

- 쉘

: 사용자가 운영체제 기능과 서비스를 조작할 수 있도록 인터페이스를 제공하는 프로그램. CLI(Command Line Interface)와 GUI(Graphical User Interface) 환경 두 종류로 분류된다.

bash-start<- 리눅스의 bash 쉘

- 시스템 콜

: 운영체제가 각 기능을 사용할 수 있도록 하는 명령 또는 함수. 즉, 사용자는 쉘을 통해 시스템 콜을 호출하여 운영체제를 제어한다. 시스템 콜은 OS와 같은 언어로 소통.

*Java와 시스템콜? - Java는 JDK를 설치하면 java언어 -> JDK -> 해당 OS에 적합한 시스템 콜을 호출해준다.
그래서 OS마다 각 OS에 맞는 시스템 콜을 컨트롤하기 위해 응용프로그램 설치파일이 다름.

- API (Application Programming Interface)

: 함수 또는 라이브러리라고 이해하면 됨. 컴퓨터나 컴퓨터 프로그램 사이의 연결.
API 내부에는 필요시 해당 운영체제의 시스템 콜을 호출하는 형태로 만들어짐. 프로그램

*정리

  • 유저는 Shell(CLI, GUI) 프로그램을 통해 응용프로그램 등을 작동함.
  • 응용프로그램은 API를 통해 시스템 콜을 호출함.
  • 시스템 콜은 커널을 동작함.
  • 커널은 컴퓨터를 직접 제어함.
    => 커널과 시스템 콜은 같은 언어로 소통하지만, 시스템 콜을 호출하는 API는 다른 언어일 수 있음.

2) 사용자 모드와 커널 모드

: 파일 삭제, 수정 등의 중요한 작업은 API가 직접 하지 못하도록 모드를 나누어 놓은 것. 시스템에 중요한 작업은 커널 모드로 작업을 하도록 권한을 설정해놓은 것.

- CPU Protection Ring

: 각 명령마다 레벨(권한)이 있어 해당 레벨을 체크하여 실행을 하게 함.

1200px-Priv_rings.svg

  • 시스템 콜은 커널 모드로 실행.
  • 커널 모드와 사용자 모드는 작업 내에도 수시로 변환이 일어남.

- 운영체제의 역할

1) 시스템 자원(System Resource) 관리자: 시스템 콜을 통해서 관리

  • CPU(각 프로그램들이 얼마나 CPU를 할당하여 사용할지 등)
  • Memory(각 프로그램이 어느 주소에 저장되고 어느정도를 할당하여 사용할지 등)
  • I/O Devices(표시 자체)
  • SSD, HDD(어디에 어떻게 저장할지 등)
    2) 사용자와 컴퓨터 간 커뮤니케이션 지원: 쉘을 통해 인터페이스 제공 3) 응용 프로그램 제어: 사용자 모드 및 커널 모드

3) 프로세스(process)

: 메모리에 올려져서 실행 중인 프로그램을 통칭해서 이야기함. (응용 프로그램을 이야기하는 것이 아님. 응용 프로그램은 여러 프로세스로 구성이 될 수 있음)
프로세스를 어떻게 관리하고 처리하는 지가 CPU의 성능과 직결됨.

- 프로세스 스케쥴링

1. 배치 처리 시스템

: 여러 프로그램을 순차적으로 실행시키는 것. FIFO. 1이 끝나면 2가 시작되도록. 1이 끝날때까지 유저가 기다렸다가 2를 작동시켜야 하는 단점이 있음. (현재는 사용하지 않음)

2. 시분할 시스템

: 다중 사용자 지원을 위해 컴퓨터 응답을 최소화 하는 시스템. 시간을 매우 잘게 쪼개어 컴퓨터 응답 시간을 최소화 하는 시스템.

3. 멀티 태스킹

: 단일 CPU에서 여러 응용 프로그램이 동시에 실행되는 것처럼 보이도록 하는 시스템. 시간을 쪼개어 실행하는 응용 프로그램이 바뀜.

** 시분할 시스템 vs 멀티 태스킹?* - 동작하는 알고리즘은 비슷하다고 보임. 그러나 추구하는 목표가 다름. 시분할 시스템은 응답 시간을 최소화, 멀티 태스킹은 여러 프로그램이 동시에 실행되는 것처럼 보이도록.

4. 멀티 프로그래밍

: CPU를 최대한 많이 활용하도록 하는 시스템. 프로그램이 대기하는 기간(ex, 파일을 읽어 오는 시간)을 활용하는 것.

5. 멀티 프로세싱

: 여러 CPU에서 하나의 응용 프로그램을 병렬로 실행해서 실행 속도를 높이는 기법.

- 프로세스 스케쥴링 알고리즘

1. FIFO

: 가장 간단한 스케쥴러. 큐에 들어온 순서대로 처리

2. SJF (최단 작업 우선)

: 실행 시간이 가장 짧은 프로세스부터 먼저 실행
그러나 일반적으로는 프로세스가 언제 끝날지 모르는 경우가 많음. 언제 끝날지 예측이 가능한 프로세스일때는 고려해볼만함.

*RTOS 와 GPOS?
RTOS - RealTime OS - 응용 프로그램 실시간 성능 보장을 목표로 하는 OS, 정확하게 프로그램이 시작, 완료 시간을 보장하기 때문인데, 공정이 오차 없이 정확한 경우 사용할 수 있음.
GPOS - General Purpose OS - 프로세스 실행시간에 민감하지 않고 일반적인 목적으로 사용되는 OS. Windew, Linux…

3. 우선순위 기반 스케쥴러

  • 정적 우선순위: 프로세스마다 우선순위가 미리 지정되어 있음
  • 동적 우선순위: 상황에 따라 우선순위를 동적으로 변경

4. Round Robin 스케쥴러

: 일정 시간 작업 후 남은 작업을 다시 큐에 넣어 선점하는 스케쥴러.

9917AA435C42D5D728

5. 프로세스 상태 기반 스케쥴러

: 작업의 현재 상태에 기반하여 작업을 처리하는 스케쥴러

image

  • ready: 현재 CPU에서 실행가능한 상태
  • running: CPU에서 실행 중
  • blocked: 특정 이벤트 발생 대기 상태(파일을 읽어 온다, 프린트가 다 되었다 등)

- 프로세스 구조

process-memory

  • Text: 코드 공간
  • Data(+BSS): 변수, 초기화된 데이터 공간
  • Stack: 임시 데이터(메서드 호출, 지역 변수 등)
  • Heap: 코드에서 동적으로 만들어지는 데이터(객체, 인스턴스 등)
  • Text와 Data는 컴파일 시 크기가 결정됨.
  • Heap과 Stack은 코드가 실행되면 코드의 내용에 따라 실행중에 메모리가 동적으로 할당됨.

- PC(Program Counter)와 SP(Stack Pointer)

: 다음 실행할 코드 주소(PC)와 스택 최상단 주소(SP)를 활용하여 코드를 읽어내려가며 프로그램을 동작시킴.

KakaoTalk_20220619_235808629

*Java의 Garbage Collection
JVM이 메모리를 관리해줌. (더이상 해당 객체를 가리키는(참조하는) 것이 없으면 메모리에서 내리는 역할을 함) 이를 통해 불필요한 객체가 차지하는 힙 공간을 확보하게 됨.
힙공간이 부족하게 되면 객체 생성이 불가능해지게 되며 프로그램이 동작할 수 없음.

- 컨텍스트 스위칭

: 문맥 교환. 즉, CPU에 실행할 프로세스를 교체하는 기술. 위에서 공부한 PC와 SP를 바꿔주면서 진행함. (바꿔줄 프로세스의 이전 PC와 SP 상태를 알고 있으면 이후에 작업이 바로 가능해짐!!) -> 이걸 어디에 기억하지?

- PCB(Process Control Block)

: 프로세서의 고유번호(ID), Register(PC, SP 등) 등을 저장하고 있음. (ex, 1번 프로세스는 여기서 이 작업을 하고 있었고, 2번 프로세스는 여기서 저 작업을 하고 있었다. 라는 정보를 캡쳐/구조화 해서 저장)

- 프로세스 커뮤니케이션

: 각 프로세스는 직접적으로 통신이 불가능함. (파일을 사용하여 전달하면 너무 느림…) 그러나 상태 및 데이터의 송수신이 필요함. (멀티 프로세싱 등)

IPC(InterProcess Communication): 프로세스간 통신 방법

  • 리눅스) 실제 프로세스는 커널 공간을 공유한다. => 이 부분을 활용해 통신하자!
    *(프로세스는 초기 프로세스를 제외하고는 클론(복사)를 통해 생성되며, 이 때 기존에 사용하던 데이터들을 최대한 활용하면 효율이 좋기 때문에 특히 커널공간은 거의 수정 없이 사용이 가능하다)
  • 메시지큐, 공유메모리, 파이프, 시그널, 세마포어, 소켓 등의 기법을 사용.

4) 스레드(Thread)

: 프로세스 내에서 실행되는 흐름의 단위. Light Weight Process라고도 말함. 멀티 프로세스와 멀티 스레드 모두 성능 개선을 위한 목표를 가지고 있음.

- 프로세스와의 차이

  • 프로세스는 각 프로세스간의 데이터 접근이 불가해서 커널공간을 통한 IPC기법으로 데이터 교환을 해야 했음.
  • 스레드는 프로세스 안에 있으므로, 프로세스의 데이터에 서로서로 접근이 가능함.
  • 하나의 프로세스 안에 여러개의 스레드 생성이 가능하며, 동시에 실행 가능함.
  • 스레드는 함수로 구현되기 때문에 각 스레드의 Stack 영역을 사용하여 작동함!!!
    프로세스내의 Code영역, Data영역, Heap영역은 부모 프로세스와 공유함.(주소 영역 공유)
    thread

- 스레드의 단점

  • 스레드 중 한 스레드만 문제가 있어도 전체 프로세스가 영향을 받음.
    (멀티 프로세스는 한 프로세스가 문제가 있어도 다른 프로세스는 모두 작업을 완료할 수 있음)
  • 스레드를 많이 생성하면 Context Switching이 많이 일어나 오히려 성능이 저하될 수 있음.
  • 동기화 이슈로 비정상적인 동작이 일어날 수 있음. => 동기화 코드를 적절히 추가해 문제 해결 가능.

*동기화(Synchronization)?

: 작업들 사이에 실행 시기를 맞추는 것.
ex1) 어떤 스레드 중 하나가 프로세스 끝에 가면 프로세스가 종료되어버릴 수 있음.
=> 마지막에 .join(); : 한 스레드가 먼저 오더라도 다른 스레드가 올 때까지 기다리게 하는 메서드로 컨트롤.
ex2) 어떤 프로세스가 1을 1000만번 더하는 중이라고 가정하면, 스레드가 나누어 작업하던 도중 (변수 읽기 -> 더하기 -> 할당하기) 중간에 스위칭이 되어 버리면 더한 값이 할당되기 전에 다른 스레드가 변수를 읽어 값이 누락되는 경우가 발생할 수 있음.
=> 상호 배제(Mutual exclusion)하여 해결: 공유 변수를 갱신하는 동안은 다른 스레드가 접근하지 못하도록 막음.

// 언어마다 해당이슈를 지원하는 메서드(함수)를 제공함.
lock.acquire() // 들어가서 문 잠그기
for i in range(100000) :
	g_count += 1
lock.release() // 나오면서 잠금 풀기

- Mutex / Semaphore

  • Mutex(뮤텍스) - 임계구역에 하나의 스레드만 접근!
  • Semaphore(세마포어) - 임계구역에 스레드 개수 제어!

- 스레드의 오류상태

  • 교착상태(Dead Lock) - 무한 대기상태. 스레드가 서로의 작업이 끝나길 기다리고 있어 더이상 진행이 안되고 있음. (이는 프로세스에서도 일어날 수 있음)
  • 기아상태(Starvation) - 특정 프로세스의 우선순위가 낮아서 자원을 계속 할당받지 못하는 상태에 놓인 것.

5) 가상 메모리 (Virtual Memory System)

: 어떤 이유로 메모리가 더 필요한 경우를 해결하기 위한 시스템. 물리적인 실제 메모리보다 많아 보이게 하는 기술.
프로세스가 진행될 때, 메모리에 모두 올라가 있을 필요가 없구나! 실제 사용하는 메모리는 작다는 점을 착안해 고안된 기술.

- 기본 아이디어

: 프로세스는 가상 주소를 사용하고, 실제 해당 주소에서 데이터를 읽거나 쓸 때만 물리 주소로 바꿔주면 된다.

  • virtual address(가상 주소) : 프로세스가 참조하는 주소
  • physical address(물리 주소) : 실제 메모리 주소

- MMU(Memory Management Unit)

: 가상 주소를 물리 주소로 바꿔주는 하드웨어!
동작이 매우 빈번하게 일어나기 때문에 소프트웨어가 아닌 하드웨어를 통해 성능을 확보함.

- 페이징 시스템

: 동일한 크기로 가상 주소와 물리 주소를 관리하는 시스템. (다 올리지 않고, 실제 메모리에 얼만큼씩 올릴거야?)
리눅스에서는 4KB로 페이징을 함. (이 조각 하나를 page 혹은 paging이라고 함)
*bit시스템? - 이 주소의 단위를 64bit로 할것인지, 32bit로 할 것인지 / 만약 32bit라면 앞의 20개는 주소, 뒤의 12개는 변위를 나타냄.

- 다중 페이징

: 리눅스의 경우, 4GB의 프로세스를 4KB로 모두 쪼개어 페이지를 관리하는 것이 비효율적임. 필요한 페이지만 테이블을 만들어서 관리하는 시스펨이 다중 페이징 시스템. 이때, 페이지 번호를 나타내는 bit를 더 쪼개어 단계를 나누어, 저장할 수 있는 주소의 수를 극대화함.
paging

- 페이징 시스템을 통한 CPU의 메모리 접근 흐름

1) 작업을 해야지! -> 프로세스 접근 2) 데이터가 어디있지? -> MMU 접근 3) 데이터 주소가 필요해 -> TLB* 먼저 접근 4) Page Table* 접근 1) 메모리에 올라가있던 적 있어? -> valid - invalid bit 체크하여 1) 있으면? -> 바로 물리주소 찾아가서 물리주소 + 변위값을 확인하여 최종 주소를 찾아가서 데이터 사용
2) 없으면? -> 페이지 폴트
인터럽트 발생 -> 시스템 콜 호출하여 메모리에 올림 -> CPU에 보고 -> 1번부터 다시 시작

*TLB? - (Translation Lookaside Buffer), 페이지 정보 캐쉬. 최근에 불러온 것들에 대한 주소 값을 가지고 있음. 캐쉬 메모리라 Page Table보다 가까워 속도 향상을 시킬 수 있음. 여기 있으면 Page Table 갈 필요 없이 바로 메모리 물리 주소로 갈 수 있음.

*Page Table? - 가상주소 - 물리주소 - 메모리 할당 여부를 가지고 있는 표. 프로세스 생성 시 페이지 테이블 정보가 생성되며, CR3 레지스터에 저장되어 있다. (메모리에 위치, MMU가 오려면 200 cycle 소요)

*변위값? - 시작점으로부터 얼마나 떨어져있는지.
페이지 테이블은 각 페이지의 1번 주소만 가지고 있으며, 페이지 내의 2, 3…번째 데이터 주소는 변위값을 더해서 사용.

*페이지폴트? - Page Table에 필요한 데이터 주소가 invalid! 즉, 메모리에 올라가 있지 않을때 발생하는 인터럽트.
운영체제에 해당 페이지를 물리 메모리에 올리라는 시스템 콜 호출
=> 페이지 폴트가 안나게 하려면? 메모리에 올려놓아야 함.
=> 메모리에 올려 놓으면? 공간을 많이 차지하고 실행되게 전에 사전 작업을 해야해서 시간이 오래걸림.
즉, trade-off 관계. => 페이지 교체 정책을 통해 상쇄!

- 페이지 교체 정책

: 물리 메모리가 다 차있을 때, 어떤 페이지를 저장 매체로 내리고 어떤 페이지를 메모리에 올릴 것인가?

  • FIFO
  • OPT(Optimal Replace Algorithm) - 앞으로 가장 오랫동안 사용하지 않을 페이지를 내리자! (쉽지 않음)
  • LRU(Lease Recently Used) - 가장 오래전에 사용된 페이지를 내리자!
  • LFU(Least Frequently Used) - 가장 적게 사용된 페이지를 내리자!
  • NUR(Not Used Recently) - 최근에 사용하지 않은 페이지부터 내리자!(LRU과 비슷하지만, 각 페이지마다 참조비트R, 수정비트M을 두어 빈도를 체크함 / (R, M) -> (0, 0), (0, 1), (1, 0), (1, 1) 순으로 교체!)

- 스레싱(Thrashing)

: 페이지 폴트가 과도하게 일어나 메모리에 올리고, 내리고를 계속 반복하다가 실제로는 아무작업도 못하는 경우. 물리적이기 때문에 1)메모리를 늘려주거나 2) 프로세스 개수를 줄여서 해결하는 방법 밖에 없음.


6) 파일 시스템

: 비트로 데이터를 모두 관리하기 어렵기 때문에 블록단위로 관리하기로 함(보통 4KB). 사용자는 파일 단위로 관리하지만, 각 파일은 블록 단위로 다시 쪼개져 관리된다.
파일은 가능한 연속적인 공간에 저장하는 것이 효율적이나, 사이즈가 변경되거나 삭제 후 해당 공간에 다른 데이터를 다시 저장할 때 공간적인 이슈가 발생함.

  • 블록 체인: 링크드리스트로 블록단위를 연결함. => 링크르리스트의 장-단점을 따름.
  • 인덱스 블록 기법: 각 블록에 대한 위치 정보를 기록하여 바로 접근 가능. => 주소를 기록할 공간 필요.

*Windows와 리눅스의 파일 시스템?

  • 윈도우: FAT, FAT32, NTFS.. 블록 위치를 FAT라는 자료 구조에 기록함.
  • 리눅스: ext2, ext3, ext4.. 인덱스 블록 기법인 inode 방식 사용.

- inode 방식

: 리눅스 운영체제의 기본 파일 시스템.

  • 수퍼 블록: 파일 시스템 정보 기록
  • 아이노드 블럭: 파일 상세 정보 기록
  • 데이터 블록: 실제 데이터 기록

inode


7) 가상 머신

: 하나의 하드웨어에서 개별 컴퓨터처럼 동작하도록 하는 프로그램.

  • Type 1: 하이퍼바이저(또는 버추얼 머신 모니터) 위에 가상 머신을 두어 개별 OS 및 App이 동작하게 하는 타입.
    대표적인 Type 1의 하이퍼바이저: Xen, KVM(AWS에서도 사용)
  • Type 2: 호스트 OS 위에 하이퍼바이저(또는 버추얼 머신 모니터) 를 설치하여 OS 및 App이 동작하게 하는 타입.
    대표적인 Type 2의 하이퍼바이저: VMWare, VirtualBox

마지막 수정일시: 2022-06-26 02:03

카테고리:

업데이트:

댓글남기기