Linux'taki her şey bir dosyaysa dizinler nelerdir?


17

Yeni başlayanlar sıklıkla "Her şey Linux / Unix'te bir dosyadır" ifadesini duyar. Ancak, o zaman dizinler nelerdir? Dosyalardan farkı nedir?

Yanıtlar:


22

Not: başlangıçta bu, komuttaki geçerli dizin neden lskendisine bağlı olarak tanımlandı? ancak bunun kendi başına ayakta kalmayı hak eden bir konu olduğunu ve dolayısıyla bu soru-cevap olduğunu hissettim .

Unix / Linux dosya sistemini ve dosyalarını anlama: Her şey bir inode'dur

Esasen, bir dizin yalnızca girişlerin listesini ve kimliklerini içeren özel bir dosyadır.

Tartışmaya başlamadan önce, birkaç terim arasında bir ayrım yapmak ve dizinlerin ve dosyaların gerçekte neyi temsil ettiğini anlamak önemlidir. Unix / Linux için "Her şey bir dosyadır" ifadesini duymuş olabilirsiniz. Kullanıcıların genellikle dosya olarak anladıkları şey şudur: /etc/passwd- Yolu ve adı olan bir nesne. Gerçekte, bir ad (dizin veya dosya ya da başka bir şey olsun) yalnızca bir metin dizesidir - gerçek nesnenin bir özelliği. Bu nesneye inode veya I numarası denir ve inode tablosundaki diskte depolanır. Açık programların inode tabloları da vardır, ancak şimdilik bu bizim endişemiz değil.

Unix'in bir dizin kavramı Ken Thompson'ın 1989 röportajında ​​belirttiği gibidir :

... Ve sonra bu dosyalardan bazıları, isim ve I-numarası içeren dizinlerdi.

Dennis Ritchie'nin 1972'deki konuşmasından ilginç bir gözlem yapılabilir .

"... dizini aslında bir dosyadan başka bir şey değildir, ancak içeriği sistem tarafından denetlenir ve içeriği diğer dosyaların adlarıdır. (Bir dizine bazen diğer sistemlerde katalog denir.)"

... ama konuşmanın hiçbir yerinde inode'dan bahsedilmiyor. Ancak, 1971 manuel üzerindeki format of directoriesdevletler:

Bir dosyanın bir dizin olması, i-düğüm girişinin bayrak sözcüğünde bir bit ile belirtilir.

Dizin girişleri 10 bayt uzunluğundadır. İlk sözcük, girdi değilse temsil edilen dosyanın i - düğümüdür, sıfır değilse; sıfırsa, giriş boştur.

Başından beri orada.

Dizin ve inode eşleştirme ayrıca Dizin yapıları UNIX dosya sisteminde nasıl saklanır? . bir dizinin kendisi bir veri yapısıdır, daha spesifik olarak: bu nesneler (izinler, tür, sahip, boyut vb.) ile ilgili listeleri gösteren nesnelerin (dosyalar ve inode numaraları) bir listesi. Böylece her dizin kendi inode numarasını ve daha sonra dosya adlarını ve inode numaralarını içerir. En ünlüsü , /dizin olan inode # 2'dir . (Bununla birlikte /devve /runsanal dosya sistemleri olduğuna dikkat edin , bu yüzden dosya sistemleri için kök klasörler olduklarından, ayrıca inode 2'ye sahiptir; yani, bir inode kendi dosyasında benzersizdir, ancak birden fazla dosya sistemi eklenmişse, benzersiz olmayan inotlarınız vardır). bağlantılı sorudan ödünç alınan diyagram muhtemelen daha kısa ve öz bir şekilde açıklıyor:

Rehber-inode-Blok

Inode'da depolanan tüm bu bilgilere stat()Linux'a göre sistem çağrıları yoluyla erişilebilir man 7 inode:

Her dosya, dosya hakkında meta veriler içeren bir inode içerir. Bir uygulama, bu meta verileri bir stat yapısı döndüren stat (2) (veya ilgili çağrılar) veya statx yapısı döndüren statx (2) kullanarak alabilir.

Sadece inode numarasını bilen bir dosyaya erişmek mümkün müdür ( ref1 , ref2 )? Bazı Unix uygulamalarında mümkündür ancak izin ve erişim denetimlerini atlar, bu nedenle Linux'ta uygulanmaz ve find <DIR> -inum 1234bir dosya adı ve karşılık gelen inode almak için dosya sistemi ağacını ( örneğin aracılığıyla ) geçmeniz gerekir .

Kaynak kodu düzeyinde, Linux çekirdek kaynağında tanımlanır ve ayrıca ext3 ve ext4 dosya sistemleri de dahil olmak üzere Unix / Linux işletim sistemlerinde çalışan birçok dosya sistemi tarafından kabul edilir (Ubuntu varsayılanı). İlginç olan şey: verilerin sadece bilgi blokları olmasıyla, Linux aslında bir inodeun bir pipe ( inode->i_pipe) olup olmadığını belirleyebilen inode_init_always işlevine sahiptir . Evet, soketler ve borular teknik olarak da dosyalardır - anonim dosyalar, diskte dosya adı olmayabilir. FIFO'lar ve Unix-Domain yuvalarının dosya sisteminde dosya adları vardır.

