Microsoft MVP성태의 닷넷 이야기
Windows: 274. Windows 7부터 도입한 conhost.exe [링크 복사], [링크+제목 복사],
조회: 4918
글쓴 사람
정성태 (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)
13566정성태2/27/20249557오류 유형: 897. Windows 7 SDK 설치 시 ".NET Development" 옵션이 비활성으로 선택이 안 되는 경우
13565정성태2/23/20248651닷넷: 2219. .NET CLR2 보안 모델에서의 개별 System.Security.Permissions 제어
13564정성태2/22/202410168Windows: 259. Hyper-V Generation 1 유형의 VM을 Generation 2 유형으로 바꾸는 방법
13563정성태2/21/20249650디버깅 기술: 196. windbg - async/await 비동기인 경우 메모리 덤프 분석의 어려움
13562정성태2/21/20249360오류 유형: 896. ASP.NET - .NET Framework 기본 예제에서 System.Web에 대한 System.IO.FileNotFoundException 예외 발생
13561정성태2/20/202410164닷넷: 2218. C# - (예를 들어, Socket) 비동기 I/O에 대한 await 호출 시 CancellationToken을 이용한 취소파일 다운로드1
13560정성태2/19/202410215디버깅 기술: 195. windbg 분석 사례 - Semaphore 잠금으로 인한 Hang 현상 (닷넷)
13559정성태2/19/202411042오류 유형: 895. ASP.NET - System.Security.SecurityException: 'Requested registry access is not allowed.'
13558정성태2/18/202410197닷넷: 2217. C# - 최댓값이 1인 SemaphoreSlim 보다 Mutex 또는 lock(obj)를 선택하는 것이 나은 이유
13557정성태2/18/20249077Windows: 258. Task Scheduler의 Author 속성 값을 변경하는 방법
13556정성태2/17/20249458Windows: 257. Windows - Symbolic (hard/soft) Link 및 Junction 차이점
13555정성태2/15/20249668닷넷: 2216. C# - SemaphoreSlim 사용 시 주의점
13554정성태2/15/20249091VS.NET IDE: 189. Visual Studio - 닷넷 소스코드 디컴파일 찾기가 안 될 때
13553정성태2/14/20248618닷넷: 2215. windbg - thin/fat lock 없이 동작하는 Monitor.Wait + Pulse
13552정성태2/13/20248743닷넷: 2214. windbg - Monitor.Enter의 thin lock과 fat lock
13551정성태2/12/20249841닷넷: 2213. ASP.NET/Core 웹 응용 프로그램 - 2차 스레드의 예외로 인한 비정상 종료
13550정성태2/11/202410297Windows: 256. C# - Server socket이 닫히면 Accept 시켰던 자식 소켓이 닫힐까요?
13549정성태2/3/202411257개발 환경 구성: 706. C# - 컨테이너에서 실행하기 위한 (소켓) 콘솔 프로젝트 구성
13548정성태2/1/202410820개발 환경 구성: 705. "Docker Desktop for Windows" - ASP.NET Core 응용 프로그램의 소켓 주소 바인딩(IPv4/IPv6 loopback, Any)
13547정성태1/31/202410494개발 환경 구성: 704. Visual Studio - .NET 8 프로젝트부터 dockerfile에 추가된 "USER app" 설정
13546정성태1/30/202410168Windows: 255. (디버거의 영향 등으로) 대상 프로세스가 멈추면 Socket KeepAlive로 연결이 끊길까요?
13545정성태1/30/20249723닷넷: 2212. ASP.NET Core - 우선순위에 따른 HTTP/HTTPS 호스트:포트 바인딩 방법
13544정성태1/30/20249354오류 유형: 894. Microsoft.Data.SqlClient - Could not load file or assembly 'System.Security.Permissions, ...'
13543정성태1/30/20249773Windows: 254. Windows - 기본 사용 중인 5357 포트 비활성화는 방법
13542정성태1/30/20248860오류 유형: 893. Visual Studio - Web Application을 실행하지 못하는 IISExpress - 두 번째 이야기
13541정성태1/29/20249625VS.NET IDE: 188. launchSettings.json의 useSSL 옵션
1  2  3  4  5  6  7  8  9  10  11  12  13  14  [15]  ...