OS - (12) Virtual Machine / Linux / Cloud

정선용·2022년 5월 21일
0

Operating System

목록 보기
12/12

Virtual Machine

  • Virtual Machine?
    가상머신이란, 컴퓨터 자원(hw - cpu,mem,disk,network..)이 다수의 실행환경을 제공하도록 추상화하는 것. 각 개별적인 실행 환경이 독립된 컴퓨터를 사용할 수 있도록 환경을 제공하는 것이다.
    쉽게 말해 컴퓨터(서버) 한 대로 여러 대를 쓰는 것 처럼 하기 위함.


위 그림처럼 컴퓨터 자원을 다수의 독립적인 실행환경으로 활용한다는 의미는,
hw뿐만아니라 hw를 이용하기위한 동일 인터페이스(시스템 호출,파일시스템 등)가 제공됨. : user mode, kernel mode가 각 가상머신에서 제공되어야한다.
-> 가상 기계 사용자모드에서 실행중인 프로그램이 시스템 호출 시 실제 hw내 virtual machine monitor(하이퍼바이저)로 전달되고, 제어를 얻은 vmm(하이퍼바이저)이 vm의 레지스터 내용과 프로그램 카운터를 변경해준다.

물리 하드웨어를 Host ,가상환경의 운영체제들을 Guest 운영체제라고 함.

  • ProcessVM, SystemVM

    • Process VM : 플랫폼에 독립적인 환경에서 프로그램 실행위함. (ex - JVM)
      host 운영체제 내 단일 프로세스를 지원하는 일반 어플리케이션으로 실행. 프로세스 시작 시 생성되며 끝나면 소멸된다.(Runtime방식 VM)

    • 실제 HW(기계)를 대체하기위해 제공하며 운영체제를 실행하기 위한 기능들을 제공한다. hw resouce는 물리적 호스트에 존재.

  • Process VM 구현 : 스택기반/레지스터기반
    가상 머신(VM : Virtual Machine)은 물리적인 CPU에 의해 처리되는 동작을 흉내낼 수 있어야 한다. 따라서 일반적으로 VM은 아래의 개념들을 구현(포함)해야 한다.

    • 소스 코드를 VM이 실행할 수 있는 바이트 코드로 변환

    • 명령어와 피연산자를 포함하는 데이터구조

    • 함수를 실행하기 위한 콜스택

    • 다음 실행할 명령어를 가리키는 IP(Instruction Pointer)

    • 가상 CPU

      • Fetch
        • IP가 가리키는 명령어를 가져온다
      • Decode
        • 가져온 명령어를 디코드(해석)한다.
      • Execution
        • 디코딩된 명령어를 수행한다
    • 구현은 스택기반 / 레지스터기반으로 이루어진다

      • 대다수 가상머신이 스택기반이며, 피연산자와 연산 후 결과를 스택에 저장.PUSH & POP연산. HW에 덜 의존적이다.
      • 레지스터기반은 피연산자가 CPU의 레지스터에 저장, PUSH&POP연산X, 명령어가 피연산자 위치인 레지스터 주소 기억해야하며 더 빠르다. 스택기반에서는 할 수 없는 연산결과 재활용이가능. 그러나 스택기반보다 명령어 길이가 길다(주소를명시해줘야하므로)
  • System VM 하이퍼바이저

  • VM 장점 / 한계

    • 장점 : 시스템 자원 보호(완전한 실행환경 격리), 단위 분리가능.(decoupling,관리용이성)
    • 한계 : 자원을 직접 공유할 수 없다
    • 해결책
      • 가상 디스크를 공유. 결과적으로 파일을 공유하게된다. sw로 구현됨
      • vm간 네트워크 구성. 네트워크를통해 정보를 주고받으며 sw로 구현.
  • VM에는 linux OS가 선호되어진다.

  • linux는 C/어셈블리 언어로 작성되어있는것이 대다수. C는 특정 HW에 비의존적이며 다른 기계 시스템에 Porting하는 것이 용이하다고 한다. OS자체도 HW에 적합하게 변형이 가능.
  • linux system은 거의 모든 프로그래밍언어를 제공(+ GNU) , 모든 시스템 소스가 개방되어있다. 커널이 공개되어있고 폭넓은 hw장치들을 지원하는 driver들이 존재.

Linux

