4

将 /TSAWARE 链接器标志添加到我的一个项目 (Visual Studio 6) 后,我惊讶地发现 PE 文件 (.idata) 中有一个新部分。如果我不设置标志,导入将合并到 .rdata 中。

为了说明“问题”,我们从一个简单的控制台程序开始:

#include <stdio.h>
int main() 
{
    printf("hello world\n");
    return 0;
}

并编译:cl /Og /O1 /GF /WX /c main.c

然后链接到

  • link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:a.exe main.obj
  • link /MACHINE:IX86 /SUBSYSTEM:CONSOLE /RELEASE /OUT:b.exe /TSAWARE main.obj

让我们比较一下 dumpbin 的输出:

Dump of file a.exe

File Type: EXECUTABLE IMAGE

  Summary

        4000 .data
        1000 .rdata
        5000 .text

Dump of file b.exe

File Type: EXECUTABLE IMAGE

  Summary

        4000 .data
        1000 .idata
        1000 .rdata
        5000 .text

所以由于某种原因,链接器决定不能合并导入。

但是如果我们editbin /TSAWARE a.exe只运行PE可选头中的DLL特性字段就会改变。

谁能给我解释一下?这是链接器中的错误还是editbin更改的可执行文件最终无法在某些系统上运行?

4

2 回答 2

5

只是一个猜测:在终端服务器系统上,您希望图像尽可能多地写入几页。如果对应于映像的内存页面未被修改,则可以将物理 RAM 的单个页面映射到使用该映像的 eash 会话中。如果修改了图像中的页面,系统必须对所有会话中的页面的每个实例执行写时复制操作,并使用不同的物理内存块来表示每个会话中的页面。

由于如果必须重新定位正在导入的 DLL,则通常需要修复图像的导入,因此保存导入的页面经常会被修改,因此无法参与会话之间的共享。如果链接器将导入与通常未修改的其他数据合并,则可能会不必要地增加写时复制页的数量。

这可能是一种优化,有助于减少跨会话复制的页面数量。

就像我说的那样——这纯粹是一个猜测。

于 2009-08-29T21:40:03.800 回答
1

@WarrenP 的评论是正确的。根据MSDN 文档

/TSAWARE 选项在程序映像的可选标头中的 IMAGE_OPTIONAL_HEADER DllCharacteristics 字段中设置一个标志。设置此标志时,终端服务器不会对应用程序进行某些更改。

当应用程序不支持终端服务器(也称为旧应用程序)时,终端服务器会对旧应用程序进行某些修改,以使其在多用户环境中正常工作。例如,终端服务器会创建一个虚拟的 Windows 文件夹,这样每个用户都会得到一个 Windows 文件夹,而不是获取系统的 Windows 目录。这使用户可以访问他们自己的 INI 文件。此外,终端服务器对旧应用程序的注册表进行了一些调整。这些修改会减慢终端服务器上旧应用程序的加载速度。

如果应用程序可以识别终端服务器,则它既不能依赖 INI 文件,也不能在安装过​​程中写入 HKEY_CURRENT_USER 注册表。

如果您使用 /TSAWARE 并且您的应用程序仍然使用 INI 文件,则这些文件将由系统的所有用户共享。如果这是可以接受的,您仍然可以将您的应用程序与 /TSAWARE 链接;否则你需要使用 /TSAWARE:NO。

此处仅暗示的一件事是,仅对不支持 TS 的进程启用影子键。

于 2012-03-13T12:45:56.240 回答