Microsoft MVP성태의 닷넷 이야기
Windows: 274. Windows 7부터 도입한 conhost.exe [링크 복사], [링크+제목 복사],
조회: 4899
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
 

(시리즈 글이 2개 있습니다.)
Windows: 274. Windows 7부터 도입한 conhost.exe
; https://www.sysnet.pe.kr/2/0/13832

Windows: 275. C# - CUI 애플리케이션과 Console 윈도우 (Windows 10 미만의 Classic Console 모드인 경우)
; https://www.sysnet.pe.kr/2/0/13834




Windows 7부터 도입한 conhost.exe

근래의 윈도우 운영체제 환경에서 콘솔 프로그램을 실행할 때 이와 함께 연달아 뜨는 conhost.exe라는 프로세스를 본 적이 있을 것입니다. 그러게요, conhost.exe 프로세스가 도대체 뭘까요? 이에 대해 검색해 보면, 아래의 글에서 아주 상세하게 설명해 주고 있습니다.

What Is conhost.exe and Why Is It Running?
; https://www.howtogeek.com/4996/what-is-conhost.exe-and-why-is-it-running/

Windows XP까지만 해도, "Command Prompt" Console은 csrss.exe 프로세스(CSRSS: ClientServer Runtime System Service)가 담당했다고 합니다. 이로 인해 몇 가지 문제가 있었다고 하는데요, 1) csrss.exe 프로세스에 문제가 생기면 Console 조차도 띄울 수 없는 상황이 발생했고, 2) csrss.exe 프로세스가 높은 권한을 가지고 있어서 일부 문제는 보안 취약점으로 이어질 수도 있고, 3) 시스템 프로세스에 속하는 csrss 내에 User Interface와 관련된 테마(Theme)를 다루는 코드를 넣을 수 없어 이후 윈도우 버전이 올라가면서 바뀌는 UI 테마를 Console에는 반영할 수 없었다고 합니다.

csrss 개발팀이 UI 테마 코드를 시스템 프로세스 내에 넣는 것을 원치 않았다고는 하지만, 만약 오직 문제가 UI 테마 하나였다면 아마도 ^^ 구겨 넣지 않았을까 싶습니다. 하지만, 여러 가지 문제가 있었기 때문에 Console 기능을 별도의 프로세스로 분리하기로 결정한 것이 아닌가 생각됩니다.

실제로 XP 당시의 이미지를 보면 메모장과는 달리 cmd.exe 창은 XP 테마가 없습니다.

[출처: What Is conhost.exe and Why Is It Running?]
con_host_0.png

이후, Vista의 Desktop Window Manager(DWM)에서는 다행히 중간 처리 단계에서 "Command Prompt" 창에 부분적으로 테마를 적용할 수 있게 되었지만 그래도 여전히 csrss에서 담당하는 UI는 테마 적용이 안 됐습니다.

[출처: What Is conhost.exe and Why Is It Running?]
(창의 프레임 영역은 테마가 적용, 스크롤바 영역은 미적용)
con_host_1.png

그리고 마침내, Windows 7에서 "Console Window Host Process"를 도입해 csrss.exe로부터 "윈도우 호스트" 부분을 독립시킴으로써 테마 문제를 (보안/안정성 문제까지 한꺼번에) 해결했습니다. 바로 그 프로세스가 conhost.exe로 cmd.exe와 csrss.exe 사이의 중간 계층으로 동작한다고 합니다. 일례로, Windows XP/Server 2003에서 cmd.exe나 콘솔 앱을 실행하면,

cmd.exe
ConsoleApp1.exe

위와 같이 그 프로세스만 뜨고, 해당 프로세스 공간에서 함께 뜨는 콘솔 윈도우는 내부적으로 csrss.exe 측에서 관리를 하게 됩니다. 반면 Windows Server 2008 R2에서 콘솔 앱을 실행하면,

csrss.exe
   |- conhost.exe (cmd.exe와 연결)
   ㄴ conhost.exe (ConsoleApp1.exe와 연결)

cmd.exe
ConsoleApp1.exe

콘솔 응용 프로그램 하나에 대해 그와 상응하는 conhost.exe가 csrss.exe의 자식 프로세스로 뜨는데요, 이후 Windows Server 2012 R2에서는 그마저도 개별 프로세스의 하위에 뜨는 것으로 바뀌었습니다.

cmd.exe
   ㄴ conhost.exe