Linux란 운영체제의 한 종류로, open source로 공개되어있으며 자유 소프트웨어라는 철학을 가지고있다.

  • 리눅스 구조

    리눅스는 기반 HW위에서 hw를 제어하는 kernel을 통해 시스템의 모든 자원을 관리, control하고, user가 사용하는 user interface, user application에서 사용자의 명령을 이 kernel이 이해할 수 있도록 해석하주는 Shell로 이루어져있다.
    응용프로그램 명령어(코드)->shell->kenrnel->HW로 flow가 흐른다.

  • 리눅스 특징
    리눅스는 안정성이 뛰어나고 보안성과 신뢰성, 성능이 높은 것이 특징이다. 또한 멀티유저(여러 사용자가 동시에 하나에 시스템에 접근가능)와, 멀티 태스키(여러 개의 작업을 동시에 실행하고 교대로 컴퓨터 자원을 사용할 수있는 기능)을 지원한다.
    가장 큰 장점으로는 오픈소스로서 커널 소스코드가 공개되어있으므로 여러 개발자들이 빠르게 발전을 지원하고 다양한 배포판이 존재, 풍부한 응용프로그램들을 제공하고있다. 리눅스는 특유의 오픈소스 문화가 있어서 무료로 공개하는 양질의 오픈소스 라이브러리들이 많다. (유용하게 잘 사용했으면 donation을 해주는것도 예의라고함. 개발자 특유의 유연한 문화가 이 오픈소스문화에서 나오지 않았을까 한다. )

Kernel Modules

  • Kernel Module
    모듈은 요청 시 커널에 load및 unload할 수 있는 코드조각이다. OS Structure중 '동적'으로 kernel안에 코드를 삽입,제거할 수 있는 module structure가 이 module을 의미.
    시스템을 재부팅 할 필요 없이 런타임에 커널기능이 확장되고 축소될 수 있다.
    example) device driver: kernel에 runtime에 적재되어 하드웨어에 access(I/O)할 수 있도록 하는 모듈.
    • vs monolithic
      리눅스는 본래 monolithic한 운영체제이나, 현대 linux에는 module방식이 도입되었다. monolithic이라면 device driver가 부팅 시 존재하지 않았다면 커널 이미지에 직접 새로운 기능을 추가하고, 커널을 재빌드해야했다. 새로운 기능이 있을 때 마다 커널을 다시 빌드하고 재부팅해야했다. -> 모듈을 이용해 컴파일 시간을 단축할 수 있고 런타임에 모듈을 적재,회수함으로써 유연한 구조를 가지게됨.(자원도 효율적으로 사용)
    • LKM : 로드가능한 커널모듈(loadable kernel module), 모듈은 lib/modules directory에서 .ko(kernel object, 커널개체) 확장자를 가진 파일로 나타낼 수 있다.
    • 주요명령어
      • lsmod : 현재 설치된 사용중 모듈 show
      • insmod : 모듈 삽입 명령어
      • rmmod : 모듈 제거 명령어
      • modinfo : 모듈 정보
      • 커널 모듈 만들고 컴파일 : 모듈 소스-> 커널소스트리로 이동 -> Makefile 생성-> make build -> .ko파일 생성.

Process

  • Process ?
    시스템에서 메모리에 적재되어 실행되고 있는 프로그램(코드 명령어의 집합체)
    리눅스에서는 프로세스 생성 목적에 따라 fork()와 execve()함수를 사용한다.
    fork()의경우 단일 프로그램 처리를 여러 프로세스로 나누어서 처리할 때 사용하고, PCB(process control block)을 생성한다.( 부모 프로세스와 동일, 부모가 사용하던 리소스를 자식 프로세스도 동일하게 사용하게된다. )
    execve()의 경우 부모와 다른 새로운 프로세스를 생성한다. 기존 프로세스를 별도의 프로세스로 덮어쓰는 방식으로 구현되기 때문에 프로세스 수는 차이가 없고, 실행할 프로그램 파일의 데이터 영역에 정보 및 메모리주소를 읽어 기존 프로세스 데이터에 덮어쓰게된다.
    두 가지 함수를 이용하여, 전혀 다른 새로운 프로세스를 생성할 때에는 fork함수를 수행한 후 자식프로세스에 대해 exec()함수를 실행한다.

Scheduling

