centos與mv的坑-不同版本的mv底層實現異同

問題描述
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功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章