为什么 getpwuid 在我的系统上调用 connect?

Why is getpwuid calling connect on my system?

在 Fedora 21 上考虑以下 Linux 命令:

[0:12:57][/tmp/nss]$ echo 'main() { getpwuid(1000); }' > test.c                                          
[0:12:59][/tmp/nss]$ gcc -ggdb test.c                          
[0:13:01][/tmp/nss]$ gdb ./a.out -ex 'break main' -ex 'r' -ex 'break connect' -ex 'c' -ex 'bt' -ex 'quit'
GNU gdb (GDB) Fedora 7.8.2-38.fc21
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...

warning: ~/.gdbinit.local: No such file or directory
Reading symbols from ./a.out...done.
Breakpoint 1 at 0x40054a: file test.c, line 1.
Starting program: /tmp/nss/a.out 
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000400546  RBX: 0x0000000000000000  RBP: 0x00007FFFFFFFDB70  RSP: 0x00007FFFFFFFDB70  o d I t s Z a P c 
  RDI: 0x0000000000000001  RSI: 0x00007FFFFFFFDC58  RDX: 0x00007FFFFFFFDC68  RCX: 0x0000000000400560  RIP: 0x000000000040054A                                                    
  R8 : 0x0000003F3E1B8E80  R9 : 0x0000003F3E1B8E80  R10: 0x0000003F3E1B76A0  R11: 0x0000003F3DE1FEF0  R12: 0x0000000000400450                                                    
  R13: 0x00007FFFFFFFDC50  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                                                                                                                     
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x40054a <main+4>:   mov    edi,0x3e8
   0x40054f <main+9>:   mov    eax,0x0
   0x400554 <main+14>:  call   0x400420 <getpwuid@plt>
   0x400559 <main+19>:  pop    rbp
   0x40055a <main+20>:  ret    
   0x40055b:    nop    DWORD PTR [rax+rax*1+0x0]
   0x400560 <__libc_csu_init>:  push   r15
   0x400562 <__libc_csu_init+2>:        push   r14
-----------------------------------------------------------------------------------------------------------------------------

Breakpoint 1, main () at test.c:1
1       main() { getpwuid(1000); }
Breakpoint 2 at 0x3f3df00f70: file ../sysdeps/unix/syscall-template.S, line 81.
Continuing.
-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000020  RBX: 0x0000000000000003  RBP: 0x00007FFFFFFFD790  RSP: 0x00007FFFFFFFD688  o d I t s z a p C 
  RDI: 0x0000000000000003  RSI: 0x00007FFFFFFFD6F0  RDX: 0x000000000000006E  RCX: 0x6F732F6463736E2F  RIP: 0x0000003F3DF00F70                                                    
  R8 : 0x00001FFFFFFFF5A4  R9 : 0x0000000000000001  R10: 0x0000000000000000  R11: 0x0000000000000202  R12: 0x0000000000000013                                                    
  R13: 0x00007FFFFFFFD690  R14: 0x0000000000000007  R15: 0x00001FFFFFFFF5A4                                                                                                      
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x3f3df00f70 <connect>:      cmp    DWORD PTR [rip+0x2bbd7d],0x0        # 0x3f3e1bccf4 <__libc_multiple_threads>
   0x3f3df00f77 <connect+7>:    jne    0x3f3df00f89 <connect+25>
   0x3f3df00f79 <__connect_nocancel>:   mov    eax,0x2a
   0x3f3df00f7e <__connect_nocancel+5>: syscall 
   0x3f3df00f80 <__connect_nocancel+7>: cmp    rax,0xfffffffffffff001
   0x3f3df00f86 <__connect_nocancel+13>:        jae    0x3f3df00fb9 <connect+73>
   0x3f3df00f88 <__connect_nocancel+15>:        ret    
   0x3f3df00f89 <connect+25>:   sub    rsp,0x8
-----------------------------------------------------------------------------------------------------------------------------

