Basit terimlerle açıklanan dosya tanımlayıcıları nelerdir?


383
  1. Vikipedi'lere kıyasla dosya tanımlayıcılarının daha basitleştirilmiş açıklaması ne olabilir? Neden gerekli? Örneğin, kabuk süreçlerini örnek olarak alın ve bunun için nasıl uygulanır?

  2. Bir işlem tablosu birden fazla dosya tanımlayıcı içeriyor mu? Evet ise, neden?


3
Stdin stdout stderr vb. Tarayıcı işlemi aç demek gibi bir örneğim var ve html'imi görüntülemek için bazı geçici dosyalar açtı. Süreç aynı fd'yi okumak / yazmak için mi kullanıyor? Ayrıca süreç tablosu ....... fd0 pointer fd1 pointer fd2 pointer gibi girişleri vardır ..... bu tüm bu dosyaların RAM olduğu anlamına mı geliyor? Neden başka göstericiler?
Nishant

43
Bir dosyayı açtığınızda, OS bu dosyaya bir akış oluşturur ve bu akışı açık dosyaya bağlar, tanımlayıcı aslında bu akışı temsil eder. Benzer şekilde, işletim sistemi tarafından oluşturulan bazı varsayılan akışlar vardır. Bu akışlar dosyalar yerine terminalinize bağlanır. Terminalde bir şey yazdığınızda bu stdin akışı ve işletim sistemine gider. Terminalde "ls" komutu yazdığınızda, işletim sistemi çıkışı stdout akışına yazar. stdout akışı monitör terminalinize bağlanır, böylece çıktıyı orada görebilirsiniz.
Tayyab

1
Tarayıcı örneği ile ilgili olarak, tarayıcının dosyaları açık tutması gerekli değildir. Tarayıcının uygulanmasına bağlıdır, ancak çoğu durumda tarayıcı geçici bir dosya açar, dosyayı yazar ve dosyayı kapatır, bu nedenle web sayfası açık olsa bile dosyanın açılması gerekmez. Ve tanımlayıcı sadece dosyanın bilgilerini tutar ve dosyayı RAM'de tutmaz. Bir tanımlayıcıdan veri okuduğunuzda, işletim sistemi verileri sabit diskten okur. Dosya tanımlayıcıdaki bilgiler sadece sabit diskteki dosyanın konumunu gösterir vb.
Tayyab