ConsoleApp1.exe (탐색기 등을 이용해 실행)
   ㄴ conhost.exe

cmd.exe (cmd.exe 환경에서 ConsoleApp1.exe 실행한 경우 conhost.exe를 공유)
   |- conhost.exe
   ㄴ ConsoleApp1.exe

conhost.exe에 대한 마이크로소프트의 공식 문서도 "What Is conhost.exe and Why Is It Running?" 글의 내용과 유사합니다.

Console Host
; https://learn.microsoft.com/en-us/windows/console/definitions#console-host

The Windows Console Host, or conhost.exe, is both the server application for all of the Windows Console APIs as well as the classic Windows user interface for working with command-line applications. The complete contents of this binary, both the API server and the UI, historically belonged to Windows csrss.exe, a critical system process, and was diverged for security and isolation purposes.


그리고 위의 글을 훨씬 자세하게 풀어쓴,

Windows Command-Line: Inside the Windows Console
; https://devblogs.microsoft.com/commandline/windows-command-line-inside-the-windows-console/

블로그에 담긴 아래의 그림이 모든 것을 설명해 줍니다.

[출처: Windows Command-Line: Inside the Windows Console]
con_host_2.png

먼저, 저 그림의 하단에 있는 ConDrv(condrv.sys)는 Console과 "Headless" 명령행 응용 프로그램이 연동하는 것을 나타냅니다. 즉, CUI 응용 프로그램의 I/O를 conhost.exe의 API Server로 연결해 주는 역할을 하는 것입니다.

사실 condrv.sys는 Windows 7 당시에는 없었고, Windows 8/Windows Server 2012 R2부터 도입됐는데요, 따라서 그전에는 아마도 속도가 느린 IPC 수단을 이용해 통신을 한 듯합니다. (그러고 보면, 마이크로소프트는 어떻게든 성능을 높이기 위해 커널 레벨로 내리는 것을 선호하는 경향이 종종 있습니다. ^^)

그림의 상단 영역에 있는 ConHost.exe 박스를 볼까요?

비록 해당 그림에서 ConHost.exe의 박스 안에 "Console UI App Services"라고 그려져 있어 자칫 프로세스 내부에서 Console 윈도우를 생성한다고 생각할 수 있는데, 실제로 테스트해 보면 ConsoleWindowClass에 해당하는 윈도우는 명령행 응용 프로그램의 프로세스 공간에서 생성됩니다. 그 윈도우와 conhost.exe가 어떻게 통신하는지는 모르겠지만, 어쩄든 그 윈도우의 관리 코드 자체는 ConHost.exe에 있다고 봐야 할 것이고 그 구성 요소 이름을 "Console UI App Services"라고 명명한 듯합니다.

이후, "Console"에 사용자가 입력한 텍스트, 가령 Console.ReadLine 코드의 수행으로 입력한 텍스트는 "Input Buffer"로 들어가 Console API를 거쳐 "Output Buffer"로 나온다고 합니다. 이때 Output Buffer는 (간략하게 보자면) CHAR_INFO 구조체 배열로 보면 되고, 그 "Output Buffer"로부터 GDI Renderer를 통해 화면으로 그려지는 명령이 다시 ConsoleWindowClass로 전달돼 최종적으로 Console 화면에 그려지는 것입니다. 이와 함께 "Console"에 사용자가 입력한 텍스트는 "API Server"를 거쳐 ConDrv의 IOCTL로 중계로 응용 프로그램에 전달됩니다. 다시 말해 Console.ReadLine의 결과가 반환되는 것입니다.

그리고 또 하나의 입력 방식이 있는데요, 바로 응용 프로그램이 ConDrv를 통해 전달하는 출력입니다. 가령 Console.WriteLine을 하면, 이것은 다시 ConDrv를 거쳐 IOCTL로 변환돼 "API Server"로 전달되고 "Console API"를 통해 "Output Buffer"로 표현됩니다. 만약 이 과정에서 Console.WriteLine에 VT Sequence가 포함돼 있다면, 이것은 VT Parser를 한 번 더 거쳐 "Output Buffer"로 전달됩니다.

그러니까, 바로 저 "VT Parser"가 추가된 덕분에 윈도우에서 VT Sequence를 제대로 처리할 수 있게 된 것입니다. 하지만 이것도 버전에 따라 다른데요, 아래의 그림에서처럼,

[출처: Windows Command-Line: Inside the Windows Console]
con_host_3.png

