본문 바로가기

CS study/운영체제

프로세스 태스크, 쓰레드, 가상화에 대해

목차

    레퍼런스

    https://www.youtube.com/watch?v=xewZYX1e5R8&ab_channel=널널한개발자TV (프로세스)

    https://www.youtube.com/watch?v=x-Lp-h_pf9Q&ab_channel=널널한개발자TV (프로세스 쓰레드의 차이)

    프로세스와 태스크

    프로세스와 태스크(task)는 운영체제에서 실행되는 프로그램 또는 작업 단위를 나타내지만, 이 두 용어는 약간 다른 의미로 사용된다.

    • 프로세스: 실행 중인 프로그램의 인스턴스로, 메모리, CPU 시간, 입출력 등의 자원을 필요로 한다. 프로세스는 독립적인 메모리 공간을 가지며, 프로세스 간에는 직접적인 메모리 접근이 일반적으로 허용되지 않는다.
    • 태스크(task): 작업의 단위로 사용되며, 특히 실시간 시스템이나 임베디드 시스템에서 더 일반적으로 사용된다. 태스크는 때로는 경량 프로세스(lightweight process)로 볼 수도 있다. 특정 시스템에서는 태스크와 프로세스가 거의 동일한 의미로 사용될 수도 있다.

    멀티태스크는 여러 프로세스나 태스크를 동시에 또는 거의 동시에 실행하는 방식을 의미한다. 이는 CPU가 빠르게 여러 작업을 전환하면서 수행하는 것처럼 보이게 하는 방식으로 구현될 수 있다.

    • 선점형 멀티태스킹(preemptive multitasking): 운영체제가 CPU 자원을 각 프로세스나 태스크에 할당하고, 일정 시간이 지나면 다음 작업으로 자원을 넘기는 방식.
    • 협력형 멀티태스킹(cooperative multitasking): 각 프로세스나 태스크가 명시적으로 CPU 자원을 다른 작업에게 양보하는 방식.

    두 방식은 각각 장단점이 있으며, 특정 애플리케이션 또는 시스템 요구 사항에 따라 적합한 방식이 선택된다.

    프로세스와 쓰레드의 차이

    프로세스와 쓰레드는 둘 다 실행 중인 프로그램 코드의 인스턴스를 나타내지만, 주요한 차이점이 몇 가지 있다.

    1. 독립성 vs 공유:
      • 프로세스: 독립적인 메모리 공간과 자원을 가짐. 다른 프로세스와 정보를 공유하려면 IPC(Inter-Process Communication) 같은 메커니즘 필요.
      • 쓰레드: 같은 프로세스 내의 쓰레드끼리는 코드, 데이터 섹션 등을 공유. 따라서 통신이 더 쉽고 빠름.
    2. 자원 소모:
      • 프로세스: 독립적인 자원을 가지므로, 생성과 종료가 더 무거움.
      • 쓰레드: 쓰레드 생성과 종료는 상대적으로 가볍고 빠름.
    3. 문맥 교환(Context Switching):
      • 프로세스: 문맥 교환이 무거움. 왜냐하면 독립적인 메모리와 자원을 가지고 있기 때문.
      • 쓰레드: 같은 프로세스 내의 쓰레드는 메모리와 자원을 공유하기 때문에 문맥 교환이 더 빠르고 가볍다.
    4. 실행과 스케줄링:
      • 프로세스: 운영체제에 의해 스케줄링됨.
      • 쓰레드: 쓰레드 라이브러리 또는 운영체제에 의해 스케줄링될 수 있음.
    5. 안정성:
      • 프로세스: 하나의 프로세스가 죽어도 다른 프로세스에는 영향을 주지 않음.
      • 쓰레드: 하나의 쓰레드가 문제를 일으키면 같은 프로세스 내의 다른 쓰레드 모두에 영향을 줄 수 있음.

    프로세스와 쓰레드는 각각의 장단점이 있어, 어떤 것을 사용할지는 애플리케이션의 요구사항과 목적에 따라 달라진다.

    가상화와 도커

    가상화(Virtualization)

    가상화는 하나의 물리적 하드웨어 리소스를 여러 가상 리소스로 나누어 사용하는 기술이다. 이를 통해 물리적 서버 하나에 여러 개의 독립적인 운영체제(OS)를 실행할 수 있다. 가상화는 크게 두 종류로 나눌 수 있다.

    1. 하드웨어 수준 가상화: 각 가상 머신(VM)이 독립적인 전체 OS를 실행한다. 이렇게 하려면 Hypervisor라고 불리는 관리 프로그램이 필요하다. Hypervisor는 각 VM에 하드웨어 리소스를 할당하고, 이 VM들이 각자의 OS를 독립적으로 실행할 수 있게 관리한다.
    2. 컨테이너 가상화: 이 방식은 하나의 OS 커널을 여러 애플리케이션 간에 공유한다. 이렇게 하면 전체 OS를 부팅할 필요 없이 애플리케이션을 실행할 수 있어 더 가볍고 빠르다.

    도커의 가상화 방식

    1. 하드웨어 수준 가상화: 여기서는 물리적 하드웨어 위에 Hypervisor가 실행되고, 이 Hypervisor가 물리적 리소스를 가상 머신(VM)들에게 분할해서 제공한다. 각 VM은 자신만의 독립적인 운영체제를 가진다. 즉, 커널 영역도 VM 별로 독립적이다. 이 경우, 실제로 새로운 운영체제를 설치한다고 볼 수 있다.
    2. 컨테이너 가상화 (예: 도커): 이 방식에서는 호스트 OS의 커널을 모든 컨테이너가 공유한다. 물리적 리소스는 아예 분리하여 할당하는 것이 아니라, cgroups 같은 메커니즘을 통해 리소스 사용을 제한하고 분리한다. 컨테이너 내에서 실행되는 애플리케이션은 호스트 OS의 커널을 사용하므로, 새로운 운영체제를 설치하는 것은 아니다.

    도커는 컨테이너 가상화 방식을 사용한다. 이는 하드웨어 수준 가상화보다 더 경량화되어 있고 빠르다. 도커 컨테이너는 호스트 OS의 커널을 공유하면서 동작한다. 그렇기 때문에 각 컨테이너는 독립적인 파일 시스템, 사용자 ID, 그룹 ID, 네트워크 등을 가질 수 있지만, 커널은 호스트와 공유한다.

    1. 커널 공유: 모든 컨테이너는 호스트 OS의 커널을 공유한다. 독립적인 커널을 가지지 않는다.
    2. 리소스 분리와 제한: 컨테이너 내부에서 실행되는 프로세스는 리눅스의 cgroups 같은 기술로 CPU, 메모리 사용 등을 제한하고 분리할 수 있다.
    3. 파일 시스템 격리: 각 컨테이너는 독립적인 파일 시스템을 가진다. 이를 통해 서로 다른 컨테이너에서 같은 파일 이름 등을 사용해도 충돌이 일어나지 않는다.

    도커는 이러한 방식으로 가상화의 대부분의 이점을 누리면서도, 추가적인 오버헤드 없이 빠르고 효율적인 실행 환경을 제공한다.

    도커는 사실 격리된 게 아니다. 격리된 것처럼 보이는 것이다.

    도커 컨테이너는 본체 PC의 리눅스 커널을 공유하고, 물리적인 자원(CPU, 메모리, 디스크 등)도 본체 PC에서 할당받는다. 도커는 리눅스의 cgroups, namespaces 같은 기술을 활용해 이런 자원들을 컨테이너 별로 분리하고 제한한다.

    예를 들어, 도커 컨테이너에서 파일을 저장하면, 그 파일은 실제로는 본체 PC의 하드 디스크에 저장된다. 다만, 도커의 파일 시스템 격리 덕분에, 컨테이너 내에서는 마치 독립된 파일 시스템을 가진 것처럼 보인다.

    도커의 포트 매핑 기능을 이용하면, 컨테이너와 외부 세계 사이의 통신을 특정 포트를 통해 제어할 수 있다. 이는 컨테이너가 별도의 IP 주소를 가지고 있는 것처럼 보이게 하며, 네트워크 격리를 더욱 강화한다.

    따라서 도커 컨테이너는 본체의 자원을 공유하면서도, 격리와 제한을 통해 독립적인 실행 환경을 생성한다. 그리고 네트워크 포트를 통한 접근을 제어하여 외부와의 차단 또는 연결을 유연하게 관리한다.