본문 바로가기
운영체제

윈도우즈 운영체제: 기본 개념 및 용어 소개 1

by oobw 2023. 10. 17.

윈도우즈 운영체제는 전세계적으로 가장 많이 사용되는 운영체제입니다. 이번 글에서는 운영체제인 윈도우즈에 대한 기본 개념과 용어를 소개합니다. 컴퓨터 사용자라면 한 번쯤은 들어봤을 이 용어들에 대해서 개념을 잡을 수 있도록 간단하게 소개합니다.

운영체제(Operating System, OS)

운영체제는 컴퓨터 시스템의 핵심 소프트웨어로, 하드웨어 자원을 관리하고 사용자와의 상호작용을 중개하며, 다양한 응용 프로그램들이 효율적이고 안정적으로 실행될 수 있도록 지원합니다. 이를 통해 사용자는 컴퓨터의 복잡한 내부 구조나 작동 원리를 상세히 알지 못해도 다양한 작업을 수행할 수 있게 되며, 응용 프로그램 개발자들은 하드웨어에 직접 접근하는 대신 운영체제가 제공하는 서비스와 인터페이스를 통해 프로그램을 개발할 수 있습니다.

Windows API

Windows API(Windows Application Programming Interface)는 마이크로소프트 윈도우 운영 체제에 포함된 일련의 프로그래밍 함수로, 개발자들이 윈도우 시스템 리소스와 서비스에 액세스할 수 있도록 합니다. 즉, 프로그램이 운영 체제와 상호 작용하게 해주는 인터페이스입니다. 다음은 Windows API의 주요 기능입니다.

  1. GUI 생성 및 관리 - 창, 버튼, 텍스트 박스 등의 사용자 인터페이스 요소를 생성하고 조작합니다.
  2. 파일 및 디렉터리 액세스 - 파일을 읽고 쓰거나 파일 시스템을 탐색합니다.
  3. 네트워크 통신 - 인터넷 또는 LAN에 연결하여 데이터를 전송합니다.
  4. 기기 제어 - 프린터, 카메라, 오디오 장치와 같은 하드웨어 장치와의 통신을 지원합니다.
  5. 메모리 관리 - 메모리 할당 및 해제와 같은 작업을 수행합니다.
  6. 시스템 서비스 - 서비스를 시작, 중지하거나 시스템 정보를 쿼리합니다.Windows API 사용하기Windows API를 사용하려면, 주로 C 또는 C++ 언어와 함께 Windows SDK를 사용합니다. 예제로, 간단한 메시지 박스를 표시하는 코드를 살펴보겠습니다:
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  MessageBox(NULL, L"Hello, Windows!", L"Greeting", MB_OK);
  return 0;
}

위 코드는 "Hello, Windows!"라는 메시지와 함께 메시지 박스를 표시합니다. Windows API는 윈도우 시스템의 근본적인 부분으로, 광범위한 기능을 제공합니다. 이로 인해, 많은 소프트웨어 개발자들이 윈도우 환경에서 다양한 애플리케이션을 만들 수 있습니다. 처음 시작하기에는 다소 복잡할 수 있지만, 시간을 투자하면 윈도우의 모든 능력을 활용하는 강력한 프로그램을 개발할 수 있습니다.

프로세스(Processes)

