dup2 / dup - neden bir dosya tanımlayıcısını kopyalamam gerekiyor?


85

Ben kullanımını anlamaya çalışıyorum dup2ve dup.

Man sayfasından:

Bu sistem çağrısına neden ihtiyacım olsun? dosya tanımlayıcısını çoğaltmanın faydası nedir?

Dosya tanımlayıcım varsa, neden bir kopyasını almak isteyeyim?

Nerede dup2/ dupgerekli olduğu konusunda bana bir örnek verebilirseniz çok sevinirim .

Teşekkürler


Kabukların boru işlevselliğini onsuz dupveya olmadan nasıl uygularsınız dup2? Aramanız pipe(2)ve ardından dosya tanımlayıcılardan birine sahip olmanız gerekirdupSTDIN_FILENO
Basile Starynkevitch

Yanıtlar:


48

Çift sistem çağrısı, mevcut bir dosya tanımlayıcısını çoğaltır ve aynı temel G / Ç nesnesine başvuran yeni bir tane döndürür.

Dup, kabukların aşağıdaki gibi komutları uygulamasına izin verir:

2> & 1, kabuğa, komuta tanımlayıcı 1'in kopyası olan bir dosya tanımlayıcısı 2 vermesini söyler (yani, stderr & stdout aynı fd'yi gösterir).
Şimdi çağırmak için hata mesajı ls üzerinde mevcut olmayan dosyanın ve doğru çıkış ls üzerinde dosya mevcut gösteriyi yukarı TMP1 dosyası.

Aşağıdaki örnek kod, bir borunun okuma ucuna bağlı standart giriş ile wc programını çalıştırır.

Çocuk, okuma ucunu 0 dosya tanımlayıcısına kopyalar, p'deki dosya tanımlayıcıları kapatır ve wc'yi çalıştırır. Wc standart girişinden okuduğunda borudan okur.
Bu, boruların dup kullanılarak uygulanma şeklidir, peki şimdi bir dup kullanımı, başka bir şey oluşturmak için boruyu kullanırsınız, bu sistem çağrılarının güzelliğidir, zaten var olan araçları kullanarak birbiri ardına inşa edersiniz, bu araçlar kullanılarak inşa edilmiştir. başka bir şey de öyle .. Sonunda sistem çağrıları, çekirdek içinde edindiğiniz en temel

Şerefe :)


1
Yani programın kendisi için dupdeğil arayan için yararlı lsmı? dupDosyaya zaten erişiminiz varsa, ls gibi bir programda kullanmanın herhangi bir faydası var mı ? Burada örneğin, kodlanmış lshataları yazıyor 2, bu yüzden bir tüketicisi olarak onu aşmanın bir yolu var ls. Sanırım bu ince bir nokta hayır mı?
Nishant

3
Örnek programınızda bir hata var gibi görünüyor ; arıyorsun dup(p[STDIN])ama sonucu çöpe atıyorsun . Kullanmak mı istedin dup2(p[STDIN], 0)?
Quuxplusone

1
@Quuxplusone dup, "şu anda işlem tarafından kullanılmayan en düşük numaralı tanımlayıcıyı" döndürür. Fd 0 henüz kapatıldığından, dup0 döndürmelidir dup2, sadece en düşük serbest fd'yi kullanmak yerine hangi fd'nin kullanılması gerektiği konusunda nettir, bu yüzden bunu tercih ederim.
Wodin

@Wodin: Ah, bahse girerim OP'nin ne düşündüğü konusunda haklısın. Yine de, "yeni kapatıldı" nın göreceli olduğu ve örneğin, dosyaları da açan eşzamanlı iş parçacıkları varlığında OP'nin kodunun bozulabileceği konusunda haklı mıyım?
Quuxplusone

@Quuxplusone Sanırım haklısın, ama kesin olarak bilmiyorum. Ama bu durumda başka sorunlarınız olacak. Eğer stdin'i başka bir yerden okumak istediğiniz için kapatırsanız ve sonra başka bir iş parçacığı sizden önce bir dosya açarsa, o fd 0 alır. Eğer o zaman dup2 kullanırsanız, diğer iş parçacığının açtığı fd'yi kapatır, böylece diğer iş parçacığı şimdi açtığınız dosyadan okuyacak (ve dosyaya mı yazacak?). Her neyse, doğru hatırlıyorsam exec*, çok iş parçacıklı bir işlemden aramamalısın. Ama iş parçacığı uzmanı değilim :)
Wodin

