2015-09-21 2 views
0

Я хочу знать, как команда rm работает в Linux. Какие системные вызовы он вызывает? Какие файловые операции используются для выполнения этой команды?Как работает команда «rm» в Linux?

Извините, если мой вопрос выглядит тривиально, но я новичок в файловых системах Linux.

ответ

0

Он вызывает unlink(2) для удаления объекта файловой системы. Независимо от того, что происходит от него, делегируется драйверу файловой системы.

2

Вопросы, как это должно быть легко отдуваться по strace(1):

$ touch test 
$ strace rm test 
execve("/usr/bin/rm", ["rm", "test"], [/* 26 vars */]) = 0 
brk(0)         = 0xb86000 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fabf8423000 
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=45618, ...}) = 0 
mmap(NULL, 45618, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fabf8417000 
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\0\34\2\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0755, st_size=2107760, ...}) = 0 
mmap(NULL, 3932736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fabf7e42000 
mprotect(0x7fabf7ff8000, 2097152, PROT_NONE) = 0 
mmap(0x7fabf81f8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7fabf81f8000 
mmap(0x7fabf81fe000, 16960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fabf81fe000 
close(3)        = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fabf8416000 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fabf8414000 
arch_prctl(ARCH_SET_FS, 0x7fabf8414740) = 0 
mprotect(0x7fabf81f8000, 16384, PROT_READ) = 0 
mprotect(0x60d000, 4096, PROT_READ)  = 0 
mprotect(0x7fabf8424000, 4096, PROT_READ) = 0 
munmap(0x7fabf8417000, 45618)   = 0 
brk(0)         = 0xb86000 
brk(0xba7000)       = 0xba7000 
brk(0)         = 0xba7000 
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 
fstat(3, {st_mode=S_IFREG|0644, st_size=106065056, ...}) = 0 
mmap(NULL, 106065056, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fabf191b000 
close(3)        = 0 
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 
fstat(3, {st_mode=S_IFREG|0644, st_size=2502, ...}) = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fabf8422000 
read(3, "# Locale name alias data base.\n#"..., 4096) = 2502 
read(3, "", 4096)      = 0 
close(3)        = 0 
munmap(0x7fabf8422000, 4096)   = 0 
open("/usr/lib/locale/UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 
newfstatat(AT_FDCWD, "test", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0 
geteuid()        = 7026 
newfstatat(AT_FDCWD, "test", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0 
faccessat(AT_FDCWD, "test", W_OK)  = 0 
unlinkat(AT_FDCWD, "test", 0)   = 0 
lseek(0, 0, SEEK_CUR)     = -1 ESPIPE (Illegal seek) 
close(0)        = 0 
close(1)        = 0 
close(2)        = 0 
exit_group(0)       = ? 
+++ exited with 0 +++ 

Решающий вызов в моем случае это unlinkat(AT_FDCWD, "test", 0), но специфика, вероятно, зависит от архитектуры системы и rm версии.

+0

Спасибо. Это очень полезно. Я очень ценю это :) – Dalia

0

The rm команда предоставляется по номеру coreutils. rm.c является источником для драйвера программы. remove.c действительно работает. В частности, excise является то, что вы ищете:

/* Remove the file system object specified by ENT. IS_DIR specifies 
    whether it is expected to be a directory or non-directory. 
    Return RM_OK upon success, else RM_ERROR. */ 
static enum RM_status 
excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir) 
{ 
    int flag = is_dir ? AT_REMOVEDIR : 0; 
    if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0) 
    { 
     if (x->verbose) 
     { 
      printf ((is_dir 
        ? _("removed directory: %s\n") 
        : _("removed %s\n")), quote (ent->fts_path)); 
     } 
     return RM_OK; 
    } 

    /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for 
    nonexistent files. When the file is indeed missing, map that to ENOENT, 
    so that rm -f ignores it, as required. Even without -f, this is useful 
    because it makes rm print the more precise diagnostic. */ 
    if (errno == EROFS) 
    { 
     struct stat st; 
     if (! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st) 
         && errno == ENOENT)) 
     errno = EROFS; 
    } 

    if (ignorable_missing (x, errno)) 
    return RM_OK; 

    /* When failing to rmdir an unreadable directory, the typical 
    errno value is EISDIR, but that is not as useful to the user 
    as the errno value from the failed open (probably EPERM). 
    Use the earlier, more descriptive errno value. */ 
    if (ent->fts_info == FTS_DNR) 
    errno = ent->fts_errno; 
    error (0, errno, _("cannot remove %s"), quote (ent->fts_path)); 
    mark_ancestor_dirs (ent); 
    return RM_ERROR; 
} 

Как вы можете видеть, он использует unlinkat системный вызов.

0

Как вам известно, rm инструмент с открытым исходным кодом и является частью пакета core-utils. В дальнейшем вы можете прочитать реализацию rm, например, на GitHub mirror или here.

1

Развивая ответ Игнасио unlink(2) является основным системным вызовом, что он будет делать на самом деле удалить файлы, и rmdir(2) удалить каталоги, но есть и другие системные вызовы, что он делает, а в том числе:

Для полного источника реализации в OpenBSD см http://bxr.su/openbsd/bin/rm/rm.c

Смежные вопросы