프로그램과 프로세스는 겉보기에는 유사하게 보일 수 있지만, 그 근본적인 본질은 다릅니다. 프로그램은 정적인 명령어의 연속이며, 프로세스는 프로그램의 인스턴스를 실행할 때 사용되는 자원 집합의 컨테이너입니다. Windows 프로세스의 가장 높은 수준의 추상화에서 다음과 같은 구성 요소를 포함합니다:

  • 개인 가상 주소 공간: 프로세스가 사용할 수 있는 가상 메모리 주소의 집합입니다.
  • 실행 가능한 프로그램: 초기 코드와 데이터를 정의하며 프로세스의 가상 주소 공간에 매핑됩니다.
  • 열려 있는 핸들의 목록: 세마포어, 동기화 객체, 파일 등의 다양한 시스템 자원을 나타내며, 프로세스 내의 모든 스레드에서 접근 가능합니다.
  • 보안 컨텍스트: 프로세스와 연결된 사용자, 보안 그룹, 권한, 속성, 클레임, 기능, 사용자 계정 제어(UAC) 가상화 상태, 세션 및 제한된 사용자 계정 상태를 식별하는 액세스 토큰이며, AppContainer 식별자와 관련된 격리 정보도 포함됩니다.
  • 프로세스 ID: 고유한 식별자로, 내부적으로는 클라이언트 ID라는 식별자의 일부입니다.
  • 적어도 하나의 실행 스레드: "빈" 프로세스도 가능하긴 하지만, 대부분 유용하지 않습니다.
  • 프로세스와 프로세스 정보를 보거나 수정할 수 있는 여러 도구들: 이러한 도구들 중 일부는 Windows 자체 내에 포함되어 있고, Windows 디버깅 도구 및 Windows SDK 내에 포함되어 있습니다. 또한 Sysinternals에서 제공하는 독립적인 도구들도 있습니다. 이러한 도구들의 많은 부분이 핵심 프로세스와 스레드 정보의 중복되는 부분집합을 보여주며, 때로는 다른 이름으로 식별될 수 있습니다.

스레드(Threads)

프로세스 내의 한 요소인 쓰레드는 Windows에서 실행을 위해 스케줄링되는 것입니다. 이것이 없으면 프로세스의 프로그램은 실행될 수 없습니다. 쓰레드에는 다음과 같은 핵심 구성 요소가 포함됩니다:

  • CPU 레지스터의 내용: 프로세서의 상태를 나타냅니다.
  • 두 개의 스택: 커널 모드에서 실행할 때 사용하는 스택, 사용자 모드에서 실행할 때 사용하는 스택
  • 스레드 로컬 스토리지(TLS)라는 개인 저장 공간: 서브시스템, 런타임 라이브러리 및 DLL에 의해 사용됩니다.
  • 쓰레드 ID라는 고유한 식별자: 내부 구조인 클라이언트 ID의 일부입니다. 프로세스 ID와 쓰레드 ID는 동일한 네임스페이스에서 생성되므로 중복되지 않습니다. 또한, 쓰레드는 때로는 다중 스레드 서버 애플리케이션에서 클라이언트의 보안 컨텍스트를 가장하는 데 사용되는 보안 컨텍스트 또는 토큰을 갖기도 합니다.

휘발성 및 비휘발성 레지스터와 개인 저장 공간은 쓰레드의 컨텍스트로 불립니다. 이 정보는 Windows가 실행되는 각 기계 아키텍처마다 다르기 때문에, 이 구조는 아키텍처에 특화되어야 합니다. Windows의 GetThreadContext 함수는 이 아키텍처 특화 정보(컨텍스트 블록이라고 불림)에 접근을 제공합니다. 추가적으로, 각 쓰레드는 스택도 갖게 되며, 이는 쓰레드 컨텍스트의 스택 레지스터에 의해 가리켜집니다.

한 쓰레드에서 다른 쓰레드로의 실행 전환은 커널 스케줄러를 포함하기 때문에, 특히 두 쓰레드가 자주 전환되는 경우 비용이 많이 들 수 있습니다. Windows는 이 비용을 줄이기 위해 다음의 두 가지 메커니즘을 구현합니다.

파이버(Fiber)

Fiber는 애플리케이션에게 Windows에 내장된 우선순위 기반 스케줄링 메커니즘에 의존하는 대신 자체 실행 스레드를 스케줄링할 수 있는 능력을 제공합니다. 이러한 Fiber는 경량 스레드로도 불립니다. 스케줄링 측면에서 코어는 Kernel32.dll의 사용자 모드에서 구현되기 때문에 이들에게 보이지 않습니다.

