Microsoft MVP성태의 닷넷 이야기
Windows: 274. Windows 7부터 도입한 conhost.exe [링크 복사], [링크+제목 복사],
조회: 4923
글쓴 사람
정성태 (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

비밀번호

댓글 작성자
 




... 31  [32]  33  34  35  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
13137정성태10/8/202214147.NET Framework: 2055. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 닷넷 모듈을 추출하는 방법
13136정성태10/7/202214504.NET Framework: 2054. .NET Core/5+ SDK 설치 없이 dotnet-dump 사용하는 방법
13135정성태10/5/202215027.NET Framework: 2053. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프를 분석하는 방법 - 두 번째 이야기 [1]
13134정성태10/4/202212232오류 유형: 820. There is a problem with AMD Radeon RX 5600 XT device. For more information, search for 'graphics device driver error code 31'
13133정성태10/4/202213365Windows: 211. Windows - (commit이 아닌) reserved 메모리 사용량 확인 방법 [1]
13132정성태10/3/202213393스크립트: 42. 파이썬 - latexify-py 패키지 소개 - 함수를 mathjax 식으로 표현
13131정성태10/3/202217197.NET Framework: 2052. C# - Windows Forms의 데이터 바인딩 지원(DataBinding, DataSource) [2]파일 다운로드1
13130정성태9/28/202213012.NET Framework: 2051. .NET Core/5+ - 에러 로깅을 위한 Middleware가 동작하지 않는 경우파일 다운로드1
13129정성태9/27/202213633.NET Framework: 2050. .NET Core를 IIS에서 호스팅하는 경우 .NET Framework CLR이 함께 로드되는 환경
13128정성태9/23/202216565C/C++: 158. Visual C++ - IDL 구문 중 "unsigned long"을 인식하지 못하는 #import [1]파일 다운로드1
13127정성태9/22/202214826Windows: 210. WSL에 systemd 도입
13126정성태9/15/202215352.NET Framework: 2049. C# 11 - 정적 메서드에 대한 delegate 처리 시 cache 적용
13125정성태9/14/202215765.NET Framework: 2048. C# 11 - 구조체 필드의 자동 초기화(auto-default structs)
13124정성태9/13/202215547.NET Framework: 2047. Golang, Python, C#에서의 CRC32 사용
13123정성태9/8/202215608.NET Framework: 2046. C# 11 - 멤버(속성/필드)에 지정할 수 있는 required 예약어 추가
13122정성태8/26/202216009.NET Framework: 2045. C# 11 - 메서드 매개 변수에 대한 nameof 지원
13121정성태8/23/202212419C/C++: 157. Golang - 구조체의 slice 필드를 Reflection을 이용해 변경하는 방법
13120정성태8/19/202216009Windows: 209. Windows NT Service에서 UI를 다루는 방법 [3]
13119정성태8/18/202215142.NET Framework: 2044. .NET Core/5+ 프로젝트에서 참조 DLL이 보관된 공통 디렉터리를 지정하는 방법
13118정성태8/18/202212682.NET Framework: 2043. WPF Color의 기본 색 영역은 (sRGB가 아닌) scRGB [2]
13117정성태8/17/202216361.NET Framework: 2042. C# 11 - 파일 범위 내에서 유효한 타입 정의 (File-local types)파일 다운로드1
13116정성태8/4/202216794.NET Framework: 2041. C# - Socket.Close 시 Socket.Receive 메서드에서 예외가 발생하는 문제파일 다운로드1
13115정성태8/3/202217357.NET Framework: 2040. C# - ValueTask와 Task의 성능 비교 [1]파일 다운로드1
13114정성태8/2/202217255.NET Framework: 2039. C# - Task와 비교해 본 ValueTask 사용법파일 다운로드1
13113정성태7/31/202216732.NET Framework: 2038. C# 11 - Span 타입에 대한 패턴 매칭 (Pattern matching on ReadOnlySpan<char>)
13112정성태7/30/202217610.NET Framework: 2037. C# 11 - 목록 패턴(List patterns) [1]파일 다운로드1
... 31  [32]  33  34  35  36  37  38  39  40  41  42  43  44  45  ...