Unix sistemlerinde, neden açıkça () veya `write ()` ı okuyabilmek için `open ()` ve `close ()` dosyalarına ihtiyacımız var?


50

Unix dosya sistemi tasarımında neden var open()ve close()var?

İşletim sistemi sadece ilk kez tespit edemedi mi read()ya write()da aranmadı ve open()normalde ne yaparsa yapamadı mı?


22
Bu modelin dosya sisteminin bir parçası değil, Unix API'nin bir parçası olduğuna dikkat etmek önemlidir . Dosya sistemi sadece disklerin baytların nereye gittiği ve dosya adının nereye yerleştirileceği, vb. Bu çağrıları dosya sistemi için uygun güncellemelere çevirmek için kernel yapın (tıpkı şimdi olduğu gibi).
marcelm

18
İfade edildiği gibi, bunun neden open()var olduğuyla ilgili daha fazla olduğunu düşünüyorum . "İşletim sistemi ilk defa read () veya write () 'ı tespit edemedi ve normalde ne yaparsa yapsın () ne yapamadı?" Zaman için karşılık gelen bir öneri var mı kapanış olur?
Joshua Taylor

7
Nasıl söylerdim read()ya write()hangi dosya erişilir? Muhtemelen yolu geçerek. Ya dosya yolu erişilirken değişir (iki read()veya write()arama arasında )?
user253751

2
Ayrıca, genellikle erişim kontrolünü read()ve write()sadece erişim kontrolünü yapmazsınız open().
Pavel Šimerda

6
@Johnny: Belki de donanımın o günlerde ne kadar sınırlı olduğunu unutmuşsunuzdur. Unix’in ilk uygulandığı PDP-7’de (Google’da) maksimum 64K RAM ve 0.333 MHz saat vardı - bugünlerde basit bir mikrodenetleyiciden daha az. Bu tür bir çöp toplama işlemi yapmak veya dosya erişimini izlemek için sistem kodunu kullanmak, sistemi dizlerine getirecektir.
jamesqf

Yanıtlar:


60

Dennis Ritchie de bahseder «Unix Zaman paylaşımı Sisteminin Evrimi» o openve closebirlikte read, writeve createn başından beri sistemde mevcut idi.

Olmadan openve closedüşünülemez bir sistem sanırım , ancak tasarımı zorlaştıracağına inanıyorum. Genelde yalnızca bir tanesine değil, birden fazla okuma ve yazma çağrısı yapmak istiyorsunuz ve bu, özellikle UNIX'in kaynaklandığı çok sınırlı RAM'i olan bu eski bilgisayarlarda geçerliydi. Geçerli dosya konumunuzu koruyan bir tutamağa sahip olmak bunu kolaylaştırır. Eğer readveyawritesapı geri getirecekti, bir çift getirmeliydiler - bir sap ve kendi geri dönüş durumları. Paritenin işleyen kısmı diğer tüm çağrılar için işe yaramaz ve bu düzenlemeyi zorlaştırırdı. İmlecin durumunu çekirdeğe bırakmak, yalnızca arabelleğe almakla değil verimliliği arttırmasını sağlar. Ayrıca, yol aramasıyla ilgili bazı maliyetler de vardır - bir tutamağa sahip olmak, yalnızca bir kez ödemenizi sağlar. Dahası, UNIX dünya görüşündeki bazı dosyaların bile bir dosya sistemi yolu yoktur (ya da böyle bir şey yapmazlar /proc/self/fd).


7
Yol arama ve izin kontrolü vb. Maliyetleri çok önemlidir. Eğer open/ olmadan bir sistem yapmak isteseydiniz close, /dev/stdoutborulara izin vermek gibi şeyleri uyguladığınızdan emin olabilirsiniz .
Peter Cordes

5
Bunun bir başka yönü de, dosyayı açık tuttuğunuzda birden fazla okuma kullanırken bu tanıtıcıyı aynı dosyaya tutabileceğinizdir. Aksi takdirde, başka bir işlemin aynı ada sahip bir dosyayı açıp yeniden oluşturduğu durumlar olabilir ve topaklarda bir dosyayı okumak tamamen tutarsız olabilir. (Bunların bazıları dosya sistemine de bağlı olabilir.)
Bruno

2
Close olmadan bir tane tasarladım (); inode numarasını iletir ve read () ve write () işlevine kaydırırsınız. Açmadan () çok kolay bir şekilde yapamam çünkü isim çözümlemesi burada yaşanıyor.
Joshua,

3
@Joshua: Bu tür bir sistemin temelde farklı semantikleri vardır, çünkü unix dosya tanımlayıcıları dosyalara (inode) atıfta bulunmaz, ancak belirli bir dosya (inode) için çok fazla olan dosya tanımlarını açar .
R.

@Joshua, sadece adını open()etmek get_inode()ve bütün sistem daha sert (imkansız / okumak için aynı anda birkaç pozisyonlarda aynı dosyayı yazma) yaptı.
vonbrand