5
Dosyaya dosya tanımlayıcı bire bir eşleme değildir. Aynı dosyayı 4 kez açabilir ve (4 farklı dosya tanıtıcısı alabilirim). Her biri okuma, yazma veya her ikisi için kullanılabilir (open'a () açık bayraklara bağlı olarak). Dosyanın RAM'de mi yoksa diskte mi olduğu konusunda - bu sizden çekirdek ve çeşitli önbellekleri tarafından gizlenir. Sonuçta, önbellek nedir diskte yazılanla eşleşir (yazma için) ve veri zaten önbellekte ise, çekirdek okumak için diske geri gitmez.
Beano

7
Bu kolayca anlamak için iyi bir yazı bottomupcs.com/file_descriptors.xhtml
Krishan Gopal

Yanıtlar:


561

Basit bir deyişle, bir dosyayı açtığınızda, işletim sistemi bu dosyayı temsil etmek ve bu açık dosya hakkındaki bilgileri depolamak için bir girdi oluşturur. Bu nedenle işletim sisteminizde 100 dosya açılmışsa, işletim sisteminde 100 giriş olacaktır (çekirdeğin bir yerinde). Bu girişler (... 100, 101, 102 ....) gibi tamsayılarla temsil edilir. Bu giriş numarası dosya tanımlayıcıdır. Yani sadece işletim sisteminde açılan bir dosyayı temsil eden bir tam sayıdır. İşleminiz 10 dosya açarsa, İşlem tablonuzda dosya tanımlayıcıları için 10 giriş olacaktır.

Benzer şekilde bir ağ soketini açtığınızda, bir tamsayı ile temsil edilir ve Soket Tanımlayıcı olarak adlandırılır. Umarım anlarsın.


7
Ayrıca, bir kerede çok sayıda dosya açarsanız, dosya tanımlayıcılarının tükenmesinin nedeni budur. Bu, * nix sistemlerinin çalışmasını engelleyecektir, çünkü tanımlayıcıları /procher zaman bir şeyler için açarlar .
Spencer Rathbun

8
@ErbenMo: Hayır, aynı olmayabilir. Dosyayı açtığınızda, işletim sistemi kullanılabilir bir FD atayacaktır ve kapattığınızda işletim sistemi FD'yi serbest bırakır ve bu FD'yi bundan sonra açılan başka bir dosyaya atayabilir. İşletim sisteminin Açılmış Dosyaları takip etme yolu ve belirli bir dosya ile ilgisi yoktur.
Tayyab

49
" Yani sadece işletim sisteminde açılan bir dosyayı benzersiz bir şekilde temsil eden bir tamsayı. " Bu yanlış. Bu tamsayı, bir işlem içinde açılan bir dosyayı benzersiz bir şekilde temsil eder . Örneğin dosya tanımlayıcısı 0, bir işlemde bir açık dosyayı ve başka bir işlemde tamamen farklı bir açık dosyayı temsil edecektir.
Keith Thompson

15
@Tayyab: Yanlış olduğuna inanıyorum. Dosya tanımlayıcıları 0, 1 ve 2 standart girdi, standart çıktı ve çalışan her işlem için standart hatadır . Başarılı bir başlangıç ​​çağrısı open(), başka bir çalışan işlemde dosya tanımlayıcı 3 olsa bile, dosya tanımlayıcı 3'ü verir . POSIX tanımınaopen() bakın : "open () işlevi, adlandırılan dosya için en düşük olan dosya tanımlayıcısını döndürür dosya tanımlayıcı şu anda bu işlem için açık değil . " (vurgu eklendi).
Keith Thompson

17
@ KeithThompson: Evet haklısın. Aslında soyutlama seviyesi hakkında. Aslında, birincisi işlem başına ve ikincisi sistem çapında olmak üzere iki tablo tutulur. İşlem başına tablodaki (yani fdtable) FD, sistem çapında benzersiz değildir. Ancak, sistem genelinde benzersiz girişleri içeren v-düğüm tablosuyla eşleşir. Bu nedenle, tanımlayıcıyı kontrol etmek için fopen () ve fileno () işlevini çağırdığınızda, işlem başına olan fdtable dizinini döndürdüğü için aynı FD numarasını 2 farklı işlemde alabilirsiniz. Getirdiğiniz için teşekkürler !!
Tayyab

116

Dosya tanımlayıcı, kullanıcı ve çekirdek alanı arasındaki arabirimde dosya / soket kaynaklarını tanımlamak için kullanılan opak bir tanıtıcıdır. Bu nedenle, open()veya socket()(sistem arabirimine sistem çağrıları) kullandığınızda, bir tamsayı olan bir dosya tanıtıcısı verilir (aslında işlemler u yapısının bir dizinidir - ancak bu önemli değildir). Eğer sistem çağrıları kullanarak çekirdekteki ile doğrudan etkileşime istiyorsanız nedenle, read(), write(), close()vb kullanmak sap bir dosya belirleyicisidir.

stdioArabirim olan sistem çağrılarının üzerine yerleştirilmiş bir soyutlama katmanı vardır . Bu, temel sistem çağrılarından daha fazla işlevsellik / özellik sağlar. Bu arayüz için, elde ettiğiniz opak tutamaç FILE*, fopen()çağrı tarafından döndürülen bir a'dır. Kullanmak çok çok işlevleri vardır stdioarayüzü fprintf(), fscanf(), fclose(), hayatınızı kolaylaştıracak orada yapmak hangi. C yılında stdin, stdoutve stderrvardır FILE*, UNIX sırasıyla dosya tanımlayıcıları eşlemek hangi 0, 1ve 2.


6
Şahsen bu cevabın cevap olarak verilen cevaptan daha iyi olduğunu düşünüyorum. Upvoted.
Tarık

101

Atın Ağzından Dinle: APUE (Richard Stevens).
Çekirdeğe, tüm açık dosyalara Dosya Tanımlayıcıları tarafından atıfta bulunulur. Dosya tanımlayıcı negatif olmayan bir sayıdır.

Mevcut bir dosyayı açtığımızda veya yeni bir dosya oluşturduğumuzda, çekirdek işleme bir dosya tanımlayıcı döndürür. Çekirdek, kullanımda olan tüm açık dosya tanımlayıcılarının bir tablosunu tutar. Dosya tanımlayıcılarının tahsisi genellikle ardışıktır ve dosyaya, ücretsiz dosya tanımlayıcıları havuzundan bir sonraki boş dosya tanımlayıcı olarak ayrılır. Dosyayı kapattığımızda, dosya tanımlayıcı serbest bırakılır ve daha fazla ayırma için kullanılabilir.
Daha fazla ayrıntı için bu resme bakın:

İki İşlem

Bir dosyayı okumak veya yazmak istediğimizde, dosyayı open () veya create () işlev çağrısı tarafından döndürülen dosya tanımlayıcıyla tanımlar ve bunu read () veya write () için bağımsız değişken olarak kullanırız .
Kural olarak, UNIX Sistem kabuklarının dosya tanımlayıcı 0'ı bir işlemin Standart Girdisi , dosya tanımlayıcı 1'i Standart Çıktı ve dosya tanımlayıcı 2'yi Standart Hata ile ilişkilendirir .
Dosya tanımlayıcı 0 ile OPEN_MAX arasında değişir. Dosya tanımlayıcı maksimum değeri ile elde edilebilir ulimit -n. Daha fazla bilgi için APUE Kitabının 3. bölümüne bakın.


1
0, 1, 2 bir işlemin "stdin", "stdout" ve "stderr" ile ilişkili olduğundan, bu tanımlayıcıları aynı anda farklı işlemler için kullanabilir miyiz?
Tarık

@Tarik: Dosya tanımlayıcıları her işlem için geçerlidir. Bunu görmek için osquery'yi indirin ve osqueryi <<< echo '.all process_open_files'bir bash kabuğunda çalıştırın .
Ben Creasy

29

Diğer cevaplar harika şeyler ekledi. Sadece 2 sent ekleyeceğim.

Wikipedia'ya göre kesin olarak biliyoruz: bir dosya tanımlayıcı negatif olmayan bir tamsayıdır. Eksik olduğunu düşündüğüm en önemli şey şunu söylemek olurdu:

Dosya tanımlayıcıları bir işlem kimliğine bağlıdır.

Biz en ünlü dosya tanımlayıcıları 0, 1 ve 2. 0 karşılık gelir biliyorum STDIN, 1 STDOUTve 2 STDERR.

Örneğin, kabuk süreçlerini örnek olarak alın ve bunun için nasıl uygulanır?

Bu kodu inceleyin

#>sleep 1000 &
[12] 14726

14726 (PID) kimliğine sahip bir işlem oluşturduk. Kullanarak lsof -p 14726biz böyle şeyler alabilirsiniz:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
sleep   14726 root  cwd    DIR    8,1     4096 1201140 /home/x
sleep   14726 root  rtd    DIR    8,1     4096       2 /
sleep   14726 root  txt    REG    8,1    35000  786587 /bin/sleep
sleep   14726 root  mem    REG    8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep   14726 root  mem    REG    8,1  2030544  137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep   14726 root  mem    REG    8,1   170960  137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

4. sütun FD ve bir sonraki sütun TYPE, Dosya Tanımlayıcı ve Dosya Tanımlayıcı türüne karşılık gelir.

FD için bazı değerler şunlar olabilir:

cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device

Ancak gerçek dosya tanımlayıcı altında:

NUMBER – Represent the actual file descriptor. 

Sayıdan sonraki karakter, yani "1u", dosyanın açıldığı modu gösterir. okumak için r, yazmak için w, okumak ve yazmak için u.

TYPE dosyanın türünü belirtir. TYPE değerlerinden bazıları:

REG – Regular File
DIR – Directory
FIFO – First In First Out

Ancak tüm dosya tanımlayıcıları CHR - Karakter özel dosyası (veya karakter aygıtı dosyası)

Şimdi, biz Dosya Tanıtıcılar belirleyebilir STDIN, STDOUTve STDERRkolay lsof -p PID, yoksa biz eğer aynı görebilirsiniz ls /proc/PID/fd.

Ayrıca, çekirdeğin izlediği dosya tanımlayıcı tablosunun, dosyalar tablosu veya inodes tablosu ile aynı olmadığını unutmayın. Diğer cevapların açıkladığı gibi bunlar ayrıdır.

fd tablosu

Kendinize bu dosya tanımlayıcılarının fiziksel olarak nerede olduğunu ve /dev/pts/6örneğin nelerin depolandığını sorabilirsiniz

sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

Eh, /dev/pts/6bellekte tamamen yaşıyor. Bunlar normal dosyalar değil, karakter aygıtı dosyalarıdır . Bunu şununla kontrol edebilirsiniz: ls -l /dev/pts/6ve cbenim durumumda başlayacaklar crw--w----.

OS gibi Linux'un çoğunu hatırlamak için yedi dosya türü tanımlar:

  • Düzenli dosyalar
  • Dizinler
  • Karakter cihazı dosyaları
  • Cihaz dosyalarını engelle
  • Yerel alan adı soketleri
  • Adlandırılmış borular (FIFO'lar) ve
  • Sembolik bağlantılar

1
Teşekkürler. Gerçekten de işlem başına olduğunu belirtmek önemlidir! Her şeyi daha iyi görselleştirmeye yardımcı olur.
Nishant

1
İşletim sisteminiz tarafından tanımlanan ve yanıtladığınız dosya türleri, dosyaları daha düşük bir düzeyde anlamaya yardımcı olur.
Rohan Bhale

20

İlgili diğer noktalar File Descriptor:

  1. File Descriptors(FD) (0, 1, 2, ...), açılan dosyalarla ilişkilendirilmiş negatif olmayan tamsayılardır .

  2. 0, 1, 2standart FD 'bu karşılık gelir s STDIN_FILENO, STDOUT_FILENOve STDERR_FILENO(tanımlanmıştır unistd.h), kabuk program başlatılır adına varsayılan olarak açılır.

  3. FD'ler sırayla ayrılır, yani olası en düşük ayrılmamış tamsayı değeri.

  4. Belirli bir işlem için FD'ler /proc/$pid/fd(Unix tabanlı sistemlerde) ' de görülebilir .


16

Diğer yanıtlara ek olarak, unix her şeyi bir dosya sistemi olarak görür. Klavyeniz yalnızca çekirdeğin perspektifinden okunan bir dosyadır. Ekran salt yazılır bir dosyadır. Benzer şekilde, klasörler, giriş-çıkış aygıtları vb. Dosyalar olarak kabul edilir. Bir dosya her açıldığında, aygıt sürücüleri [aygıt dosyaları için] bir open () istediğinde veya bir işlem bir kullanıcı dosyasını açtığında, çekirdeğin bir dosya tanımlayıcısı (bu dosyaya erişimi salt okunur olacak şekilde belirten bir tamsayı) ayırdığını varsayalım , yalnızca yazma vb. [referans için: https://en.wikipedia.org/wiki/Everything_is_a_file ]


Dosya tanımlayıcıları, anonim kanallar ve ağ yuvaları gibi dosya sisteminde olmayan şeylere de başvurabilir.
kbolino

12

Dosya Tanımlayıcıları (FD):

  • In Linux / Unix , her şey bir dosyadır. Normal dosya, Dizinler ve hatta Aygıtlar dosyalardır. Her dosyanın, Dosya Tanımlayıcı (FD) adında ilişkili bir numarası vardır.
  • Ekranınızda ayrıca bir Dosya Tanımlayıcı bulunur. Bir program yürütüldüğünde çıktı, ekranın Dosya Tanımlayıcısına gönderilir ve monitörünüzde program çıktısını görürsünüz. Çıktı yazıcının Dosya Tanımlayıcısına gönderilirse, program çıktısı yazdırılır.

    Hata Yeniden Yönlendirme:
    Terminalde bir program / komut yürüttüğünüzde, 3 dosya her zaman açıktır
    1. standart giriş
    2. standart çıktı
    3. standart hata.

    Bu dosyalar her program çalıştırıldığında daima mevcuttur. Bir dosya tanımlayıcıdan önce açıklandığı gibi, bu dosyaların her biri ile ilişkilendirilir.
    Dosya                                        Dosya Tanımlayıcı
    Standart Giriş STDIN 0
    Standart Çıkış STDOUT 1
    Standart Hata STDERR 2

  • Örneğin, dosyaları ararken, genellikle izin verilmeyen hatalar veya başka tür hatalar alır. Bu hatalar belirli bir dosyaya kaydedilebilir.
    örnek 1

$ ls mydir 2> errorfile.txt

Standart hata için dosya tanımlayıcı 2'dir.
Mydir adında bir dizin yoksa komutun çıktısı errorfile.txt dosyasına kaydedilir
. "2>" kullanarak hata çıktısını "errorfile adlı bir dosyaya yeniden yönlendiririz. txt "
Böylece, program çıktısı hatalarla karışmaz.

Umarım cevabını almışsındır.


5

Herhangi bir işletim sisteminde p1, p2, p3 ve benzeri işlemler ( p'ler) vardır . Her işlem genellikle dosyaların sürekli kullanımını sağlar.

Her işlem bir işlem ağacından (veya başka bir cümlede bir işlem tablosundan) oluşur.

Genellikle, İşletim sistemleri her işlemdeki her dosyayı bir sayıyla (yani her işlem ağacında / tabloda) temsil eder.

İşleminde kullanılan birinci dosya file0 ikinci, file1 üçüncü bir file2 benzeri ve.

Böyle bir sayı bir dosya tanımlayıcıdır.

Dosya tanımlayıcıları genellikle tamsayılardır (0, 1, 2 ve 0,5, 1,5, 2,5 değil).

İşlemleri sık sık "süreç tabloları" olarak tanımladığımız ve tabloların satır (girişler) olduğu göz önüne alındığında, her girişteki dosya tanımlayıcı hücresinin tüm girişi temsil etmek için kullandığını söyleyebiliriz.

Benzer şekilde, bir ağ soketini açtığınızda soket tanımlayıcısı vardır.

Bazı işletim sistemlerinde, dosya tanımlayıcıları bitebilir, ancak bu durumda son derece nadirdir ve ortalama bir bilgisayar kullanıcısı bundan endişelenmemelidir.

Dosya tanımlayıcıları küresel olabilir (A işlemi 0'da başlar ve 1'de biter; B işlemi 2'de başlar ve 3'te biter) ve benzerleri, ancak bildiğim kadarıyla, genellikle modern işletim sistemlerinde, dosya tanımlayıcılar genel değildir ve gerçekte işleme özgüdür (A işlemi mesela 0'da başlar ve 5'de biter, B süreci 0'da başlar ve 10'da sona erer).


Linux'taki FD'ler hakkında

1
büyük cevap :)
humble_wolf

5

Dosya tanımlayıcıları

  • Çekirdek için tüm açık dosyalara dosya tanımlayıcıları tarafından atıfta bulunulur.
  • Dosya tanımlayıcı, negatif olmayan bir tamsayıdır.
  • Mevcut bir dosyayı açtığımızda veya yeni bir dosya oluşturduğumuzda, çekirdek bir işleme bir dosya tanımlayıcı döndürür.
  • Bir dosyayı okumak veya üzerine yazmak istediğimizde, dosyayı aç veya oluştur tarafından yeniden ayarlanan dosya tanımlayıcıyla, okuma veya yazma argümanı olarak tanımlarız.
  • Her UNIX işlemi 20 dosya tanıtıcısına sahiptir ve bertarafı 0 ila 19 arasındadır, ancak birçok sistem tarafından 63'e genişletilmiştir.
  • İşlem başladığında ilk üçü zaten açılır 0: Standart giriş 1: Standart çıkış 2: Standart hata çıkışı
  • Üst işlem bir işlemi çatalladığında, alt işlem üst öğenin dosya tanımlayıcılarını devralır

1

Her şeyden önce basitleştirilmiş yanıtlara ekleme.
Eğer bash betiğindeki dosyalarla çalışıyorsanız, dosya tanımlayıcıyı kullanmak daha iyidir.
Örneğin: -
"test.txt" dosyasını okumak ve dosyadan yazmak istiyorsunuz.
Dosya tanımlayıcıyı aşağıda gösterildiği gibi kullanın

FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor
# Reading from the file line by line using file descriptor
while read LINE; do
    echo "$LINE"
done <&5

# Writing to the file using descriptor
echo "Adding the date: `date`" >&5 
exec 5<&- # Closing a file descriptor

-5

Dosya Tanımlayıcıları, bir dosyanın tanımlayıcılarıdır. Bir dosyaya bağlantılar verirler. Onların yardımıyla bir dosyayı okuyabilir, yazabilir ve açabiliriz.

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.