by QuickMouse (quickmouse@263.net) 2005年11月4日
真正认真考虑libnss_*的版本问题还是在前两天,我刚刚用i486的方式成功编译完glibc-2.3.5。因为是想在最小系统上试验一下这个版本的glibc,所以就要考虑要把原来的最小系统中多少.so库替换成新的版本。显然对于libnss_*的文件也纳入了考虑的范围。
以前制作最小系统,按说法都是保留/lib/libnss_SERVICE.so.X的,其中X包含1和2两个版本,分别对应glibc 2.0和glibc 2.1的NSS服务库。但是新编译出来的glibc只有libnss_SERVICE.so.2,也就是只有对应glibc 2.1的NSS库。那到底是在小系统当中替换so.2还是同时把libnss_SERVICE.so.1也删除?这就引出来一个问题:到底libnss_*的版本和工作机制是怎样的。
从man nsswitch.conf和info libc上都很难得到一个直接的结论,其上只是说通常而言.so.1是留给以前的glibc 2.0程序用的,而.so.2是新的glibc 2.1以后的接口。那按道理来说现在的程序都不会用glibc 2.0了,是否可以在系统当中不再保留libnss_SERVICE.so.1?
在glibc的FAQ当中却又明确提出:
Another problem is that older binaries that were linked statically against glibc 2.0 will reference the older nss modules (libnss_files.so.1 instead of libnss_files.so.2), so don't remove them.
也就是要保留。这就涉及到libnss_*的工作机制问题。
打开glibc源代码的nss/nsswitch.c文件可以看到如下的字段:
__stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
"libnss_"),
ni->library->name),
".so"),
__nss_shlib_revision);
ni->library->lib_handle = __libc_dlopen (shlib_name);
可见libc当中使用了dlopen去动态的加载一个libnss_*的库,显然当一个程序是动态链接到libc.so的时候,其加载的是与libc.so版本对应的libnss_*库。这样就容易理解为什么glibc的FAQ当中所提到的:如果一个较早的程序静态链接了glibc 2.0的库,也就是在编译过程当中用-static 直接将glibc 2.0的libc.a链接入程序,则会导致其程序当中dlopen那一段代码用的是glibc 2.0的接口,也就是会打开libnss_SERVICE.so.1。
所以,在一个系统当中,如果不存在有程序静态链接了旧版本的glibc 2.0库,则可以不必保留libnss_SERVICE.so.1。
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=615237