为什么我要选择 512 以外的 C# 编译器文件对齐设置?
我可以在 MS Docs 中看到如何更改 C# 编译的文件对齐方式(通过项目设置和命令行)。
我在 google 上搜索并看到文章解释 512 字节的文件对齐会减小 .dll 的大小。我用不同的文件对齐方式测试了自己,发现确实如此。
我的问题是:
为什么我想要使用不同的文件对齐方式?一定有一些场景需要这样做,否则就没有选择?
另外,它到底有什么作用? MSDN 页面谈论部分?什么是章节?
I can see in MS Docs how to change the file alignment for C# compilation (via project settings and the command line).
I have googled and seen articles explaining that a file alignment of 512 Bytes reduces the size of the .dll. I have tested myself with different file alignments and seen that, yes, it does.
My question is:
Why would I ever want to use a different file alignement? There must be scenarios where this is required or there wouldn't be the option?
Also, what does it do exactly? The MSDN pages talk about sections? What are sections?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个相当技术性的实现细节。首先,您必须了解 PE32 文件的结构,即 Windows 中 DLL 和 EXE 的文件格式。这方面的权威文章是 Matt Pietrik 的“Peering Inside the PE, A Tour of the Win32 Portable Executable File Format”。写于 17 年前,但仍然具有相关性并且可用。
/filealign 设置是指 IMAGE_OPTIONAL_HEADER.FileAlignment 字段的值。它决定了节中原始数据的对齐方式。节是文件中的一段代码或数据。在纯 .NET 程序集的情况下几乎都是数据。
文件格式与磁盘之间有着非常密切的关系。可执行映像用作 Windows 中内存映射文件的后备文件。通过将文件映射到虚拟内存地址空间来加载可执行文件。非常高效,加载 DLL 仅涉及创建该映射,而不从文件中读取实际数据。当进程尝试从节中读取字节时,这种情况会以惰性方式发生。如果尚未加载到内存中,则会产生页面错误,操作系统会从文件中读取 4096 字节到内存中。最大的优点是您无需为不使用的数据或代码付费。这也是第一次阅读[属性]时成本昂贵的原因。
文件对齐的相关性是各部分中的原始数据如何排列。大多数包含机器代码的现代可执行文件都使用 4096 字节的对齐方式,即虚拟内存页面的大小。这与包含托管代码的程序集关系不大,IL 只是数据。这使得使用较小的对齐方式是有意义的,这种对齐方式浪费的空间更少。 512 字节(不是千字节)是一个令人高兴的数字,它是 PE32 格式中允许的最小值。
我能想到的将选项添加到 UI 的唯一可能原因是,与其他编译器相比,C# 编译器的编译选项非常少。 “其他”是生成本机代码的编译器。所以这个选项就在那里,因为编译器有这个选项。 [属性] 涵盖了许多调整,很好地使编译器命令行变得简短而敏捷。但是文件对齐没有属性,需要在生成文件之前知道,属性就来不及了。
相反的例子是C++编译器和链接器,IDE提供十九个属性页来设置它们。但还没有涵盖所有,真正晦涩难懂的还得在“命令行”选项页中设置。
That's a rather technical implementation detail. To get started, you first have to understand the structure of a PE32 file, the file format for DLLs and EXEs in Windows. The canonical article for that is Matt Pietrik's "Peering Inside the PE, A Tour of the Win32 Portable Executable File Format". Written 17 years ago but still relevant and available.
The /filealign setting refers to the value of IMAGE_OPTIONAL_HEADER.FileAlignment field. It determines how the raw data in a section is aligned. A section is a chunk of code or data in the file. Almost exclusively data in the case of pure .NET assemblies.
There is a very close relationship between the file format and the disk. An executable image is used as the backing file of a Memory Mapped File in Windows. Executables are loaded by mapping the file into the virtual memory address space. Very efficient, loading a DLL only involves creating that mapping, no actual data is read from the file. That happens in a lazy fashion when the process tries to read a byte from a section. If it isn't loaded into memory yet, that produces a page fault and the operating system reads 4096 bytes from the file into memory. The big advantage is that you don't pay for data or code that you don't use. Also the reason that reading [attributes] is expensive when you read it the first time.
The relevance of the file alignment is how the raw data in the sections line up. Most modern executables that contain machine code use an alignment of 4096 bytes, the size of a virtual memory page. That isn't very relevant for assemblies containing managed code, IL is just data. Which would make it sense to use a smaller alignment, one that wastes less space. 512 bytes (not kilobytes) is a happy number there, it is the smallest value allowed in the PE32 format.
The only possible reason I can think of for adding the option to the UI at all is that the C# compiler has very few compile options compared to other compilers. "Other" being compilers that generate native code. So the option is there because the compiler has the option. A lot of the tweaks are covered by [attributes], nicely making the compiler command line short and snappy. But no attribute for the file alignment, it needs to be known before generating the file, an attribute would be too late.
The opposite example is the C++ compiler and linker, the IDE offers nineteen property pages to set them. But still not covering them all, the really obscure ones have to be set in the "Command Line" option page.