18

Bir dosya tanımlayıcısını çoğaltmanın bir başka nedeni de onu kullanmaktır fdopen. fcloseiletilen dosya tanımlayıcısını kapatır fdopen, bu nedenle orijinal dosya tanımlayıcının kapatılmasını istemiyorsanız, dupönce onu çoğaltmanız gerekir .


fdopen()bir dosya tanımlayıcısını çoğaltmıyor gibi görünüyor, sadece kullanıcı alanında tampon oluşturuyor.
Trump 2020 - Adalet

3
Cevabımı yanlış anladın. Nokta isteyebilirsiniz olmasıdır dupgeçirmeden önce fd fdopenberi fclosebunu kapatacaktır.
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

1
@ theferrit32: Stdio FILEarabirimleri aracılığıyla önceden var olan açık bir dosyaya erişmek için bir tutamaç ayırırsanız , fclosebu FILEtanıtıcıyı serbest bırakmak için aramanız gerekir . Eğer altta yatan açık dosyasını kullanarak veya devam etmek istiyorsanız yazılım mimarisi dosya tanımlayıcı için orijinal "sahibi" kod olacak şekilde ise closeo, aslında fcloseaynı zamanda teslim yatan bir dosya tanıtıcı kapatır fdopenbir sorundur. Sen kullanarak bu sorunu önleyebilirsiniz dupgeçmek aynı açık dosya için bir dosya tanıtıcı yapmak fdopen, böylece, fcloseyakın orijinal bir değil.
R .. GitHub BUZA YARDIM ETMEYİ DUR

1
Buradaki önemli nokta, fdopen () fd'nin sahipliğini kopyalamak yerine fd'ye taşır . Bu, kullanıcıların bilmesi gereken bir şey. Nesneye ek olarak kullanılabilir bir tanıtıcı tutması gereken tüketiciler ,. Bu kadar. FILEfdFILEfd
Conrad Meyer

1
@ConradMeyer: Evet, bu onu ifade etmenin çok iyi bir yolu. Sahipliği bir FILEkez ona taşıdığınızda "sahipliği taşıma" işleminin olmadığını not edin .
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

4

dup, bir işlemin çıktısını yeniden yönlendirebilmek için kullanılır.

Örneğin, bir işlemin çıktısını kaydetmek istiyorsanız, çıktıyı çoğaltırsınız (fd = 1), çoğaltılan fd'yi bir dosyaya yönlendirirsiniz, ardından işlemi uygularsınız ve işlem bittiğinde yeniden yönlendirirsiniz. fd çıktıya kaydedildi.


4

Dup / dup2 ile ilgili bazı noktalar not edilebilir lütfen

dup / dup2 - Teknik olarak amaç, bir Dosya tablosu Girişini tek bir işlem içinde farklı tutamaçlarla paylaşmaktır . (Çatallıyorsak, tanımlayıcı varsayılan olarak alt süreçte kopyalanır ve dosya tablosu girişi de paylaşılır).

Bu, dup / dup2 işlevini kullanan tek bir açık dosya tablosu girişi için muhtemelen farklı özniteliklere sahip birden fazla dosya tanımlayıcımız olabileceği anlamına gelir .

(Görünüşe göre şu anda sadece FD_CLOEXEC bayrağı bir dosya tanımlayıcısının tek özniteliğidir).

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

Farklar (sonuncusu için) - dup2 ve fcntl close arasındaki bazı errno değerlerinin yanı sıra, fcntl'nin izlediği iki işlev çağrısı dahil olduğundan yarış koşullarını artırabilir.

Ayrıntılar http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html adresinden kontrol edilebilir.

Bir kullanım örneği -

Dup / dup2 kullanımının görülebildiği bir kabukta iş denetimini uygularken ilginç bir örnek .. aşağıdaki bağlantıda

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

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.