Windows에는 운영체제가 응용 프로그램으로 보내 주는 각종 통지 메시지, 또는 응용 프로그램으로 하여금 보내기로 정한 기본(시스템) 메시지들이 0부터 WM_USER 미만까지의 범위에 들어있다. 그런데 시스템 메시지 영역은 유니코드 BMP만큼이나 이제 빈 공간이 거의 없고 다 고갈됐을 것 같은데..
2048도 아니고 겨우 1024는 처음에 공간을 너무 좁게 잡은 것 같다. 앞으로 새로운 메시지가 추가 가능할지 궁금하다.
- 그리고 요즘 어지간한 사용자들이 프로그램을 이것저것 띄워 놓고 나면 사용자 등록 메시지는 공간이 얼마나 사용되며 여유가 얼마나 남아 있을까?
- 스레드를 생성하면 TLS 슬롯이 얼마나 사용되며 이 역시 여유 공간은 얼마나 될까?
- Custom 클립보드 포맷을 등록하는 공간 역시 보통 얼마나 쓰이는 편일까?
- 20년 전이나 지금이나 빌드되는 프로그램의 기본 스택 크기는 1MB인 걸까? 부족하지는 않은가?
이런 게 궁금해지곤 한다. Windows의 개발사인 마소에서는 이런 usage 데이터를 더욱 궁금해하고 수집하고 싶어할 것이다.
그리고 Windows가 16비트에서 32비트로 넘어가면서.. 특히 3.x에서 95로 넘어가면서 메시지 체계가 바뀐 게 좀 있다.
(1) EM_SETSEL (에디트), LB_ADDSTRING (리스트박스) 같은 기성 컨트롤을 조작하는 메시지들이 그때는 WM_USER 이후의 사용자 영역에 있었지만, 32비트 시절부터는 WM_USER 이내의 시스템 메시지 영역으로 이동했다.
이런 건 굳이 바꿀 필요가 없어 보이는데 왜 헷갈리게 단절적인 변화를 만든 걸까? 게다가 앞서 언급한 바와 같이 WM_USER 이내의 영역 자체도 그리 넉넉한 편이 아닌데 말이다.
이런 메시지들은 비트수(16/32/64..;; ) 내지 사용하는 문자열(2바이트 단위 유니코드 / 1바이트 ANSI) 형태가 다른 프로그램끼리 주고 받더라도 언제나 제대로 맞게 전달된다는 것을 운영체제 차원에서 보장하기 위해서이다.
즉, 문자열 포인터 같은 게 lParam 값으로 같이 전달됐다면 포인터가 가리키는 메모리의 값에 대한 복사와 보정까지 운영체제가 알아서 처리해 준다는 것이다. WM_SETTEXT처럼 말이다.
이들과 달리, 기성 컨트롤 말고 후대에 새로 추가된 공용 컨트롤들은 통신 메시지들이 WM_USER 이후에 있으며, 운영체제 차원에서의 메모리 보정 지원이 없다.
공용 컨트롤은 처음부터 Windows 95 내지 NT 3.5x라는 32비트 환경에서 개발됐기 때문에 16비트 호환성을 고려할 필요가 없다.
그리고 메시지들이 LV_ITEM, TV_ITEM 같은 복잡한 구조체와 비트 플래그를 주고받는 형태로 구현돼 있다. 그러니 한 프로세스가 다른 프로세스의 공용 컨트롤 내용을 들여다보거나 메시지를 보내서 조작하기란 매우 난감할 것이다.
그나마 과거의 Windows 9x는 프로세스 간 공유 메모리(memory-mapped file)의 주소가 모든 프로세스에서 동일하기라도 했지만, 현재의 NT 계열에서는 그런 보장마저 없다. system hook을 설치해서 공용 컨트롤을 그 프로세스의 문맥에서 조작하는 코드를 집어넣어야 할 듯하다.
(2) 기성 컨트롤의 글자색과 배경색을 변경하는 용도로 WM_CTLCOLOR 계열 메시지가 쓰이는데.. 얘는 16비트 시절에 그랬다. 32비트부터는 WM_CTLCOLORBTN, DLG, EDIT, STATIC 등으로 메시지의 형태가 세분화됐다. 왜 그리 됐을까?
메시지와 함께 전달되던 값이 HDC와 창 핸들(HWND), 그리고 창의 종류 정보 셋이었다. 16비트 시절에는 32비트짜리 lParam에 창 핸들과 종류 정보가 각각 16비트씩 합쳐져서 들어있었는데.. 32비트에 와서는 창 핸들만으로 32비트를 차지하기 때문에 기존 방식대로 메시지를 전달할 수가 없어졌던 것이다. 그래서 창의 종류 정보는 메시지 자체에 담겨 있도록 불가피하게 메시징 방식이 변경됐다.
다만, Windows 9x는 16비트 프로그램과의 호환을 위해 창 핸들의 값이 여전히 16비트 범위 내에서만 할당되었기 때문에 옛날 방식대로 메시징을 해도 “이론적으로는” 상위 word의 값이 짤려서 문제될 게 없다.
그리고 MFC는 32비트 이후에도 메시지 핸들러 함수가 16비트 시절과 동일하게 CWnd::OnCtlColor에서 처리하게 돼 있다. 즉, 하위 호환성이 유지된다. MFC의 소스를 보면 WM_CTLCOLOR???? 메시지들을 모두 CWnd::OnNTCtlColor라는 내부 함수에다 한데 모은 뒤, 특수 처리를 해서 OnCtlColor로 재전달을 하게 돼 있다.
(3) 세월이 흘러서 컴퓨터 환경이 바뀌고 Windows의 버전이 올라가면 새 메시지만 추가되는 게 아니라.. 기존 메시지가 용도나 존재감을 잃고 잉여로 전락하는 경우도 있다.
WM_QUERYDRAGICON은 최소화된 창이 아이콘 모양으로 떠 있던 Windows 3.x의 GUI 엔진의 잔재이다. 요즘으로 치면 리스트뷰 컨트롤에서의 큰 아이콘 모드와 비스무리한 동작인데.. 95/NT4부터는 저 메시지가 전혀 쓰이지 않는다.
WM_COMPACTING이라고 현재 시스템에 메모리가 부족한 상황임을 알리는 메시지도 있다. 이 메시지는 정확하게 메모리의 양이 부족해졌거나, 가상 메모리 스왑 파일 thrashing 시간이 너무 길어졌을 때 발생하는 것도 아니다.
16비트 시절에는 가상 메모리라는 게 없었기 때문에, 메모리의 단편화(leak이 아니라 fragmentation) 정도를 모니터링 하고 연속된 빈 메모리 공간을 많이 확보해 두는 걸 운영체제가 알아서 해야 했다. 응용 프로그램은 당장 사용하지 않는 메모리는 이동과 재배치가 가능하게 해 줘야 했는데.. 이렇게 메모리 재배치에 걸리는 시간이 일정 수준 이상 너무 길어진다 싶으면 이 메시지가 날아갔다. 32비트부터는 당연히 존재감이 전혀 없어졌다.
그리고.. 256색 팔레트 관련 메시지들도 21세기쯤부터는 완전히 퇴출 상태이다. Windows XP 무렵부터는 이제 안전 모드에서도 그래픽이 하이컬러 이상이지, 구닥다리 16색/256색 따위는 완전히 퇴출됐기 때문이다.
요즘 컴퓨터 기기에서 뭔가 자원이 부족하다는 메시지는 배터리 부족 정도밖에 없지 싶다.
WM_USER 이내에 시스템 메시지를 추가할 공간이 도저히 남아 있지 않다면, 이제 쓰이지 않게 된 구닥다리 메시지의 값을 재활용해야 하지 않을까?
Posted by 사무엘