Mach Overview
OSXDEV
Mac OS X 커널의 기본이 되는 서비스와 요소들은 Mach 3.0에 기반하고 있다. Apple은 Mac OS X의 기능과 목표한 성능에 적합하도록 Mach를 수정하고 확장하였다.
Mach 3.0은 처음에 간단하고, 확장가능하고, 통신하는 마이크로커널로써 고안되었다. 이것은 유저 모드 서버로서 실행되는 I/O, 파일 시스템, 네트워킹 스택과 같은 전통적인 운영체제 서비스들과 함께 독립적인(stand-alone) 커널로서 실행이 가능하다.
그러나, Mac OS X에서 Mach는 다른 커널 요소들과 단일한 커널 주소 영역에 링크된다. 이것의 주된 이유는 성능때문이다. 링크된 요소들 사이에 바로 호출을 하는 것이 분리된 태스크간에 메세지를 보내거나 원격 프로시져 호출(RPC)을 하는 것보다 훨씬 빠르다. 이러한 모듈화된 구조는 순수한 마이크로커널의 성능 저하 문제가 없이, monolithic 커널이 허용하는 것 보다 더욱 안정적이고 확장가능한 시스템이 될 수 있도록 한다.
그러므로 Mac OS X에서는 Mach가 클라이언트와 서버사이에 통신 허브(hub)의 본래의 역할을 하지 않는다. 그러나 Mach는 추상화와 확장성, 유연함과 같은 가치를 지닌다. 특별히 Mach는 다음과 같은 기능을 제공한다.
- 객체 참조로서 통신 채널(예를 들어 ports)과 함께 객체기반의 API
- 고도로 병행화된 실행. 선점적으로(preemptively) 스케쥴되는 쓰레드와 SMP에 지원을 포함
- 유연한 스케쥴링 프레임워크. 실시간(real-time) 사용에 대한 지원 포함
- 완전한 IPC 기본 요소 세트. 메세징, RPC, 동기화와 notification을 포함
- 큰 영역의 가상 메모리 공간, 공유 메모리 영역, 지속적인 저장공간 위에 올려지는 메모리 오브젝트 지원
- 증명된 확장성과 이식성. 예를 들어, 다양한 명령 셋트 아키텍쳐 지원(across instruction set architectures)과 분산화된 환경
- 기본적인 디자인 원칙으로 보안과 자원 관리에 대한 고려. 모든 자원은 가상화된다.
목차 |
[편집] Mach 커널 추상화 요소
Mach는 간결함과 강력함을 위해 디자인된 세부적인 추상화 세트를 제공한다. 주요 커널 추상화 요소는 다음과 같다:
- Tasks. 자원을 소유하게 되는 단위이다. 각각의 태스크는 가상 메모리 영역, 포트 권한 이름공간(port right namespace), 하나 이상의 쓰레드로 구성되어 있다. (프로세스와 비슷하다.)
- Threads. 태스크에서 CPU 실행의 단위이다.
- Address space. 메모리 관리자와의 결합으로, Mach는 희박한(sparse) 가상 메모리 주소와 공유 메모리 개념을 구현한다.
- Memory objects. 내부적인 메모리 관리 단위이다. 메모리 오브젝트는 이름 있는 엔트리와 영역을 포함한다. 주소 영역으로 맵핑되었을 잠재적으로 영속적인 데이터의 표현이다.
- Ports. 안전하고(secure), 단방향의 통신 채널이다. 오직 보내고, 받는 기능을 통해서만 접근이 가능하다. (port rights 라고 알려짐)
- IPC. Message queues, remote procedure calls, notifications, semaphores, and lock sets.
- Time. Clocks, timers, and waiting.
트랩(trap) 레벨에서, 대분의 Mach 추상화 요소들에 대한 인터페이스는 이러한 오브젝트를 나타내는 kernel ports에 보내지고 받는 메세지로 구성된다. 트랩 레벨 인터페이스(mach_msg_overwrite_trap 같은) 그리고 메세지 포맷 그 자체는는 Mach Interface Generator(MIG)에 의해 일반적인 사용형태로 추상화된다. MIG는 그러한 API의 descriptor에 기반하여 절차적인(procedural) 인터페이스를 메세지 기반의 API로 컴파일 하는데 사용된다.
[편집] 태스크와 쓰레드
Mac OS X 프로세스와 POSIX 쓰레드(pthreads)는 각각 Mach 태스크와 쓰레드 위에 구현되어있다. 쓰레드는 태스크에서 제어 흐름이 일어나는 시점이다. 태스크는 포함하고 있는 쓰레드를 위한 자원을 제공하기위해 존재한다. 이러한 구분은 병렬화와 자원공유를 위해서 존재한다.
쓰레드
- 태스크에서 제어의 흐름의 시점
- 포함하는 태스크의 모든 요소에 접근할 수 있다.
- 다른 쓰레드들과 병렬로 실행된다(잠재적으로), 심지어 같은 태스크의 쓰레드들과 병렬로 실행될 수 있다.
- 부하를 적게하기 위해 죄소한의 상태 정보만 저장하고 있다.
태스크
- 시스템 자원의 집합이다. 이러한 자원들은, 주소 공간에 대한 것을 제외하고, port에 의해 참조된다. 이러한 자원들은 그 포트에 대한 권한이 분배되도록 되어있다면, 다른 태스크와 공유될 수 있다.
- 가상 메모리에 의해 참조되는 크고, 잠재적으로 드문드문한 주소 공간을 제공한다. 이러한 공간의 일부분은 상속 또는 외부 메모리 관리를 통해 공유될 수 있다.
- 몇개의 쓰레드를 포함한다.
태스크는 자기 자신의 생명주기가 없다는 것에 주의하자 - 오직 쓰레드가 명령을 수행한다. "태스크 Y가 X를 한다"고 한다면, 이것은 실제로 "태스크 Y에 속하고 있는 어떤 쓰레드가 X를 한다"는 것을 의미한다.
태스크는 꽤 비싼 실체이다. 이것은 자원들의 집합으로써 존재한다. 태스트안의 모든 쓰레드는 모든것을 공유한다. 두개의 태스크는 명시적인 처리없이(보통 간단한 처리이다) 어떤 것도 공유하지 않고, 일부 자원은 (port 수신 권한 같은) 두개의 태스크에서 절대로 공유될 수 없다.
쓰레드는 꽤 가벼운 실채이다. 이것은 생성하기에 꽤나 비용이 적고, 작동하는데 부하가 작다. 쓰레드는 적은 상태 정보를 갖고 있기 때문에(대부분 레지스터 상태) 이것은 사실이다. 태스크는 자원 관리에 대한 모든 책임을 진다. 멀티프로세서 컴퓨터에서, 하나의 태스크에 있는 다수의 쓰레드가 병렬로 실행되는 것이 가능하다. 병렬성이 목표가 아닌 상황에서도, 다수의 쓰레드는 하나의 쓰레드가 다수의 서비스를 제공하기 위해서 비동기적인 프로그래밍을 해야하는 대신에, 각각의 쓰레드가 동기적인 프로그래밍 스타일을 사용할 수 있다는 점에서 이점이 있다.
쓰레드는 기본이되는 계산의 실체이다. 쓰레드는 자신의 가상 메모리 공간을 정의하는 오직 하나의 태스크에 속한다. 주소 공간의 구조에 영향을 미치거나, 메모리 공간이 아닌 어떤 자원에 참조하기 위해 쓰레드는 특별한 trap 명령을 실행하여 커널이 쓰레드를 대신하여 작업을 수행하거나, 어떤 대행자에게 메세지를 보내도록 해야한다. 일반적으로 이러한 trap은 쓰레드를 포함하고 있는 태스크와 연관된 자원을 다룬다. 커널이 이러한 실체를 다루도록(생성, 삭제, 상태에 영향을 미침) 요청할 수 있다.
Mach는 쓰레드 스케쥴링 정책에 대해 유연한 프레임워크를 제공한다. Mac OS X의 초기 버젼은 시간 공유(time-sharing)와 고정된 우선순위(fixed priority) 정책 모두를 지원한다. 시간 공유 쓰레드 우선순위는 다른 시간 공유 쓰레드에 대해 자신의 자원 소모의 균형을 맞추기 위해 올라갔다가 내려간다.
고정 순위 쓰레드는 특정한 시간의 양만큼 실행을 한다, 그런후에 동일한 우선순위의 쓰레드들의 큐의 마지막에 들어간다. 고정 순위 쓰레드의 레벨을 무한대로 설정하는 것은 쓰레드가 block되거나 더 높은 우선순위의 쓰레드에 의해 선점될때까지 실행되는 것을 허용한다. 높은 순위의 실시간 쓰레드는 일반적으로 고정된 우선순위이다.
Mac OS X는 실시간 성능을 보장하기 위해 시간 제약 스케쥴링도 제공한다. 이 스케쥴링은 쓰레드가 반드시 특정한 시간의 기간동안 특정한 시간 양만큼 취하도록 지정할 수 있다.
Mach 스케쥴링은 Mach Scheduling and Thread Interfaces에서 더 자세히 다룬다.
[편집] Ports, Port Rights, Port Sets, and Port Namespaces
태스크의 가상 주소 공간을 제외하고, 모든 다른 Mach 자원들은 port라고 알려진 간접적인 단계를 통해 접근이 가능하다. port는 서비스를 요청한 client와 서비스를 제공하는 서버 사이의 단방향 통신 채널의 종점이다. 만약 그러한 서비스 요청에 대해 응답이 제공되어야 한다면, 또 하나의 port가 반드시 사용되어야 한다. 이것은 UNIX에서의 (단방향) 파이프와 비슷하다.
대개, port에 의해 접근되는(즉 port에 의해 이름붙여진) 자원은 객체로서 참조된다. port의 의해 이름붙여진 대부분의 객체는 하나의 수신자와 (잠재적으로) 다수의 발송자를 갖는다. 즉, 메세지 큐 같은 일반적인 객체에대해 정확히 하나의 수신 포트와, 최소한 하나의 송신 포트가 있다.
하나의 객체에 의해 제공되는 서비스는 객체에 보내진 요청을 수신하는 관리자에의해 결정된다. 커널이 제공하는 객체와 관련된 port에 대한 수신자는 커널이되고, 태스크가 제공하는 객체와 관련된 port에 대한 수신자는 태스크가 제공하는 객체이다.
태스크 제공 객체의 이름을 짓는 port에 대해, 다른 태스크에 대한 port로의 요청의 수신자를 변경하는 것이 가능하다. 어떤 하나의 태스크는 그것이 지원하는 자원을 참조하는 다수의 port를 갖을 수 있다. 이런 식으로, 어떤 주어진 실체는 그것을 표현하는 다수의 포트를 갖을 수 있다. 그것들은 각각의 허용되는 작업의 세트를 포함하고 있다. 예를 들어, 많은 객체는 name port와 control control(privileged port라 불리기도 함)을 갖고 있다. control port로의 접근은 객체가 조작되는 것을 허용한다; name port로의 접근은 간단히 객체에 이름을 짓는다, 그렇게 함으로써 객체의 정보를 가져오거나 다른 비특권적인 작업을 수행할 수 있다.
태스크는 특정한 방법(송신, 수신, 일회성 송신)으로 포트에 접근할 수 있는 권한을 가지고 있다. 이것을 port 권한(rights)이라고 한다. port는 오직 권한(right)를 통해서만 접근이 가능하다. Port는 Mach안의 객체에게 클라이언트 접근을 주기위해 사용되기도 한다. 객체의 IPC port에 송신할 권한을 갖는다는 것은 규정된 방식대로 객체를 다룰 수 있는 권한이 있다는 것을 뜻한다. Port의 권한 소유권은 Mach안에서 근본이되는 보안 메커니즘이다. 어떤 객체에 대해 권한을 갖는 것은 그 객체를 접근하고 다룰 수 있는 능력이 있다는 것을 뜻한다.
Port 권한은 IPC를 통한 태스크간에 복사되고 이동될 수 있다. 그렇게 함으로써, 권한을 어떤 객체나 서버에게 넘길 수 있다.
Port에 의해 참조되는 객체 타입중의 하나로 port set가 있다. 이름에서 추측이 가능하듯, port set는 메시지나 set의 어떤 다른 멤버로부터의 이벤트를 받을때 하나의 단위로 취급될 수 있는 port 권한의 세트이다. Port set는 하나의 쓰레드가 다수의 메세지나 이벤트 소스를 기다리도록 허가할 수 있다, 예로 work loops가 있다.
전통적으로 Mach에서는, port에 의해 표현되는 통신 채널은 항상 메세지의 큐(queue)였다. 그러나, Mac OS X는 추가적인 형식의 커뮤니케이션 채널을 지원한다. 그리고 이러한 IPC 객체의 새로운 형식은 물론 port와 port 권한에 의해 표현된다. IPC 형식들에 대해 더 자세히 알고 싶다면 Interprocess Communication (IPC) 를 보기 바란다.
Port와 port 권한은 임의의 port나 권한이 직접적으로 다뤄질 수 있는 시스템전역적인 이름을 갖지 않는다. 오직 태스크가 port 이름공간(namespace)의 port 권한을 갖고 있는 경우에만, port를 다룰 수 있다. Port 권한은 port name에 의해 지정된다. Port name은 32bit의 port 이름공간의 정수형 인덱스이다. 각각의 태스크는 단일한 port 이름공간과 관련되어 있다.
다른 태스크가 명시적으로 Port 권한을 자신의 네임스페이스로 추가할때, 메세지에서 권한을 수신할경우, 그 객체에 대한 권한을 리턴하는 객체를 생성함으로써, 그리고 확정된 특별한 ports(mach_thread_self, mach_task_self, mach_reply_port) Mach 호출을 통해, 태스크는 port 권한을 획득한다.
[편집] 메모리 관리
대부분 현대적인 운영체제처럼, Mach는 넓고(large), 드문드문한(sparse) 가상 주소 공간을 제공한다. 실시간 접근은 접근이 시도되는 최초의 시간에 물리적 메모리 위치와 일치하지 않을 수도 있는 가상의 주소를 통해서 이루어진다. Mach는 요청된 가상 주소를 취하여 대응하는 물리적 메모리 주소를 할당한다. 이것은 페이지 요청(demand pagaing)을 통해 수행된다.
가상 주소의 범위는 메모리 객체가 그 범위에 맵핑될때 데이터와 함께 장소를 차지하게 된다. 주소 공간의 모든 데이터는 궁극적으로는 메모리 객체를 통해 제공된다. Mach는 메모리 객체의 소유자(페이저)에게 페이지의 내용을 요구한다, 물리적 메모리에서 그것을 수행했다면 페이지를 회수하기 전에 페이저에게 수정되었을듯한 데이터를 리턴한다. Mac OS X는 기본(default) 페이저와 vnode 페이저의 두개의 내장된 페이저를 포함하고 있다.
기본 페이저는 익명 메모리라고 알려진 비영속적인 메모리를 다룬다. 익명 메모리는 0으로 초기화되어있다, 그리고 태스크가 살아있는 동안만 존재한다. vnoe 페이저는 파일을 메모리 객체로 맵핑한다. Mach는 메모리 객체에 대한 인터페이스를 익스포트하여 메모리 객체의 내용이 사용자 모드 태스크에 의해 분배되도록 한다. 이러한 인터페이스는 External Memory Management Interface(EMMI) 라고 알려져 있다.
메모리 관리 하위시스템은 named entries또는 named memory entries라고 알려진 가상 메모리 핸들을 익스포트한다. 대부분의 커널 자원들처럼, 이것들도 포트에 의해 나타난다. named memory entry를 갖게되면 소유자가 하부의 가상 메모리 객체를 맵핑하거나 하부의 객체를 다른 객체에 맵핑하기 위해 권한을 넘길 수 있다. 두개의 다른 태스크에서 named entry를 맵핑하면 두개의 태스크 사이의 공유 메모리 윈도우가 된다. 이것은 공유 메모리를 구현하는데 유연한 방법을 제공한다.
Mac OS X 10.1을 시작으로, EMMI 시스템은 포트없는 EMMI를 지원하도록 향상되었다. 전통적인 EMMI에서는, 두개의 Mach 포트가 각각의 메모리 영역에 생성되었다, 그리고 비슷하게 두개의 포트가 각각의 캐쉬된 vnode에 생성되었다. 포트없는 EMMI는 이것을 직접 메모리 참조(근본적으로 포인터)로 대체하였다. 앞으로의 릴리즈에서, 커널 공간의 페이저와의 통신을 위해 직접 참조를 사용하는 동시에, 포트는 커널밖에서 페이저와 통신하는데 사용될 것이다.
가상 메모리 공간의 주소 영역은 직접 할당을 통해 (vm_allocate을 사용) 장소를 차지할 수 있다. 하부의 가상 메모리 객체는 익명이고 기본 페이져에 의해 관리된다. 주소 공간의 공유 영역은 상속을 통해 구축될 수 있다. 새로운 태스크가 생성되면, 그것들은 부몰부터 복사된다. 이러한 복사는 하부의 메모리 주소 공간과 관련되있다. 객체의 맵핑된 부분은 맵핑에 관련된 속성에 기반하여 복사나, 공유나, 아무것도 아닌것으로 상속될 수 있다. Mach는 태스크 생성시에 상속된 복사의 성능을 최적화하기 위해서 copy-on-write로 알려진 지연된 복사의 형태를 수행한다.
바로 복사할 영역을 복사하는 대신에, copy-on-write 최적화가 보호된 공유에 의해 완료된다. 두개의 태스크는 읽기전용의 복사될 메모리를 공유한다. 둘중의 하나의 태스크가 어떤 영역을 수정하려고 한다면, 그 영역은 그때 복사된다. 이러한 메모리 복사의 지연된 평가는 몇가지 영역에서 간단하게 구현할 수 있는 중요한 최적화 방법으로, 특히 메세징 API에 그러하다.
Mach는 named 영역의 익스포트를 통해, 다른 형태의 공유를 제공한다. named 영역은 named 실체(entity)의 형태이나, 가상 메모리 객체에 의해 처리되는 대신에, 가상 맵 단편(virtual map fragment)에 의해 처리된다. 이 단편은 수많은 가상 메모리 객체로의 맵핑을 담고 있을 수 있다. 이것은 다른 가상 맵으로 맵핑될 수 있어서, 가상 메모리 객체의 그룹뿐만 아니라 그들의 존재하는 맵핑 관계까지 상속할 수 있는 방법을 제공한다. 이러한 특징은 테스크 구축에 중요한 최적화 수단이 된다. 예를 들어 공유 라이브리에 사용되는 메모리 공간의 복잡한 영역을 공유할때가 그러하다.
[편집] 시간 관리
Mach에서 전통적인 시간의 추상화는 clock이다. clock은 mach_timespec_t에 기반한 비동기적인 알람 서비스 세트를 제공한다. 하나 이상의 clock 객체들은 단조롭게 증가하는 나노세컨드로 표현되는 시간 값을 정의한다. 실시간 clock은 내장되어있고(built-in), 가장 중요하다. 그러나 시스템에서 다른 개념의 시간에 대한 다른 clock도 있을 수 있다. clock은 현재 시간을 얻고, 주어진 기간동안 잠들고, 알람을 설정하고(주어진 시간이 되면 통지하는 것), 그밖의 연산들을 지원한다.
mach_timespec_t API는 Mac OS X에서 구식이 되었다. 새롭고 더 적당한 API는 차례로 기본 데이타 타입으로 AbsoluteTime을 사용하는 타이머 객체에 기반하고 있다. AbsoluteTime은 기계의존적인 타입으로, 일반적으로 플랫폼 고유한 시간 기준이 된다. AbsoluteTime 값과 나노세컨드와 같은 다른 데이타 타입간에 변환하는 루틴이 제공된다. 타이머 객체는 비동기, 이동없는(drift-free) 통지, 취소, 이른(premature) 알람을 지원한다. 이것들은 좀 더 효율적이고 clock보다 더 정밀하다.




