삽질의 현장/- 윈도우 시스템

#033_WIndow_System_DLL (2)

shovelman 2015. 9. 30. 21:33


안녕하세요 삽잡이입니다.


이번 시간에는 지난시간에 이어서 DLL의 기능에 대해서 알아보려고합니다.


서버에서는 DLL기능을 클라이언트에 가져다 쓰는데 두가지 기능을 제공한다고 했습니다.

바로, 명시적인 DLL 연결 (explicit 연결)과 암묵적인 DLL 연결(implicit 연결)입니다.


DLL이 먼저 만들어지게 되지 않습니까...

존재하지 않는 기능을 먼저 쓸 수 없으니까 말입니다...

서버와 클라이언트중 서버가 먼저 만들어집니다. 당연한 말이지요...


DLL을 미리 만들어서 줘야 쓸 수 있는데,

그 만든 것을 클라이언트에게 주어야하는 요소가 명시적 연결에서는 두개만 주면됩니다.

서버가 클라이언트에게 주어야할 요소는 바로 'DLL', '도움말' 입니다.


암묵적인 DLL 연결은 첫번째로 DLL, 그리고 lib, 헤더 파일의 목록, 도움말

이러게 네가지를 줘야합니다.


명시적인 연결에서는 상식적으로 도움말은 우리가 만들어서 제공한다고 하면

주어야할 것은 DLL밖에 없습니다.

암묵적인 연결을 위해서는 lib와 헤더가 부가적으로 더 필요한 것이구요...


왜 이런 현상이 발생할까요? 명시적 연결은 왜 명시적일까요?

클라이언트에 진짜로 DLL에 대한 어떤 정보도 포함시키지 않기 떄문입니다.

단, 내부적으로 DLL이 무엇인지, 내가 쓰고자하는 정보가 무엇인지만 알고 있습니다.

모든 것을 실행 시간에 판단하는 것이지요...


명시적인 연결에서 가장 핵심적인 함수는

LoadLibrary와 FreeLibrary, GetProcAddress 함수입니다...



 




요렇게들 생겨먹었습니다...


이 세개의 함수만 알면 DLL에 어떤 정보도 알지 않아도 됩니다.

실행시간에 모든 것을 찾아볼 수 있기 때문이지요...



그러면 암묵적인 연결을 위해서 필요한 것은 무엇일까요?

DLL것을 사용한지, 내 함수를 사용한지는 전혀 알 필요가 없습니다.

왜냐하면 암묵적인 연결에서는 내가 모든 거을 포함하고 있기 때문이지요...


지금까지 API를 공부하면서

CreateWindow, SendMessage 같은 함수들을 모두 내 것 처럼 쓰지 않았습니까...

다 DLL에 들어있는데... DLL에 들어있는 것 조차도 몰랐었습니다...


그럼 생각해봅시다...

DLL에 있는 것을 나도 모르게 내 것처럼 사용하려면

내부에서 자동으로 Laod하고 실제 함수를 호출해주고 그 함수를 다 사용했을때

자동으로 Unload되는 기능이 있어야하지 않겠습니까...


예를들어 CreateWindow함수를 사용하려면 그 선언 정보인 헤더가 있어야하는데,

우리가 한 행위는 #include <Windows.h> 밖에 없습니다.


곧 우리는 지금까지 암묵적으로 DLL 연결이라는 방식을 사용하여

APIU 라이브러리들을 사용했던 것입니다.

우리가 DLL 함수인지 조차 모르고 말입니다...


lib 파일은 왜 필요할까요?

암묵적인 연결은 lib 때문에 실질적으로 그런 기능들이 가능했던 것입니다.


DLL에 실제 CreateWindow 함수가 있고,

lib에는 CreateWindow의 Stub이라는 것이 있는데,

여기서 Stub이란 우리말로 '진짜 처럼 행동하는 가짜, 짜가, 껍데기'를 뜻합니다.

아무튼... CreateWindow Stub을 호출하면 DLL이 로드하고 CreateWindow를 호출하게 되는 것입니다.


lib는 암묵적인 연결을 위해서 필요한 것입니다.

