2010-02-22 14 views
15

C rutinleri opendir(), readdir() ve closedir() bir dizin yapısını geçmem için bir yol sağlar. Ancak, readdir() tarafından döndürülen her bir yön yapısı, dizin alt dizinlerine tekrar girmem gerekecek olan DIR işaretçi kümesini elde etmem için kullanışlı bir yol sağlamayabilir.Etkin Çapraz Yönlendirme Dizini opendir(), readdir() ve closedir()

Tabi ki bana dosyaların ismini verdiler, bu yüzden bu adı ya dizin yoluna ve stat() ve opendir() öğesine ekleyebilirim ya da işlemin şu andaki çalışma dizinini chdir yoluyla değiştirebilirim() ve chdir (“..”) ile geri döndürün.

İlk yaklaşımdaki sorun, dizin yolunun uzunluğu yeterince büyük olduğunda, opendir() öğesini içeren bir dizeyi geçirmenin maliyetinin bir dizinin açılması maliyetini aşmasıdır. Biraz daha teorik iseniz, karmaşıklığınızın doğrusal zamanın ötesine geçebileceğini söyleyebiliriz (dizin ağacındaki (bağıl) dosya adlarının toplam karakter sayısında). Ayrıca, ikinci yaklaşımın bir sorunu vardır. Her işlem tek bir geçerli çalışma dizinine sahip olduğundan, bir iş parçacığının tümü, bir çok iş parçacıklı uygulamada engellenmelidir. Ayrıca, geçerli çalışma dizininin sadece bir kolaylık olup olmadığını bilmiyorum (yani dosya sistemi sorgusu öncesinde göreceli bir yol eklenecektir). Öyleyse, bu yaklaşım da verimsiz olacaktır.

Bu işlevlere alternatifleri kabul ediyorum. Peki, bir UNIX dizin ağacını verimli bir şekilde nasıl geçebilir (altındaki dosyaların toplam karakter sayısında doğrusal zaman)?

+0

bir dosya adı ya da alt dizinin maksimum uzunluğu geleneksel olarak kesinlikle 255 ve size fonksiyon özyinelemeli yaparsanız Yani, büyük dizeleri olmaz hemen hemen hiç fazla 512 den olduğunu MAXCOMPLEN tarafından ayarlanır dizin yollarını tutan dizeleri ayırma ve yönetme noktasının yakınında hiçbir yerde geçişin genel karmaşıklığını etkiler. –

cevap

4

opendir/readdir/closedir kullanmak yolu işlevi özyinelemeli yapmaktır! Snippet'e Dreamincode.net'dan bakın.

Bu yardımcı olur umarım.

DÜZENLEME Teşekkür R.Sahu, Linky süresi doldu, ancak, wayback archive aracılığıyla buldum ve gist eklemek için özgürlük aldı. Lütfen lisansı uygun şekilde kontrol etmek ve orijinal yazarın kaynağına atıfta bulunduğunu unutmayın! :)

+0

Kodun bağlantısı artık geçerli değil. Sadece FYI. –

+0

@RSahu buna göre güncelleştirildi;) – t0mm13b

5

Tek bir temel noktayı kaçırıyor gibi görünüyorsunuz: dizin geçişi diskten veri okumayı içerir. Bu veriler önbellekte olduğunda/olsa bile, önbellekten işleminize almak için adil bir koddan geçersiniz. Yollar da genellikle oldukça kısadır - bir çift yüz bayttan daha fazlası oldukça sıra dışıdır. Bunların hepsi, gerçek bir sorun olmadan ihtiyaç duyduğunuz tüm yollar için oldukça makul bir şekilde dizeleri oluşturabileceğiniz anlamına gelir. Dizeleri oluşturmak için harcanan zaman, diskten veri okuma zamanı ile karşılaştırıldığında hala oldukça küçüktür. Bu, dize manipülasyonu için harcanan süreyi normal olarak göz ardı edebileceğiniz ve sadece disk kullanımını optimize etmede çalıştığınız anlamına gelir.

Kendi deneyimim, çoğu dizin geçişi için, geniş kapsamlı bir ilk arama genellikle tercih edilir - geçerli dizini geçtiğinizde, tüm alt dizinlere tam yolları bir öncelik sırası gibi bir şeyle koyun. Geçerli dizini geçmeyi bitirdiğinizde, sıradaki ilk öğeyi sıradan çekin ve sıra boşalana kadar devam edin. Bu genellikle önbellek mevkisini geliştirir, bu yüzden diski okuma harcanan zaman miktarını azaltır. Sisteme bağlı olarak (disk hızı, CPU hızı, toplam bellek kullanılabilir, vb.) Neredeyse her zaman en azından derinlikteki ilk geçiş kadar hızlıdır ve kolayca iki kat daha hızlıdır (veya benzeri).

+0

Neden bir öncelik sırası kullanın ve bir FIFO kuyruğu gibi daha basit bir şey kullanmıyorsunuz? Öncelik özelliği olarak ne kullanıyorsunuz? –

+0

@Andrew: İyi soru. Bir FIFO mükemmel şekilde çalışacaktır. Bir PQ basitçe kullanıcının tercih ettiği isme göre sıralamayı kolaylaştırır (kullanıcının bunu kullanırken kesinlikle tercih ederim). –

+0

Teşekkürler, bu mantıklı, çıktıyı düşünmemiştim biçim. –

15

aka Dosya Ağacı Yürüyüşü'u denediniz mi?man 3 ftw den

Snippit:

ftw

int ftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int nopenfd);() belirtilen dizin dir başlayarak dizin ağacı yürür. ağaçtaki her bulundu giriş için, o giriş için stat girişi, bir işaretçi (2) yapısı ve uygulamanız için

+2

Ve 'nftw()' bazen - ikisi arasında ince bir fark var, ama bulmak için manuel bashing gitmek zorundayım ... http: //www.opengroup.org/onlinepubs/9699919799/functions/nftw. html ("nftw() işlevi, yinelenen dizin hiyerarşisini, yolun içinde kök dizinine indirecektir. nftw() işlevi, ek argüman bayrakları alması dışında ftw() işlevine benzer bir etkiye sahiptir ..."). –

+0

Nftw() 'yi hatırlattığınız için teşekkür ederiz. Bunu 'ftw()' yi kullanarak kullanmayı hatırlıyorum çünkü eski, sizin için (diğer şeylerin yanı sıra) symlinks üzerinden yinelenmemesini söylemek için bir bayrak geçmenize izin veriyor. – SiegeX

+0

Bir dizinde sıralı geçiş yapmak için ftw() kullanabilir miyiz? (böylece dizin ağacı yapısının en altından dosya/dizinleri silebiliriz) – Dinushan

2

Muhtemelen overkill bir int bayrağının tam yolunu birlikte fn() çağırır, ancak Yüzlerce milyon dosya içeren bir dizin ağacından geçmek için tasarlanmış bir kütüphane.

https://github.com/hpc/libcircle

İlgili konular