libc_nonshared.a
这个库文件?它有什么作用?我在网上没有找到一个好的答案来解释它的存在。
据我所知,该文件提供了一些函数(比如stat
、lstat
、fstat
、atexit
等)。如果有人在代码中使用了其中的一个函数,那么这个函数就会从这个归档文件中链接到最终的可执行文件中。这些函数是 POSIX 标准的一部分,而且非常常见,所以我不明白为什么它们不直接放在共享库libc.so.6
或者静态库libc.a
中。
libc_nonshared.a
这个库文件?它有什么作用?我在网上没有找到一个好的答案来解释它的存在。
据我所知,该文件提供了一些函数(比如stat
、lstat
、fstat
、atexit
等)。如果有人在代码中使用了其中的一个函数,那么这个函数就会从这个归档文件中链接到最终的可执行文件中。这些函数是 POSIX 标准的一部分,而且非常常见,所以我不明白为什么它们不直接放在共享库libc.so.6
或者静态库libc.a
中。
struct stat
的可扩展性时犯了一个“遗留错误”。在libc_nonshared.a
中定义stat
-系列函数会导致结构体的版本在链接时绑定,而这里的定义会调用真正共享库中的__xstat
-系列函数,它们需要一个额外的参数指示所需的结构体版本。该实现不符合标准,因为每个共享库最终都将获得自己的stat
-系列函数副本,并且它们具有自己的地址,从而违反了指向相同函数的指针应该相等的要求。libc_nonshared.a
中的函数(例如 atexit
)是否也受到了不符合标准的影响?那么,更好的名称是 libc_nonstandard.a
吗? - Jeff Holtstat
函数族有一个很好的特性,就是取决于你调用哪个版本,_缓冲区的大小会有所不同_。因此,将指向 stat
函数的指针传递给在不同时间编译的另一个模块根本行不通。 - Joshuaoff_t
和time_t
,当意识到off_t
需要改变大小时,符号重定向已经被发明了,而且它是一个更好的解决方案,因为它在编译时绑定而不是链接时(链接时对于静态库中的代码会产生错误的结果)。 - R.. GitHub STOP HELPING ICEdlopen
时的一些麻烦;对于"stat"
的dlsym
函数将会给你32位的旧版本的off_t
函数,如果它能工作的话,对于"lseek"
等也是如此。不过,这个问题完全可以通过符号重定向来解决;只需像在32位系统上做musl libc的time64转换一样,将dlsym
精确地重定向到一个进行相同映射的版本即可:https://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c?id=v1.2.2#n2293 - R.. GitHub STOP HELPING ICE这里的问题是,很久以前,struct stat
结构的成员与现在不同。特别地:
uid_t
是 2 字节(尽管我认为在从 libc5 到 glibc 的转换中已经修复了这个问题)
gid_t
是 2 字节
off_t
是 4 字节
blkcnt_t
是 4 字节
time_t
是 4 字节
此外,根本未使用 timespec
,也没有足够的空间来提供纳秒精度。
因此,所有这些都必须更改。唯一真正的解决方案是创建不同版本的 stat()
系统调用和库函数,并获得您编译的版本。也就是说,.a
文件与头文件匹配。这些事情并非一次全部更改,但我认为现在已经全部更改完毕。
你无法通过宏来解决这个问题,因为结构体名称与函数名称相同;而且一开始并没有强制要求使用 inline
,所以 glibc 不能要求每个人都使用它。
我记得曾经有一个叫做 O_LARGEFILE
的东西,用于表示您可以处理大于 4GB 的文件;否则,一切都无法正常工作。我们还曾经不得不定义像 _LARGEFILE_SOURCE
和 _LARGEFILE64_SOURCE
这样的东西,但现在这些都是自动处理的。在过去,如果您还没有准备好使用大文件支持,则不会定义这些东西,并且您将无法获得 64 位版本的 stat
结构;并且也可以在缺少新系统调用的旧内核版本上运行。我没有检查过,32 位编译是否仍然不会自动定义这些变量,但 64 位始终会。
因此,你可能会想:好吧,那就别把东西混合编译了?只需使用相同的 glibc 版本和 largefile 选择来构建最终可执行文件中的所有内容就可以了。有用过浏览器插件之类的插件吗?它们几乎保证是在不同的地方使用不同的编译器和 glibc 版本和选项编译的;而这并不要求您同时升级浏览器并替换其所有插件。