As discussed above, Windows Console provides a rich API. Using the Console API, Command-Line apps and tools write text, change text colors, move the cursor, etc. And, because of the Console API, Windows Console had little need to support ANSI/VT sequences that provide very similar functionality on other platforms. In fact, until Windows 10, Windows Console only implemented the bare minimum support for ANSI/VT sequences: ...[생략]... The Console team added comprehensive support for ANSI/VT sequences to Windows 10's Console, ...[생략]...


Windows 7에서는 기본적인 VT Sequence만 지원했고 이후 Windows 10이 돼서야 제대로 지원을 하게 됐다고 합니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 11/29/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13693정성태7/24/20247222개발 환경 구성: 717. Visual Studio - C# 프로젝트에서 레지스트리에 등록하지 않은 COM 개체 참조 및 사용 방법파일 다운로드1
13692정성태7/24/20247996디버깅 기술: 199. Windbg - 리눅스에서 뜬 닷넷 응용 프로그램 덤프 파일에 포함된 DLL의 Export Directory 탐색
13691정성태7/23/20247357디버깅 기술: 198. Windbg - 스레드의 Win32 Message Queue 정보 조회
13690정성태7/23/20246991오류 유형: 919. Visual C++ 리눅스 프로젝트 - error : ‘u8’ was not declared in this scope
13689정성태7/22/20248489디버깅 기술: 197. Windbg - PE 포맷의 Export Directory 탐색
13688정성태7/21/20247600닷넷: 2281. C# - Lock / Wait 상태에서도 일부 Win32 메시지 처리파일 다운로드1
13687정성태7/19/20248033닷넷: 2280. C# - PostThreadMessage로 보낸 메시지를 Windows Forms에서 수신하는 방법파일 다운로드1
13686정성태7/19/20247827오류 유형: 918. Visual Studio - ATL Simple Object 추가 시 error C2065: 'IDR_...': undeclared identifier
13685정성태7/19/20247978스크립트: 66. Windows 디렉터리 경로를 WSL의 /mnt 포맷으로 구하는 방법 - 두 번째 이야기
13684정성태7/19/20248144닷넷: 2279. C# - 문자열 보간식 사례 (예: 조건 연산자 사용)
13683정성태7/18/20247626오류 유형: 917. ClrMD - Linux 환경의 .NET 5 덤프 분석 시 hang 현상
13682정성태7/18/20247838닷넷: 2278. WPF - 스레드에 종속되는 DependencyObject파일 다운로드1
13681정성태7/17/20247449닷넷: 2277. C# 13 - (2) 메서드 그룹의 자연 타입 개선 (메서드 추론 개선)파일 다운로드1
13680정성태7/16/20247806닷넷: 2276. C# - Method Group, Natural Type, function_type파일 다운로드1
13679정성태7/16/20246915Linux: 76. Linux - C++ (getaddrinfo 등을 담고 있는) libnss 정적 링크
13678정성태7/15/20247041VS.NET IDE: 191. Visual Studio 2022 - .NET 5 프로젝트를 Docker Support로 실행했을 때 오류
13677정성태7/15/20247113오류 유형: 916. MSBuild - CheckEolTargetFramework (warning NETSDK1138)
13676정성태7/14/20247303Linux: 75. gdb에서 glibc의 함수에 Breakpoint 걸기
13675정성태7/13/20249082C/C++: 166. C/C++ - DLL에서 template 함수를 export하는 방법 [1]파일 다운로드1
13674정성태7/13/20247971오류 유형: 915. Unhandled Exception: Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException: Unable to connect to Process
13673정성태7/11/20248410닷넷: 2275. C# 13 - (1) 신규 이스케이프 시퀀스 '\e'파일 다운로드1
13672정성태7/10/20247134닷넷: 2274. IIS - (프로세스 종료 없는) AppDomain Recycle
13671정성태7/10/20247243오류 유형: 914. Package ca-certificates is not installed.
13669정성태7/9/20247355오류 유형: 913. C# - AOT StaticExecutable 정적 링킹 시 빌드 오류
13668정성태7/8/20247379개발 환경 구성: 716. Hyper-V - Ubuntu 22.04 Generation 2 유형의 VM 설치
13667정성태7/7/20246597닷넷: 2273. C# - 리눅스 환경에서의 Hyper-V Socket 연동 (AF_VSOCK)파일 다운로드1
1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...