진짜 기능을 가지기 위한 껍데기를 가지고 있으니깐 말입니다...


DLL이 10m바이트라면 lib는 stub 코드 밖에 없어서 몇 k바이트도 안합니다...

아무튼... 이것이 바로 DLL의 개념입니다...


Main.cpp를 컴파일해서 obj파일이 만들어지고,

OS의 lib를 링크과정을 같이 하게 되면 App.exe가 만들어 지게 됩니다.

App.exe 안에는 main.obj와 os가제공하는 lib 파일이 같이 들어있겠지요...

그리고 lib에는 stub이 들어가있구요...

이 안에는 DLL을 로드시키고 실제 함수가 아닌 가짜함수들의 목록이 즐비합니다.


실행시키게 되면, 매핑되어 물리 메모리에 뜨게 됩니다.

그리고, CreateWindow를 호출하면 stub이 호출되는 것이구요...

lib에는 OS의 DLL을 로드하는 기능이 있는데, 

물리 메모리에 OS가 제공하는 DLL이 로드되고 거기에서 실제 CreateWindow를 호출하게 되는 것입니다.

즉, 내 것처럼 호출이 되는 것이지요...

그 기능이 lib에 들어있다는 것이구요!


정리하자면, lib 파일의 핵심 기능은 로드, 언로드, 실제 함수를 호출하는 기능입니다.

헤더는 클라이언트를 위해 존재하지요...

DLL은 외부 프로그램이 사용하는 기능과 DLL 내에서 사용하는 기능이 분리됩니다.

따라서, 외부에서 사용하는 것은 해당 함수에서 외부에서 사용할 수 있다는 표시를 해줘야합니다.

표시를 안하면 사용을 못하지요...


그래서 extren "C" __declspec(dllexport) 와 같은 키워드를 명시해줘야합니다.



이런식으로 말입니다...

이 표시가 DLL 외부에서도 사용할 수 있는 함수라고 명시를 해주는 것입니다.


extern "C"는 C 스타일로 함수를 컴파일 시키겠다는 뜻인데,

C++로 하지 안흔 이유는 C++로 할 경우 C++밖에 못쓰기 때문입니다.

C스타일로 컴파일을 해놓으면 다른 언어, C++에서도 쓸 수 있게 되는데 말입니다...

단, C++만의 문법은 안됩ㄴ디ㅏ.


그리고 __declspec(dllexport)는 노출 시키겠다는 뜻을 말합니다.

외부로 노출하겠다 이정도 이지요...


헤더는 외부의 라이브러리를 받지요...

따라서 extern "C" __declspec(dllimport)와 같이 사용합니다.



받아들이곘다는 뜻이지요...

클라이언트 입작에서는 export는 공개하는 것이고 import는 받아들이기 위한 뜻이라는 것입니다.

헤더를 클라이언트가 가져다 쓰는것이니 import 시키는 것이지요...

헤더는 클라이언트가 가져다 씁니다.


지금 우리는 암묵적인 연결을 쓰는 클라이언트를 살펴봤습니다...


암묵적인 연결은 Stub코드가 exe에 포함되는 것입니다.

따라서 exe파일과 dll의 위치가 같아야합니다.


명시적으로 DLL을 연결하면 사용하는 코드가 복잡할 뿐 DLL에 대한 정보도 없이

이름만 알게 되면 끝납니다. 부가적인 작업이 필요 없이 말입니다...


그리고 class는 명시적인 방법을 사용할 수 없습니다.

오직 암묵적인 방법만 사용이 가능합니다...


이상으로 dll에 대한 소개를 마치도록 하곘습니다.


이상 삽잡이였습니다!



'삽질의 현장 > - 윈도우 시스템' 카테고리의 다른 글

#033_WIndow_System_DLL (3)  (0) 2015.10.01
#032_WIndow_System_DLL (1)  (0) 2015.09.30
#031_WIndow_System_힙(Heap)  (0) 2015.09.30
#030_WIndow_System_메모리 맵 파일  (0) 2015.09.30
#029_WIndow_System_IPC_파이프(2)  (0) 2015.09.30