53

O zaman readve writeçağrıların tümü , her işlem için bu bilgiyi iletmek zorunda kalacaktı:

  • Dosyanın adı
  • Dosyanın izinleri
  • Arayanın ekleyip oluşturmadığını
  • Arayan olup olmadığını yapılan dosyayla çalışmak (kullanılmayan salt tamponlarını atmak ve yazmaya karşı tampon gerçekten bitmiş yazma sağlamak için)

Eğer bağımsız düşünün olsun aramaları open , read, writeve closeI / O tek bir amaç daha basit olmasını mesajı tasarım felsefesi üzerine kurulmuştur. Unix geliştiricileri, her şeyi yapan tek bir işlem (veya program) yerine, birçok şekilde birleştirilebilecek basit işlemleri ve programları kullanmayı seçti.


Arayanlar da çoğu durumda bir dosyada istenen ofseti belirtmek zorunda kalır. Her isteğin bir dosyayı bağımsız olarak tanımlaması ve ofsetini belirlemesinin yardımcı olabileceği bazı durumlar vardır (örneğin, verilere erişime izin veren bir UDP protokolü), bir sunucunun durumunu sürdürme ihtiyacını ortadan kaldırdığı için genel olarak sunucunun bulunması daha uygundur. dosya konumunu takip et. Ayrıca, başka yerlerde de belirtildiği gibi, dosyaları yazacak kodun genellikle önceden ve sonradan kilitlenmesi gerekir; bu işlemleri açma / kapama ile taramak çok kullanışlıdır.
supercat

5
"Dosya" ilk etapta bir isim veya izinlere sahip olmayabilir; readve writebir dosya sistemi üzerinde yaşayan dosyalara kısıtlı ve pjc50 açıkladığı gibi bu, Unix temel bir tasarım kararı olduğu verilmez.
reinierpost

1
Ayrıca dosyanın nerede okunup / nerede yazılacağı - başlangıç, bitiş veya isteğe bağlı bir pozisyon (tipik olarak en son okuma / yazma işleminin bitiminden hemen sonra olmak üzere) - çekirdek sizin için bunu izler (bir mod ile tüm yazıları dosyanın sonuna yönlendirin, aksi takdirde dosyalar başlangıçta konumuyla açılır ve her okuma / yazma ile lseek
ileriye

51

Dosya tanıtıcısı kavramı, UNIX'in dosya sisteminin bir parçası olmayan şeyler de dahil olmak üzere "her şeyin bir dosya olduğu" tasarım seçimi nedeniyle önemlidir. Teyp sürücüleri, klavye ve ekran (veya teletype!), Delikli kart / teyp okuyucuları, seri bağlantılar, ağ bağlantıları ve (UNIX'in ana anahtarı) "borular" adı verilen diğer programlara doğrudan bağlantılar.

Eğer gibi basit standart UNIX araçlardan birçok bakarsak grepözellikle kendi orijinal versiyonları, onlar aramaları kapsamamaktadır fark edeceksiniz open()ve close()ama sadece readve write. Dosya tanıtıcıları programın dışında kabuk tarafından kurulur ve çalıştırıldığında iletilir. Bu nedenle, programın bir dosyaya mı yoksa başka bir programa mı yazdığı ile ilgilenmesi gerekmez.

Yanı sıra open, dosya tanımlayıcıları almanın başka yolları vardır socket, listen, pipe, dup, ve boruların üzerinde dosya tanımlayıcıları gönderme için çok Heath Robinson mekanizması: https://stackoverflow.com/questions/28003921/sending-file-descriptor-by-linux -priz

Düzenleme: dolaylı katmanları açıklayan bazı ders notları ve bunun O_APPEND'in mantıklı bir şekilde çalışmasına nasıl olanak sağladığı. İnode verilerini bellekte tutmanın sistemin bir dahaki yazma işlemi için tekrar gelip getirilmemesi gerektiğini garanti ettiğini unutmayın.


1
Ayrıca creatve listenbir fd oluşturmaz, ancak dinleme sırasında bir istek geldiğinde (ve eğer) acceptyeni (bağlı) soket için bir fd oluşturur ve döndürür.
dave_thompson_085

18
Bu doğru cevap. Dosya tanıtıcılarındaki ünlü (küçük) işlemler kümesi, veri üreten veya tüketen her türlü kaynak için birleştirici bir API'dir. Bu konsept HUGELY başarılı. Bir dize , kaynak türünü asıl konumla birlikte tanımlayan bir sözdizimine sahip olabilir (URL, herhangi biri URL?), Ancak mevcut RAM'in yüzde kaçını kaplayan dizgileri kopyalamak (PDP 7? 16 kB?) Ne kadar aşırı görünüyordu? .
Peter - Monica

Belki düşük seviyeli aramalar ve kabuk aynı anda geliştirildiyse olur. Ancak pipeUnix'teki gelişmeler başladıktan birkaç yıl sonra tanıtıldı.
Thomas Dickey