리눅스 커널은 프로세스 스케줄러를 통해 multi process를 통작시킨다.
이 때 cpu는 하나의 프로세스만을 처리할 수 있지만, concurency를 위해 각 프로세스를 작업 단위로 잘게 쪼개어 동시에 처리하는 것 처럼 시분할 처리한다.
taskset -c 0 /sched <n> <total> <resol> : 경과시간동안 동작한 프로세스번호와 여러 프로세스 각 진행도를 프로세스별로 확인 가능하며, CPU가 동시에 여러 프로세스를 처리하지 않는다는 것을 확인 가능. 또 이 명령어 결과를 통해 리눅스에서 여러 프로세스는 RR(라운드로빈)방식으로 처리된다는 것 확인가능.

  • PS
    ps ax : 프로세스의 status확인 가능. (-R : 실행혹은 실행대기, -S or -D : 슬립, -Z : 좀비).
    일반적으로 프로세스가 생성되면 실행 대기 상태로 진입하고, 이벤트가 발생하기 전 까지는 슬립상태로 있는다. 이벤트가 발생하여 CPU를 실행할 수 있는 권한을 얻게 되면 실행상태로 변한하게되며 수행을 마무리했을 때에는 좀비상태로 돌입하게된다. -> process는 생성되어 종료될 때 까지 CPU를 계속 사용하는 것이 아니라 status를 변화하며 상태에 따라 cpu를 사용한다.