Fiber를 사용하려면 먼저 Windows의 ConvertThreadToFiber 함수를 호출해야 합니다. 이 함수는 스레드를 실행 중인 Fiber로 변환합니다. 그 후, 새롭게 변환된 Fiber는 CreateFiber 함수를 통해 추가적인 Fiber를 생성할 수 있습니다. 그러나 스레드와 달리 Fiber는 SwitchToFiber 함수를 통해 수동으로 선택될 때까지 실행을 시작하지 않습니다. 새 Fiber는 종료되거나 다른 Fiber를 실행하도록 다시 SwitchToFiber를 호출할 때까지 실행됩니다. 더 자세한 내용은 Windows SDK 문서의 Fiber 함수 부분을 참조하세요.

 

Fiber는 애플리케이션에 특정 유형의 스케줄링 제어를 제공할 수 있지만, 그 사용은 일반적으로 권장되지 않습니다. 대부분의 경우, 표준 스레드와 Windows 커널의 스케줄링 메커니즘을 활용하는 것이 더 안정적이고 효율적입니다.

유저 모드 스케줄링( User-mode scheduling, UMS)

윈도우의 64비트 버전에서만 사용 가능한 '유저 모드 스케줄링(User-mode scheduling, UMS) 스레드'는 기본적으로 fiber와 동일한 장점을 제공하면서 그 단점 중 일부만 가지고 있습니다. UMS 스레드는 자체 커널 스레드 상태를 가지기 때문에 커널에서도 확인할 수 있습니다. 이로 인해 여러 UMS 스레드가 시스템 호출을 차단하고 리소스를 공유하며 경쟁할 수 있습니다. 또한 두 개 이상의 UMS 스레드가 사용자 모드에서 작업을 수행할 필요가 있을 때, 스케줄러를 사용하는 대신 사용자 모드에서 실행 컨텍스트를 주기적으로 전환(한 스레드에서 다른 스레드로 양보)할 수 있습니다. 커널의 관점에서는 동일한 커널 스레드가 계속 실행 중이며 아무 것도 변한 것이 없습니다.

스레드는 각자의 실행 컨텍스트를 가지고 있지만, 프로세스 내의 모든 스레드는 프로세스의 가상 주소 공간과 그 프로세스에 속한 나머지 리소스를 공유합니다. 이는 프로세스 내의 모든 스레드가 프로세스의 가상 주소 공간에 대한 전체 읽기-쓰기 권한을 가지고 있음을 의미합니다. 그러나 다른 프로세스의 주소 공간을 참조할 수는 없습니다. 그렇게 하려면 해당 프로세스가 자신의 개인 주소 공간의 일부를 공유 메모리 섹션으로 사용 가능하게 해야 합니다. 또는 한 프로세스가 다른 프로세스를 열어 교차 프로세스 메모리 함수를 사용할 권한이 있어야 합니다.

각 프로세스는 개인 주소 공간과 하나 이상의 스레드 외에도 보안 컨텍스트와 커널 객체(파일, 공유 메모리 섹션 또는 뮤텍스, 이벤트, 세마포어와 같은 동기화 객체)에 대한 열린 핸들 목록을 가지고 있습니다. 각 프로세스의 보안 컨텍스트는 액세스 토큰이라는 객체에 저장됩니다. 프로세스 액세스 토큰은 프로세스의 보안 식별 및 자격 증명을 포함합니다. 기본적으로 스레드는 자체 액세스 토큰을 가지고 있지 않지만, 하나를 얻을 수 있습니다. 이를 통해 개별 스레드가 다른 프로세스의 보안 컨텍스트를 가장하게 할 수 있습니다.

가상 주소 서술자(VADs)는 메모리 관리자가 프로세스에서 사용하는 가상 주소를 추적하기 위해 사용하는 데이터 구조입니다. 이러한 데이터 구조체는 더 자세히 다루어집니다.

마무리

윈도우즈는 복잡한 구조와 많은 기능을 가진 운영체제입니다. 여기서 소개한 개념과 용어는 그저 언뜻 봤을 때 알아야 할 기초 중의 기초일 뿐입니다. 다음 글에 추가적으로 다른 기본 개념들을 소개하겠습니다.