프로세스 별로 핸들정보를 저장하고 있는 핸들 테이블이 존재한다.
각각의 프로세스가 자신만의 핸들 테이블을 하나씩 구성하고 관리한다.
프로세스가 CreateProcess 함수나 CreateMailslot과 같은 함수 호출을 통해서 리소스 생성을 요구한 결과로 핸들 정보를 얻게 될 경우, 프로세스 자신에게 속해있는 핸들 테이블에 해당 정보가 등록된다.
핸들 테이블은 프로세스 별로 독립적이다.
핸들의 상속
CreateProcess 함수를 호출하면 새로운 자식 프로세스가 생성되고, 자식프로세스를 위한 핸들 테이블도 더불어 생성된다. CreateProcess 함수 호출시 전달되는 인자에 따라 부모프로세스의 핸들테이블에 등록되어 있는 핸들 정보들을 자식 프로세스에 상속시킬 수 있다.
핸들의 상속에 대한 이해
실제 핸들테이블에는 해당 핸들의 상속여부를 결정짓기 위한 컬럼이 존재한다. 또한 핸들테이블의 레코드가 상속될때 상속 여부에 대한 정보도 변경없이 그대로 상속된다. 따라서 자식 프로세스가 또 다른 자식 프로세스를 생성할 경우에도 이 핸들에 대한 정보도 계속해서 상속된다.
CreateProcess 함수중 bInheritHandle 전달인자는 자식 프로세스에게 핸들 테이블에 등록되어 있는 핸들 정보를 상속해 줄것인지, 말것인지를 결정하는 요소이다. TRUE를 인자로 전달할 경우 부모 프로세스의 핸들 테이블 정보는 자식 프로세스로 상속된다.
핸들의 상속과 커널 오브젝트의 Usage Count
프로세스의 핸들 테이블에 해당 핸들에 대한 정보가 갱신(추가)되었을 때 프로세스가 핸들을 얻게 되었다고 한다.
자식프로세스 생성 후 ->
핸들 테이블에 등록되어 있는 수만큼 Usage Count가 정해진다.
Mailslot 예제 핸들테이블
MailReceiver의 핸들 테이블의 127, 0x1200 번지에 있는 커널 오브젝트는 CreateMailSlot 에 의해 생성된 것이다.
MailSender의 핸들 테이블의 핸들 127은 0x1700번지에 있는 커널 오브젝트는 MailSlot에 데이터를 쓰기위한 CreateFile에 의해 생성된 것이다. 핸들 테이블은 프로세스 마다 독립적인 요소이기 때문에 핸들값이 같아도 가리키는 커널 오브젝트는 같을수도 있고, 다를 수도 있다.
Pseudo 핸들과 핸들의 중복(Duplicate)
GetCurrentProcess 함수를 통해서 얻은 핸들은 가짜 핸들(Pseudo 핸들) 이다.
GetCurrentProcess함수를 통해 얻은 핸들은 핸들 테이블에 등록되어 있지 않은 핸들이고, 실행중인 프로세스를 참조하기 위한 용도로 정의해놓은, 약속된 상수가 반환되는 것이기 때문이다. 그렇기 때문에 자식 프로세스에게 상속되지 않고, CloseHandle함수가 호출되어도 아무일도 발생하지 않는다.
실행중인 프로세스의 진짜 핸들을 얻기 위해서는 DuplicateHandle 이라는 함수가 필요하다.
DuplicateHandle()
BOOL DuplicateHandle(
HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwOptions
);
1.hSourceProcessHandle : 복제할 핸들을 소유하는 프로세스 지정
2.hSourceHandle : 복제할 핸들 지정
3.hTargetProcessHandle : 복제된 핸들을 소유할 프로세스 지정
4.lpTargetHandle : 복제된 핸들값을 저장할 변수의 주소를 지정
5.dwDesiredAccess : 복제된 핸들의 접근권한 지정
6.bInheritHandle : 복제된 핸들 상속 여부
7.dwOptions : DUPLICATE_SAME_ACCESS를 전달하면 원본 핸들과 동일한 접근권한, DUPLICATE_CLOSE_SOURCE가 전달되면 원본 핸들 종료
ex)
DulpcateHandle(A핸들, 256, B핸들, &val, ...);
DuplicateHandle(
프로세스 A 핸들, //프로세스 A에 존재하는
256, //핸들 256의 정보를
프로세스 B 핸들, //프로세스 B의 핸들 테이블에 등록한다.
&val, //등록된 핸들의 값은 변수 val에 저장한다.
...
);
프로세스를 생성할 때 핸들 테이블을 상속시키면 핸들 값 그대로 상속되지만 Duplicate Handle함수를 사용하면 새로운 핸들 값을 지정하여 테이블에 등록한다.
DuplicateHandle 사용예시
DuplicateHandle(
프로세스 A 핸들,
256
프로세스 A 핸들,
&val,
...
);
위 사용은 프로세스 A핸들 테이블의 256에 해당하는 핸들을 A프로세스 핸들테이블에 저장하라는 것이다.
DuplicateHandle함수에 의해 핸들이 복사되고 나면, Usage Count 도 증가한다. 복사된 핸들에 대해서도 CloseHandle 함수를 통해 핸들을 반환해야한다.
DuplicateHandle(
GetCurrentProcess(), GetCurrentProcess(),
GetCurrentProcess, &hProcess, ...
);
위와 같이 호출하면 진짜 핸들이 생성되어 핸들 테이블에 등록된다.
위와같이 DuplicateHandle함수로 자기자신의 핸들을 테이블에 등록할 때 beInheritHandle인자를 TRUE로 주어 상속을 하게 설정하면 등록된 부모프로세스의 핸들을 자식에게 상속시켜 줄 수 있다. 이후 부모프로세스의 핸들을 통해 자식 프로세스가 부모프로세스의 정보를 참조하거나 상태를 알 수 있다.
'Programming > Windows System Programming' 카테고리의 다른 글
스케줄링 알고리즘과 우선순위 (0) | 2020.07.13 |
---|---|
파이프 방식의 IPC (0) | 2020.07.12 |
프로세스 환경변수 (0) | 2020.07.11 |
Signaled vs Non-Signaled (0) | 2020.07.11 |
프로세스간 통신(IPC) 메일 슬롯 (0) | 2020.07.10 |