Memory

  • 메모리?
    linux kernel도 하나의 프로그램이다. 연산을 하고, 메모리를 사용한다.
    free명령어를 통해 리눅스 시스템의 메모리 용량과 사용중인 용량을 확인할 수 있다.
    • total : 시스템 전체 메모리
    • free : 이용하지 않는 메모리
    • buff/cache : 버퍼 캐시 or page cache가 사용하는 메모리.
    • available : 실질적으로 사용 가능한 메모리.
    • shared : 프로그램간 공유 가능한 자원
    • swap : 메모리에 OOM이 발생했을 경우 스와핑 가능 스왑영역 (OOM : out of memory)
      • out of memory : system 에서 어떤 동작을 수행함에 있어 필요한 메모리가 부족하거나 없는 상태.
      • OOM Killer : linux kernel에서 메모리 부족시 메모리를 확보하는 역할을 하는 process ( mm/oom_kill.c )
        시스템 구동 중 메모리가 부족하면 운영체제 내보 우선순위 알고리즘에 의해 프로세스를 죽인다. 리눅스 커널은 프로세스의 메모리 할당 시 남은 메모리가 없는 상황을 처리하기 위해 Out ot memory killer를 가지고있고, 모든 프로세스를 어떤 제약으로 점수를 매겨 init을 제외한 최고 점수 프로세스는 죽여 메모리를 확보한다. 그러므로 일반적으로 서버를 운영할 떄에는 서비스 데몬이 oom-killer에게 죽지 않도록 메모리 관리를 잘 해야한다 .
      • OOM 발생 원인 : kernel은 virtual memory를 이용한 메모리 할당을 하므로, 실제 available한 물리메모리보다 큰 size 메모리를 할당할 수 있다. -> overcommit (프로그램에서 당장 사용하는것이 아닌 실행단위(모듈)은 메모리를 나중에 할당하므로, 실제 사용가능 메모리를 넘는 process에도 load될 수 있다. -> overcommit된 메모리에 실제 뭔가 쓰여지기 시작하면 메모리가 모자라므로 out of memory 발생.메모리(RAM)이 부족하고, swap이 없다면 clean page를 버린다. clean page가 더이상 없다면 시스템에 가상메모리(ram+swap)이 부족하게되고 프로세스를 종료하게된다.
      • oom의 원인은 다양하다. 어려운문제이고 heap dump를 통해 원인을 파악해나가기도한다. 원인은 memory leak뿐만이 아닐 수 있다. 일반적으로 크게봤을 떄 프로그램에서는 program에서 메모리를 강하게 참조하고있기 때문이라고 발생한다고도 하며, static과같은 정적 메모리로 선언되어있다면 메모리에 지워지지 않고 계속 남으므로, 의도한것이 아닌 경우 메모리 lock으로 발전할 수 있다. 쓰레드생성에서는 OS의 자원 소진일 수도 있으며 이럴경우 자원량을 늘리거나 최적화해서사용해야한다.
  • 메모리 할당 과정과 가상메모리
    • 가상메모리가 없다면.
      프로세스가 생성될 때 메모리를 할당하고, 추가로 메모리 필요 시 시스템 콜을 통해 kernel에게 메모리 요청을 한다. 이 때 kerenl이 필요 사이즈만큼 free 영역에서 추출해 시작 주소값을 전달한다 하면, 메모리는 프로세스 생성 종료를 반복하며 비효율적으로 공간을 사용하게된다 -> 외부단편화
    • 가상메모리
      linux에서도 가상 메모리는 가상 주소 공간을 이용한다. -> 물리 주소공간의 연속성은 더이상 메모리 할당의 제한사항이 아니다.
      shell 환경에서 프로그램 메모리를 출력하게되면 받는 값들은 논리적 값=가상 주소가 되는 것이다.
      • 페이지 테이블
        이 가상 주소를 실제 물리 메모리 주소로 매핑한 테이블을 '페이지 테이블'이라고 한다. -> 모든 논리 주소가 physical(실제 물리)메모리에 매핑되어있지는 않고, 동적으로 매핑된다.
        이 떄 물리 메모리에 매핑되어있지 않은 virtual address에 접근하게되면 page fault 에러가 발생한다.
    • 가상메모리가 메모리를 할당받는방법
      C의 malloc, C++의 new와 같은 함수들이 systemcall mmap()함수를 호출하여 커널로부터 메모리를 할당받는다. Demand paging 방식으로, valid - invalid bit을 사용하여 물리메모리에 있는지 없는지를 구분하고, page fault가 발생하면 linux OS가 해당 page(논리 메모리, 고정크기 블록)를 스왑영역에서(적재되있지 않은 상태)에서 물리메모리와 매핑시켜준다. (Interrupt Service Routine을 거쳐서.. page table 업데이트.)
    • 가상메모리 단위
      가상메모리 단위는 page단위로 관리된다했고, 물리메모리는 프레임 단위로 관리된다(복습) -> 페이지와 프레임은 1:1매핑으로 동일 사이즈를 가지고, Linux 시스템에서는 page크기를 4kb(32bit)를 기본으로 한다. 4kb단위로 이 page와 frame을 매칭시켜서 할당해주는 것.
    • segmentation in linux
      External Fragmentation을 해결하기위해 물리적 메모리, 논리적 메모리를 분할하고 , 매칭하여 메모리공간을 비연속적으로 사용하는 기법으로 paging(고정크기블록으로 할당), segmentation(의미단위인 세그먼트로 할당)이있는데,
      리눅스(x86 cpu)에서는 segmentation을 제한적으로 사용한다.
      왜냐, linux는 multi architecture를 지원하는 kernel이므로 segmentation을 지원하지 않는 architecture에서는 이를 포팅하는 것이 힘들다(호환,확장성문제-> 리눅스의 철학은 이식성도 중요한 부분임. : machine independent하도록 노력) (포팅==운영체제 플랫폼을 다른 환경에서 돌아가도록 하는것.)
      paging이 더 범용적이기 떄문에 주로 paging방식을 사용한다. 이 때 segmentation을 paging기법을 동시에 사용하면 복잡해지며 segment를 사용한다면 모든 segment가 동일한 segment address를 사용하도록 해 , (모든 프로세스가 같은 segment를 사용하도록 설정) 메모리 관리를 쉽게한다.
      segmentation은 segment(의미)단위로 메모리 접근 control을 쉽게할 수 있다는 장점이 있었는데, linux는 우선 과거엔 segment방식을 사용하다가 고도화된 paging(pure paging)을 이용하는 것이고, 이 과정에서 segment단위로 하던 access control을 다 page table로 이식하였다고 한다. -> OS가 SW application적으로 어느 page가 code segment인지, data segment인지 region을 관리하지만, paged segment처럼 MMU가 segment주소를 참조해 테이블을 찾는 등 방식으로 복잡하게 찾지 않고, OS가 관리는 하지만 페이지에 접근해 주소 변환하는 단계에서는 paging만 한다. OS가 segmentation의 개념적인 부분을 어느정도 가지고 있다 정도로 이해하면 될 것 같다.
    • Swap
      리눅스에서도 사용해 저장장치를 메모리를 대신해 사용하게 되는 swapping이 발생한다. demad paging과 같이 메모리를 효율적으로 사용하기 위해 잘 사용하지 않을 것 같은 부분들은 주기적으로 swap out해 저장장치에 저장해놓고 프로세스 접근 시 page fault->swap in.
    • 캐시 메모리
      메모리를 담아두는 곳 : 저장장치(disk),메모리(ram) 캐시메모리, 레지스터가 있다. 명령어 수행 시 register에서 메모리로 데이터를 읽어 계산, 계산값을 메모리에 write하게된다.
      Cache는 캐시메모리에 메모리값을 저장해두어 cpu가 메모리까지 접근하지 않더라도 보다 빠르게 접근해 바로 읽을 수 있도록 하는 것.
      리눅스에서 캐시메모리와 유사하게 페이지 캐시 기능을 사용하는데, 저장장치 내 파일을 메모리에 캐싱한다. 프로세스가 파일의 데이터를 읽게되면 메모리에 올라가있는 프로세스 영역에 바로 복사하는 것이 아니라 페이지 캐시 영역에 복사한 후 프로세스 메모리로 복사하게된다. 이후 동일 데이터에 접근할 때에는 페이지케이영역에서 바로 탐색해 반환한다(페이지 테이블과 실제 물리 메모리에 접근할 필요가 없어짐.
    • 하이퍼스레드
      리눅스에서는 하이퍼스레드라는 기능이 존재하는데, CPU 코어 안의 일부 자원들(레지스터 등) 복제해 시스템 입장에서 각각 논리 CPU로 인식하게 하는 기능이다. core개수를 부풀려 논리적으로 여러개로 인식하게하며 프로그램 처리 속도를 증가시킬 수 있다고 한다.

File Systems

  • 파일시스템은 ?
    파일을 어떻게 관리할 것인가에 대한 정책. HW 저장공간에 저장되는 데이터들을 어떻게 저장하고, 읽을지, 공간 관리를 어떻게할지 등.
  • 리눅스의 파일시스템
    / (root) 아래에 계층적으로 모든 파일과 디렉토리가 만들어진다. 파일시스템으로는 EXT를 사용함.
    /
    /bin
    /home
    /lib
    /user
    /boot
    /etc
    리눅스는 위와 같은 공통구조를 갖는다.
    - bin : 기본 명령어들이 저장된 폴더
    - boot : 리눅스 boot와 관련된 명령이 들어간 폴더
    - etc : 리눅스 설정 파일들이 존재하는 폴더
    - home : home폴더, 로그인 계정에 따라 폴더 생성 및 할당
    - lib : 리눅스 및 programs에서 사용되는 라이브러리들 폴더.
    • 파일 시스템 종류 : FAT, NTFS, EXT
      • EXT : Extended file system. 리눅스의 기본 파일시스템으로 EXT2, EXT3, EXT4..가 있다. (성능 향상하며 시리즈로 출시) EXT3부터 큰 규모 디렉토리를 접근하기 위해 해쉬를 통해 접근하는 H-Tree를 사용하여 데이터 검색이 용이하다.
      • FAT
        파일 할당 테이블, 매우 단순한 자료구조로 FAT12,16,32..등으로 발전해왔다. 거의 이동식 디스크에 사용함. sector의 크기는 보통 512바이트이고, FAT에서는 여러 섹터를 하나로 묶은 논리 단위인 클러스터 단위로 디스크에 접근한다. index table에는 이 클러스터의 번호가 기록되는데, 종류에 따라 이 번호를 기록할 공간의 비트 크기가 다르고 이 크기를 이름에 붙여서 서로를 구분 디스크를 포맷할 때 일괄적으로 index들을 만들어놓는다. list 자료구조중 단순 연결 리스트를 이용한다.(읽고 쓰는 속도가 약간더빠르다는 장점, 32는 클러스터의 주소(16비트,32비트)를 의미.
      • NTFS : new technology file system. windows 계열의 파일시스템으로 시스템 고장 및 손상 시 디스크 볼륨을 재구성하여 일관성있는 상태로 복구가 가능, 안정성이 높고 보안성도 FAT보다 향상된 파일시스템. 가장 현대적인 파일시스템이다.
  • mount
    windows의 경우 usb등 보조기억장치를 연결하면 자동으로 directory에 연결되지만,(Plug and Play) 리눅스의경우 PnP를 지원하지 않는다. 보조기억장치 설치 시 mount작업을 수행해야함.
    파일 시스템 명 확인 : fdisk -l
    device를 특정 디렉토리에 마운트 : mount [option] [device] [directory]
    디스크 정보 출력(mount) : df

I/O

Interprocess

Network

Cloud

profile
정선용

0개의 댓글