Breakpoint 2, connect () at ../sysdeps/unix/syscall-template.S:81
81      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
#0  connect () at ../sysdeps/unix/syscall-template.S:81
#1  0x0000003f3df37663 in open_socket (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", keylen=keylen@entry=0x7) at nscd_helper.c:207
#2  0x0000003f3df37d1d in __nscd_get_mapping (type=type@entry=GETFDPW, key=key@entry=0x3f3df86853 "passwd", mappedp=mappedp@entry=0x3f3e1bc618 <map_handle+8>) at nscd_helper.c:293
#3  0x0000003f3df38277 in __nscd_get_map_ref (type=type@entry=GETFDPW, name=name@entry=0x3f3df86853 "passwd", mapptr=mapptr@entry=0x3f3e1bc610 <map_handle>, gc_cyclep=gc_cyclep@entry=0x7fffffffd9fc) at nscd_helper.c:443
#4  0x0000003f3df34758 in nscd_getpw_r (key=0x7fffffffda87 "1000", keylen=keylen@entry=0x5, type=type@entry=GETPWBYUID, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=0x7fffffffdb38) at nscd_getpw_r.c:95
#5  0x0000003f3df34bd9 in __nscd_getpwuid_r (uid=uid@entry=0x3e8, resultbuf=resultbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=buffer@entry=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at nscd_getpw_r.c:63
#6  0x0000003f3dec3610 in __getpwuid_r (uid=uid@entry=0x3e8, resbuf=resbuf@entry=0x3f3e1ba160 <resbuf.9883>, buffer=0x602010 "", buflen=buflen@entry=0x400, result=result@entry=0x7fffffffdb38) at ../nss/getXXbyYY_r.c:196
#7  0x0000003f3dec2ebe in getpwuid (uid=0x3e8) at ../nss/getXXbyYY.c:116
#8  0x0000000000400559 in main () at test.c:1
[0:13:04][/tmp/nss]$ cat /etc/nsswitch.conf
#
# /etc/nsswitch.conf
#
# An example Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# The entry '[NOTFOUND=return]' means that the search for an
# entry should stop if the search in the previous entry turned
# up nothing. Note that if the search failed due to some other reason
# (like no NIS server responding) then the search continues with the
# next entry.
#
# Valid entries include:
#
#       nisplus                 Use NIS+ (NIS version 3)
#       nis                     Use NIS (NIS version 2), also called YP
#       dns                     Use DNS (Domain Name Service)
#       files                   Use the local files
#       db                      Use the local database (.db) files
#       compat                  Use NIS on compat mode
#       hesiod                  Use Hesiod for user lookups
#       [NOTFOUND=return]       Stop searching if not found so far
#

# To use db, put the "db" in front of "files" for entries you want to be
# looked up first in the databases
#
# Example:
#passwd:    db files nisplus nis
#shadow:    db files nisplus nis
#group:     db files nisplus nis

passwd:     files
shadow:     files
group:      files
#initgroups: files

#hosts:     db files nisplus nis dns
hosts:      files dns mdns4_minimal myhostname

# Example - obey only what nisplus tells us...
#services:   nisplus [NOTFOUND=return] files
#networks:   nisplus [NOTFOUND=return] files
#protocols:  nisplus [NOTFOUND=return] files
#rpc:        nisplus [NOTFOUND=return] files
#ethers:     nisplus [NOTFOUND=return] files
#netmasks:   nisplus [NOTFOUND=return] files     

bootparams: nisplus [NOTFOUND=return] files

ethers:     files
netmasks:   files
networks:   files
protocols:  files
rpc:        files
services:   files

netgroup:   files

publickey:  nisplus

automount:  files
aliases:    files nisplus

为什么在 /etc/passwd 上进行简单查找就可以在此处调用 connect

nscd就是"name service cache daemon"。客户端通过套接字连接到它(使用堆栈跟踪中的 nscd* 函数),它缓存名称查找结果。将所有工作卸载到这个守护进程中而不是在每个客户端中使用特殊外壳是有意义的。