strace 分析 Linux 版的 getaddrinfo

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1075355798/article/details/86665445

为啥说是 Linux 版的 getaddrinfo,因为这世界上还有一个安卓的。而且这一不注意就搅混了。毕竟Linux版本使用的是 glibc 库,而安卓版本用的是 bionic 库。两个不同的 C 库,两个不同的实现,原理相似,基因相似,实质不同。

/ # strace /data/getaddinfo localhost
execve("/data/getaddinfo", ["/data/getaddinfo", "localhost"], [/* 24 vars */]) = 0
brk(0)                                  = 0xb74000
uname({sys="Linux", node="localhost", ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f02000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/v7l/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/v7l/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/v7l", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/tls/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/tls", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/vendor/lib/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/v7l/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/v7l/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/v7l", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/vendor/lib/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/vendor/lib/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/neon", 0xbea1b2e0)  = -1 ENOENT (No such file or directory)
open("/vendor/lib/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib/vfp", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/vendor/lib/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/vendor/lib", {st_mode=S_IFDIR|0755, st_size=2456, ...}) = 0
open("/system/lib/tls/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/v7l/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/v7l/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/v7l", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/tls/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/tls", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/system/lib/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/v7l/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/v7l/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/v7l", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/system/lib/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/system/lib/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/neon", 0xbea1b2e0)  = -1 ENOENT (No such file or directory)
open("/system/lib/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib/vfp", 0xbea1b2e0)   = -1 ENOENT (No such file or directory)
open("/system/lib/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/system/lib", {st_mode=S_IFDIR|0755, st_size=13632, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY)      = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/neon", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l/vfp", 0xbea1b2e0)  = -1 ENOENT (No such file or directory)
open("/lib/tls/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v7l", 0xbea1b2e0)      = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/lib/tls/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/neon", 0xbea1b2e0)     = -1 ENOENT (No such file or directory)
open("/lib/tls/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/vfp", 0xbea1b2e0)      = -1 ENOENT (No such file or directory)
open("/lib/tls/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0xbea1b2e0)          = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon/vfp", 0xbea1b2e0) = -1 ENOENT (No such file or directory)
open("/lib/v7l/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/neon", 0xbea1b2e0)     = -1 ENOENT (No such file or directory)
open("/lib/v7l/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l/vfp", 0xbea1b2e0)      = -1 ENOENT (No such file or directory)
open("/lib/v7l/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v7l", 0xbea1b2e0)          = -1 ENOENT (No such file or directory)
open("/lib/neon/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/neon/vfp", 0xbea1b2e0)     = -1 ENOENT (No such file or directory)
open("/lib/neon/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/neon", 0xbea1b2e0)         = -1 ENOENT (No such file or directory)
open("/lib/vfp/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/vfp", 0xbea1b2e0)          = -1 ENOENT (No such file or directory)
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\0\0iI4\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0777, st_size=118728, ...}) = 0
mmap2(0x49690000, 115268, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x49690000
mmap2(0x496ac000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c) = 0x496ac000
close(3)                                = 0
open("/vendor/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/system/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0鳿2LI4\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0777, st_size=1230676, ...}) = 0
mmap2(0x494a8000, 1263968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x494a8000
mprotect(0x495d0000, 28672, PROT_NONE)  = 0
mmap2(0x495d7000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x127) = 0x495d7000
mmap2(0x495db000, 6496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x495db000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f01000
set_tls(0xb6f016d0, 0xb6f01db8, 0x27660, 0xb6f016d0, 0x494a0050) = 0
mprotect(0x495d7000, 8192, PROT_READ)   = 0
mprotect(0x4949f000, 4096, PROT_READ)   = 0
getpid()                                = 717
brk(0)                                  = 0xb74000
brk(0xb95000)                           = 0xb95000
open("/etc/resolv.conf", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0777, st_size=20, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f00000
read(3, "namespace 127.0.0.1\n", 4096)  = 20
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb6f00000, 4096)                = 0
uname({sys="Linux", node="localhost", ...}) = 0
socket(PF_UNIX, SOCK_STREAM|0x80800 /* SOCK_??? */, 0) = 3
connect(3, {sa_family=AF_UNIX, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(PF_UNIX, SOCK_STREAM|0x80800 /* SOCK_??? */, 0) = 3
connect(3, {sa_family=AF_UNIX, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/nsswitch.conf", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/vendor/lib/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/system/lib/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_dns.so.2", O_RDONLY)  = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0P\f\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0777, st_size=35641, ...}) = 0
mmap2(NULL, 57544, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6ef2000
mprotect(0xb6ef8000, 28672, PROT_NONE)  = 0
mmap2(0xb6eff000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5) = 0xb6eff000
close(3)                                = 0
open("/vendor/lib/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/system/lib/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libresolv.so.2", O_RDONLY)   = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/neon/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/neon/vfp", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/neon/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/neon", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l/vfp", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/v7l/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/v7l", 0xbea1aa60)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/neon/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/neon/vfp", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/neon/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/neon", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls/vfp", 0xbea1aa60)  = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/tls", 0xbea1aa60)      = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/neon/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/neon/vfp", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/neon/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/neon", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l/vfp", 0xbea1aa60)  = -1 ENOENT (No such file or directory)
open("/usr/lib/v7l/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/v7l", 0xbea1aa60)      = -1 ENOENT (No such file or directory)
open("/usr/lib/neon/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/neon/vfp", 0xbea1aa60) = -1 ENOENT (No such file or directory)
open("/usr/lib/neon/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/neon", 0xbea1aa60)     = -1 ENOENT (No such file or directory)
open("/usr/lib/vfp/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib/vfp", 0xbea1aa60)      = -1 ENOENT (No such file or directory)
open("/usr/lib/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/usr/lib", 0xbea1aa60)          = -1 ENOENT (No such file or directory)
munmap(0xb6ef2000, 57544)               = 0
open("/vendor/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/system/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_files.so.2", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0衆32\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0777, st_size=75075, ...}) = 0
mmap2(NULL, 86988, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6eeb000
mprotect(0xb6ef8000, 28672, PROT_NONE)  = 0
mmap2(0xb6eff000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xc) = 0xb6eff000
close(3)                                = 0
mprotect(0xb6eff000, 4096, PROT_READ)   = 0
open("/etc/host.conf", O_RDONLY)        = 3
fstat64(3, {st_mode=S_IFREG|0777, st_size=151, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6eea000
read(3, "#The \"order\" line is only used b"..., 4096) = 151
read(3, "", 4096)                       = 0
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb6eea000, 4096)                = 0
open("/etc/hosts", O_RDONLY)            = 3
fcntl64(3, F_GETFD)                     = 0x1 (flags FD_CLOEXEC)
fstat64(3, {st_mode=S_IFREG|0777, st_size=78, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6eea000
read(3, "127.0.0.1\t\t    localhost\n120.79."..., 4096) = 78
read(3, "", 4096)                       = 0
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb6eea000, 4096)                = 0
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 4), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6eea000
write(1, "127.0.0.1\n", 10127.0.0.1
)             = 10
exit_group(0)    

 仔细分析上面的 strace 信息, 这里开始进入系统调用。:

strace /data/getaddinfo localhost
execve("/data/getaddinfo", ["/data/getaddinfo", "localhost"], [/* 24 vars */]) = 0
brk(0)                                  = 0xb74000
uname({sys="Linux", node="localhost", ...}) = 0

找 C 库,如果是安卓设备,so 库一般放置在 /system/lib 下的,Linux则一般放置在  /lib  下的:

open("/lib/libc.so.6", O_RDONLY)        = 3

open("/lib/libnss_files.so.2", O_RDONLY) = 3

open("/lib/libnss_dns.so.2", O_RDONLY)  = -1 ENOENT (No such file or directory)

读网络配置文件:

open("/etc/resolv.conf", O_RDONLY)      = 3

open("/etc/nsswitch.conf", O_RDONLY)    = -1 ENOENT (No such file or directory)

open("/etc/host.conf", O_RDONLY)        = 3

open("/etc/hosts", O_RDONLY)            = 3

猜你喜欢

转载自blog.csdn.net/q1075355798/article/details/86665445