问题描述
1.Centos7.5及以下版本,使用mv命令,调用rename函数
2.Centos7.7(7.5以上的版本),使用mv命令,调用renameat2函数

分析:
1.在centos7.5系统上,mv版本与7.7上的一致时,都是8.22,------------使用mv命令,调用rename函数
猜想:与内核有关,与mv的版本没有关系
验证:通过查看mv的不同版本代码,发现无关系

2.在相同的7.7版本上,自己下载一个coreutils源码,进行编译,--------------------自己编译的,使用mv命令,调用rename函数;系统自带的,使用mv命令,调用renameat2函数
结合:http://blog.sina.com.cn/s/blog_5420e00001016r8r.html gnulib+glib+glibc+libc的不同
猜想:centos有一套自己维护的glibc,和开源的有点差别,进行了特殊处理

3.结合下面描述,
https://lwn.net/Articles/655028/ 自己写了个例子验证:

#include <fcntl.h>

#include <sys/syscall.h>
#include <linux/fs.h>

int main()
{
        const char* src = "kkk1";
        const char* dest = "kkk2";
        int rc = syscall(SYS_renameat2,AT_FDCWD,src,AT_FDCWD,dest,0);
//      printf("rc:%d\n",rc);
        return 0;
}

使用strace跟踪如下

# strace ./a.out 
execve("./a.out", ["./a.out"], 0x7ffd1537ff30 /* 22 vars */) = 0
brk(NULL)                               = 0x2417000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=22466, ...}) = 0
mmap(NULL, 22466, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fd2ed9a8000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156240, ...}) = 0
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x
mprotect(0x7fd2ed583000, 2097152, PROT_NONE) = 0
mmap(0x7fd2ed783000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DE
mmap(0x7fd2ed789000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_AN
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7
arch_prctl(ARCH_SET_FS, 0x7fd2ed9a5740) = 0
mprotect(0x7fd2ed783000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fd2ed9af000, 4096, PROT_READ) = 0
munmap(0x7fd2ed9a8000, 22466)           = 0
renameat2(AT_FDCWD, "kkk1", AT_FDCWD, "kkk2", 0) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7
write(1, "rc:0\n", 5rc:0
)                   = 5
exit_group(0)                           = ?
+++ exited with 0 +++

猜想:glibc中没有实现renameat2,直接使用syscall调用系统接口,在我的coreutils源码中,mv.c中并没有跟到syscall的调用,所以有极大的可能时gnulib的库里面centos自己做了改动,根据第二点的结合,在里面直接调用了syscall,实现的mv功能。