Verilerin kendisi benzersiz olabilir, ancak inode numaraları benzersiz değildir. Eğer foobar olarak adlandırılan foo'ya zor bir bağımız varsa, bu da inode 123'ü gösterecektir. Bu inodeun kendisi, o inode tarafından hangi gerçek disk alanı bloklarının işgal edildiğine dair bilgi içerir. Ve teknik .olarak dizin dosya adına nasıl bağlanabilirsiniz. Neredeyse: Linux'taki dizinlere sabit bağlantı oluşturamazsınız , ancak dosya sistemleri dizinlere çok disiplinli bir şekilde sabit bağlantılara izin verebilir, bu da sadece .ve ..sabit bağlantılara sahip olmayı kısıtlar .

Dizin Ağacı

Dosya sistemleri, ağaç veri yapılarından biri olarak bir dizin ağacı uygular. Özellikle,

  • ext3 ve ext4 HTree kullanıyor
  • xfs B + Ağacı kullanır
  • zfs karma ağacı kullanır

Buradaki kilit nokta, dizinlerin kendilerinin bir ağaçtaki düğümler ve alt dizinlerin alt düğümler olması ve her çocuğun ana düğüme geri bağlanmasıdır. Bu nedenle, bir dizin bağlantısı için çıplak bir dizin (dizin adına /home/example/bağlantı ve kendine bağlantı) için inode sayısı minimum 2'dir /home/example/.ve her ek alt dizin fazladan bir bağlantı / düğümdür:

# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

Bulunan diyagram Ian D. Allen'in ders sayfası gösterileri basitleştirilmiş çok açık şeması:

WRONG - names on things      RIGHT - names above things
=======================      ==========================

    R O O T            --->         [etc,bin,home]   <-- ROOT directory
   /   |   \                         /    |      \
etc   bin   home       --->  [passwd]  [ls,rm]  [abcd0001]
 |   /   \    \                 |      /    \       |
 |  ls   rm  abcd0001  --->     |  <data>  <data>  [.bashrc]
 |               |              |                   |
passwd       .bashrc   --->  <data>                <data>

SAĞ diyagramda yanlış olan tek şey, dosyaların teknik olarak dizin ağacının kendisinde olduğu düşünülmemesidir: Dosya eklemenin bağlantı sayısı üzerinde hiçbir etkisi yoktur:

$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4

Dizinlere dosyaymış gibi erişme

Linus Torvalds'ı alıntılamak için :

"Her şey bir dosyadır" ile bütün mesele rastgele bir dosya isminizin olmadığı anlamına gelir (gerçekten, soketler ve borular "dosya" ve "dosya adı" nın birbiriyle hiçbir ilgisi olmadığını gösterir), ama ortak kullanabileceğiniz gerçeği farklı şeyler üzerinde çalışmak için araçlar.

Bir dizinin yalnızca bir dosyanın özel bir durumu olduğunu göz önünde bulundurursak, doğal olarak, bunları normal dosyalara benzer şekilde açmamıza / okumamıza / yazmamıza / kapatmamıza izin veren API'ler olmalıdır .

İşte bu noktada dirent.hC kütüphanesi devreye giriyor, bu direntda man 3 readdir dizininde bulabileceğiniz yapıyı tanımlıyor :

   struct dirent {
       ino_t          d_ino;       /* Inode number */
       off_t          d_off;       /* Not an offset; see below */
       unsigned short d_reclen;    /* Length of this record */
       unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
       char           d_name[256]; /* Null-terminated filename */
   };

Bu nedenle, C kodunuzda tanımlamanız gerekir struct dirent *entry_pve ile bir dizin açıp opendir()okumaya başladığımızda readdir(), her öğeyi bu entry_pyapıya depolayacağız . Elbette, her öğe direntyukarıda gösterilen şablonda tanımlanan alanları içerecektir .

Bunun nasıl çalıştığına dair pratik örnek , geçerli çalışma dizinindeki dosyaları ve bunların inode numaralarını listeleme konusundaki cevabımda bulunabilir .

O Not POSIX fdopen manuel "[t] o dizin nokta için girdileri ve dot-dot isteğe bağlıdır" diye devletler ve readdir manuel devletler struct dirent sadece olması gerekir d_nameve d_inoalanlar.

Dizinlere "yazma" ile ilgili not: bir dizine yazmak, girdilerin "listesini" değiştiriyor. Bu nedenle, bir dosya oluşturma veya kaldırma doğrudan dizin yazma izinleriyle ilişkilidir ve dosya ekleme / kaldırma, söz konusu dizine yazma işlemidir.


2
Soketler dosyaları kabul etmeyi reddediyorum;) "Her şeye bir dosya olarak erişilebilir" daha doğru olur mu?
Rinzwind

@Rinzwind "Her şeye bir dosya olarak erişilebilir" ifadesi doğrudur. Düzenli dosyalar var open()ve read()prizler var connect()ve read()de. Daha doğru olan şey, "dosya" nın diskte veya bellekte depolanan "veri" nin gerçekten organize edilmiş olması ve bazı dosyaların anonim olmasıdır - dosya adı yoktur. Genellikle kullanıcılar dosyaları masaüstündeki bu simge açısından düşünürler, ancak var olan tek şey bu değildir. Ayrıca bkz. Unix.stackexchange.com/a/116616/85039
Sergiy Kolodyazhnyy

Soru daha çok bir dizinin bir dosya olup olmadığıyla ilgiliydi. Ve budur. Soketler, FIFO Named Pipes ile birlikte neredeyse ayrı bir soru olabilir.
WinEunuuchs2Unix

Şimdiye kadar borular hakkında bir cevap aldım: askubuntu.com/a/1074550/295286 Belki FIFO'lar sıraya girecek
Sergiy Kolodyazhnyy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.