1
@Thomas Dickey: Özgün tasarımın ne kadar iyi olduğunu gösteriyor, çünkü boruların basit bir şekilde uzamasına izin verdi & c :-)
jamesqf

Ancak bu argüman çizgisinin ardından, bu cevap yeni bir şey sağlamıyor.
Thomas Dickey,

10

Cevap hayır çünkü open () ve close () sırasıyla bir tanıtıcı oluşturur ve yok eder. Belirli bir erişim düzeyine sahip tek arayan siz olduğunuzu garanti etmek isteyebileceğiniz, örneğin beklenmedik bir şekilde ayrıştırdığınız bir dosyaya yazarken başka bir arayan (örneğin) bırakacağınızı garanti etmek isteyebileceğiniz zamanlar (yani, her zaman, gerçekten) vardır. bilinmeyen bir durumda olan bir uygulama veya bir livelock veya çıkmaza neden olabilir, örneğin Dining Philosophers lemma.

Bu düşünce olmadan bile, dikkate alınması gereken performans etkileri vardır; close (), dosya sisteminin (uygunsa veya çağırdıysanız) işgal ettiğiniz arabelleği temizlemesini sağlar, pahalı bir işlemdir. Bir bellek içi akışta ardışık olarak yapılan birkaç düzenleme, esasen ilgisiz birkaç okuma-yazma-değiştirme döngüsünden çok daha etkilidir, bildiğiniz üzere, hepiniz için yüksek gecikmeli toplu depolama değerinde bir veri merkezi üzerine dağılmış bir dünyanın yarısı kadar varlığını sürdürür. Yerel depolamada bile, bellek genellikle toplu depolama alanından daha hızlıdır.


7

Open (), dosyaları kullanımdayken kilitlemenin bir yolunu sunar. Dosyalar otomatik olarak açılırsa, işletim sistemi tarafından tekrar okunur / yazılır ve kapatılırsa, diğer dosyaların işlemleri arasında bu dosyaları değiştirmesini durduracak hiçbir şey olmaz.

Bu, kolay yönetilebilir (çoğu sistem özel olmayan dosya erişimini destekler) olabilirken, çoğu uygulama, açtıkları dosyaların değişmediğini varsaymaktadır.


5

Çünkü dosyanın yolu aynı kalacağını varsayırken, dosyanın yolu hareket edebilir.


4

Okuma ve bir dosya sistemi yazma edebilir tamponlama şemaları, OS temizlik, düşük seviyeli disk yönetimi ve diğer potansiyel eylemlerin bir dizi büyük bir çeşitlilik içerir. Dolayısıyla, eylemler open()ve close()bu başlık altındaki faaliyetler için bu tür kurulumlar olarak hizmet edilir. Bir dosya sisteminin farklı uygulamaları gerektiği şekilde özelleştirilebilir ve çağıran programa karşı şeffaf kalır.

İşletim sistemi açılmadı / kapanmadıysa, o zaman readveya ile write, bu dosya işlemlerinin her seferinde herhangi bir başlatma, tampon yıkama / yönetim, vb. Yapması gerekirdi. Tekrarlayan okumalar ve yazılar için empoze etmek için çok fazla yükü var.


Unutma, open () ve close () ayrıca dosyadaki konumunu da tutar (bir sonraki okuma veya bir sonraki yazma için). Bu yüzden sonunda veya read () ve write () tüm parametreleri işlemek için bir yapıya veya her parametre için argümanlara ihtiyaç duyar. Bir yapı oluşturmak bir açıkla eşdeğerdir (programcı sitesi), bu nedenle eğer işletim sistemi açık hakkında da bilgi sahibi ise, sadece daha fazla avantaja sahibiz.
Giacomo Catenazzi

1

Unix mantra, “bir şeyi yapmanın bir yolunu sunar”, yani irade ile bir araya getirilebilecek (yeniden kullanılabilir) parçalar halinde "çarpan" demektir. Yani, bu durumda, dosya tanıtıcılarının oluşturulmasını ve imha edilmesini kullanımlarından ayırın. Borular ve ağ bağlantılarıyla birlikte önemli avantajlar geldi (dosya tutamaçlarından da manipüle ediliyorlar, ancak başka şekillerde yaratılıyorlar). Dosya tanıtıcılarını etrafa sevk edebilmek (örneğin, onları hayatta kalan "açık dosyalar" olarak çocuk işlemlerine exec(2)ve hatta bir boru aracılığıyla ilgisiz işlemlere geçirmek) ancak bu şekilde mümkündür. Özellikle, korumalı bir dosyaya kontrollü erişim sağlamak istiyorsanız. Yani açabilirsiniz örneğin/etc/passwd yazmak için ve bu dosyayı yazma için açmasına izin verilmeyen bir çocuk sürecine geçirin (evet, bunun saçma bir örnek olduğunu biliyorum, daha gerçekçi bir şeyle düzenlemekten çekinmeyin).

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.