libc_nonshared.a的目的是什么?

25
为什么会存在libc_nonshared.a这个库文件?它有什么作用?我在网上没有找到一个好的答案来解释它的存在。

据我所知,该文件提供了一些函数(比如statlstatfstatatexit等)。如果有人在代码中使用了其中的一个函数,那么这个函数就会从这个归档文件中链接到最终的可执行文件中。这些函数是 POSIX 标准的一部分,而且非常常见,所以我不明白为什么它们不直接放在共享库libc.so.6或者静态库libc.a中。


3
在INSTALL文件中,其描述为“该库的部分始终与应用程序和库进行静态链接,即使使用共享链接”,这解释了为什么它不应该在libc.a中,但这并没有真正回答更深层次的问题。 - Nate Eldredge
2个回答

21
在更好的机制(符号重定向或版本控制)提出之前,glibc在实现struct stat的可扩展性时犯了一个“遗留错误”。在libc_nonshared.a中定义stat-系列函数会导致结构体的版本在链接时绑定,而这里的定义会调用真正共享库中的__xstat-系列函数,它们需要一个额外的参数指示所需的结构体版本。该实现不符合标准,因为每个共享库最终都将获得自己的stat-系列函数副本,并且它们具有自己的地址,从而违反了指向相同函数的指针应该相等的要求。

libc_nonshared.a 中的函数(例如 atexit)是否也受到了不符合标准的影响?那么,更好的名称是 libc_nonstandard.a 吗? - Jeff Holt
2
我不认为你能用任何机制来解决这个问题。stat 函数族有一个很好的特性,就是取决于你调用哪个版本,_缓冲区的大小会有所不同_。因此,将指向 stat 函数的指针传递给在不同时间编译的另一个模块根本行不通。 - Joshua
这是必要的,以允许文件大小超过4GB,uid/gid超过64k,并使time_t变为64位。 - Joshua
@Joshua:这个黑客技巧早于64位的off_ttime_t,当意识到off_t需要改变大小时,符号重定向已经被发明了,而且它是一个更好的解决方案,因为它在编译时绑定而不是链接时(链接时对于静态库中的代码会产生错误的结果)。 - R.. GitHub STOP HELPING ICE
@Joshua:在glibc上,你已经会遇到使用dlopen时的一些麻烦;对于"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
显示剩余2条评论

16

这里的问题是,很久以前,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 版本和选项编译的;而这并不要求您同时升级浏览器并替换其所有插件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接