hi.
i have a problem with dlls under Win32. i've read several articles about dlls but there's one thing i don't understand (i'm at least not sure if i do understand it).
system dlls are loaded into the shared-memory-area. so each program can access them. so windows doesn't have to load the system dlls into each processe's address-space. so system dlls exist only once in virtual memory and only once in physical memory, right?
but now the "normal" dlls (non system dlls). if a program needs to access a non system dll, the dll must be loaded into its address-space (not shared-memory), right? and if another program uses the same dll at the same time, the dll must also be loaded into this porgram's address-space, right? so the dlls exist twice in virtual memory (once in each processe's address-space). but both dlls in the different address-spaces are mapped to the same physical addresses, right? so the dll exists twice in virtual memory, but only once in physical memory, is that right? so if a program modifies such a dll in its address-space, the changes will also be done to the dll in the other program's address-space, because they both actually use the same physical addresses. is that correct? if not, please correct me!
One more question:
how can i find out, how many (and which) dlls a process has loaded into its address-space? of course i could walk the import table of the .exe file to know which dlls are loaded at program startup. but what if a program does a LoadLibrary somewhen during runtime? any suggestions?
Hope someone helps me.
Thanks in advance.
I'm not sure, I think only the process that modifies the dll will be affected by the change. From the MSDN article at http://msdn.microsoft.com/library/techart/msdn_ntvmm.htm :
By default, all code pages have PAGE_READWRITE protection in Windows NT. This characteristic makes life easy for applications like debuggers. Because a debugger can write code pages, it is relatively easy to embed break points and single-step execution instructions in the code itself. Yet, this also raises another issue. What if the code being debugged was also being executed by another process simultaneously? The act of writing a break-point instruction to the code page would affect both the process being debugged and the other process. On the other hand, having duplicate copies of code, one for each instance of a process, would be redundant and wasteful.
The solution to this problem is in an optimization called Copy-on-write. I have already discussed how a prototype PTE is used for all code pages to make them capable of being shared among different processes. In addition to the shareability of code pages, Windows NT gives code pages another special characteristic that enables them to be copied, if necessary, and backed by the pagefile. Copying would only occur if and when a write ever occurred to a code page. The optimization resides in the fact that copying does not occur unless necessary, as determined by the act of writing to a page. Consequently, only pages that are written to are copied, saving precious memory resources.
But you should make a test.peter:
to know the dlls loaded by a process, in win9x, you can use Module32First() and Module32Next(), and in NT, EnumProcessModules()
Peter: Most of your understanding about DLL is correct.
system dlls are loaded into the shared-memory-area. so each program can access them. so windows doesn't have to load the system dlls into each processe's address-space. so system dlls exist only once in virtual memory and only once in physical memory, right?
Yes
but now the "normal" dlls (non system dlls). if a program needs to access a non system dll, the dll must be loaded into its address-space (not shared-memory), right?
Yes
and if another program uses the same dll at the same time, the dll must also be loaded into this porgram's address-space, right?
Yes
so the dlls exist twice in virtual memory (once in each processe's address-space). but both dlls in the different address-spaces are mapped to the same physical addresses, right?
Yes
so the dll exists twice in virtual memory, but only once in physical memory, is that right?
Yes
so if a program modifies such a dll in its address-space, the changes will also be done to the dll in the other program's address-space, because they both actually use the same physical addresses. is that correct? if not, please correct me!
Bot yes and no. It depends on the OS. Under NT/2k, when you modify the image in one process, Windows is notified of it and it creates another copy of the modified area in the process. That means, both processes share the same DLL image until one process tries to modify it. The process that modified the DLL code will still share most of the DLL image with the other process except the page(s) which it modified. This feature is called "copy-on-write".
Under win9x, copy-on-write feature is only available IF you modify the code with WriteProcessMemory.
how can i find out, how many (and which) dlls a process has loaded into its address-space? of course i could walk the import table of the .exe file to know which dlls are loaded at program startup. but what if a program does a LoadLibrary somewhen during runtime? any suggestions?
Depending on what process you want to enumerate. If you want to enumerate the modules in other process, you use toolhelp32 under win9x/2k and you can use psapi under NT. If you want to enumerate the DLLs in your own process, you can combine VirtualQuery() with GetModuleFileName() to obtain the names of the modules in your own process. I used this method in my IczDump utility.
This message was edited by Iczelion, on 6/9/2001 9:18:41 AMthanks a lot Iczelion. that helped me a lot and now i understand it :)