Rmdir क्यों और दो अलग-अलग सिस्टम कॉल अनलिंक हैं?


10

यहाँ कुछ ऐसा है जो मुझे कुछ समय के लिए हैरान कर रहा है:

[15:40:50][/tmp]$ mkdir a
[15:40:52][/tmp]$ strace rmdir a
execve("/usr/bin/rmdir", ["rmdir", "a"], [/* 78 vars */]) = 0
brk(0)                                  = 0x11bb000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3772c3000
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=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff377286000
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\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377285000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377283000
arch_prctl(ARCH_SET_FS, 0x7ff377283740) = 0
mprotect(0x609000, 4096, PROT_READ)     = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7ff377286000, 245801)          = 0
brk(0)                                  = 0x11bb000
brk(0x11dc000)                          = 0x11dc000
brk(0)                                  = 0x11dc000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff370d5a000
close(3)                                = 0
rmdir("a")                              = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
[15:40:55][/tmp]$ touch a
[15:41:16][/tmp]$ strace rm a
execve("/usr/bin/rm", ["rm", "a"], [/* 78 vars */]) = 0
brk(0)                                  = 0xfa8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2388a000
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=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b2384d000
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\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384c000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384a000
arch_prctl(ARCH_SET_FS, 0x7f3b2384a740) = 0
mprotect(0x60d000, 4096, PROT_READ)     = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7f3b2384d000, 245801)          = 0
brk(0)                                  = 0xfa8000
brk(0xfc9000)                           = 0xfc9000
brk(0)                                  = 0xfc9000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b1d321000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 1000
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "a", W_OK)          = 0
unlinkat(AT_FDCWD, "a", 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 +++

निर्देशिका और फ़ाइलों को हटाने के लिए अलग-अलग सिस्टम कॉल क्यों हैं? ये दोनों ऑपरेशन शब्दशः अलग क्यों होंगे?


3
यहाँ उत्तर दिया गया: superuser.com/questions/430313/…
jlliagre

जवाबों:


9

निर्देशिकाएँ इस मायने में खास हैं कि एक निर्देशिका के भीतर आपके पास कई फाइलों और निर्देशिकाओं के संदर्भ हो सकते हैं, इसलिए, यदि आप मूल निर्देशिका को निकालते हैं, तो वे सभी फाइलें अपना संदर्भ बिंदु खो देती हैं जहां से उन्हें एक्सेस किया जा सकता है, प्रक्रिया के साथ भी। ऐसे मामलों के लिए, rmdir()अलग-अलग जाँचें, जो अलग हैं unlink():

  • यदि निर्देशिका खाली नहीं है। यदि कोई निर्देशिका खाली नहीं है, तो वह तब तक इसे हटा नहीं सकता है जब तक कि सामग्री unlink'घ / हटा नहीं दी जाती है।

       ENOTEMPTY
          pathname contains entries other than . and .. ; or, pathname has
          ..  as its final component.  POSIX.1-2001 also allows EEXIST for
          this condition.
    
  • यदि निर्देशिका उपयोग में है। यदि कोई प्रक्रिया उनकी वर्तमान निर्देशिका को नुकसान पहुंचाती है, तो यह समस्याओं और अपरिभाषित व्यवहारों को जन्म दे सकती है। उन्हें रोकने के लिए बेहतर है।

       EBUSY  pathname  is currently in use by the system or some process that
          prevents its removal.  On Linux this means pathname is currently
          used  as  a  mount point or is the root directory of the calling
          process.
    

unlink()इन चेकों के मामले में मौजूद नहीं है। वास्तव में, आप किसी फ़ाइल के नाम को हटा सकते हैं unlink()और वह प्रक्रिया जो अभी भी / उसके संदर्भ का उपयोग कर रही है, उसे बिना किसी समस्या के संशोधित कर सकती है। फ़ाइल तब तक मौजूद रहती है जब तक फ़ाइल डिस्क्रिप्टर मौजूद नहीं होता है, बस नई प्रक्रिया के लिए अस्वीकार्य है (जब तक कि आप नहीं जानते कि कहां खोजा जाए)। यह * NIX फ़ाइल सिस्टम के इंद्रधनुष-रंग-हाथों के जादू का हिस्सा है।

अब, वह है unlinkat()जो दोनों के रूप में व्यवहार करता है, unlink()या rmdir(2)उस पथ पर निर्भर करता है जो आप उम्मीद करते हैं।


अच्छी तरह से rm -rf "$PWD"काम करता है और वर्तमान निर्देशिका को हटा देता है। मुझे लगता है कि इसका कारण rmdir()संभवत: ऐतिहासिक है (शुरू में, निर्देशिकाओं को अनलिंक किया गया था) और rmdir (कमांड) को dir /।, Dir / .. और dir को अनलिंक किया जा रहा था, और जब इसे कर्नेल में स्थानांतरित किया गया, तो इसे होना ही था। नए syscall सभी को कम से कम एक संक्रमण अवधि या ऐसा कुछ करने के लिए)
स्टीफन चेज़लस

@ स्टीफनचेज़लस सहमत हैं, इसीलिए मैंने अनलिंकट जोड़ा।
Braiam

यदि मैं आपके उत्तर को ठीक से पढ़ता हूं, तो आप कह रहे हैं कि rmdir(dir)यदि dirउपयोग में है तो काम नहीं करता । यह कम से कम लिनक्स पर सच नहीं है, जहां rmdir(getcwd())ठीक काम करता है (बशर्ते वर्तमान निर्देशिका खाली हो)।
स्टीफन चेज़लस

@ StéphaneChazelas सही, एक प्रक्रिया या माउंट बिंदु के रूप में उपयोग किया जाता है: EBUSY pathname वर्तमान में सिस्टम या कुछ प्रक्रिया द्वारा उपयोग में है जो इसके हटाने को रोकता है । लिनक्स पर इसका अर्थ है कि पथनाम का उपयोग वर्तमान में एक माउंट बिंदु के रूप में किया जाता है या कॉलिंग प्रक्रिया की मूल निर्देशिका है।
ब्रिअम

मुझे यकीन नहीं है कि वे क्या मतलब है या कॉलिंग प्रक्रिया की जड़ निर्देशिका हैmkdir test; sudo strace -e chroot,rmdir perl -e 'chroot("test"); rmdir("test")'चिरोट और rmdir दोनों सफल दिखाते हैं।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.