2011-07-05 12 views

cevap

22

Linux'ta olduğunuza göre, (neredeyse kesinlikle) dosya sistemi olan /proc dosya sistemini aldınız. Bu, en kolay yöntemin, /proc/self/fd içeriğinin bir listesini almak olduğu anlamına gelir; oradaki her dosya bir FD'den sonra adlandırılır. (Tabii ki, liste yapmak g_dir_open, g_dir_read_name ve g_dir_close kullanın.)

(örneğin hiçbir yararlı POSIX API yoktur; bu standardize edilmemiştir bir alanı olan) bilgisi aksi orta garip alınıyor.

+3

Başka bir işlem için bunları listelemek için, bunun yerine '/ proc/PID/fd 'dizinini listeleyin (burada PID, söz konusu işlemin işlem kimliğidir). Kök olmasanız bile bunları yalnızca bazı işlemler için görebileceksiniz. –

+0

/proc/*/pid kullanımı elbette çok linux spesifiktir ve hiç taşınabilir değildir, ancak bu bir problem değilse, o zaman iyi çalışmalıdır. – TomH

+2

@Tom: 'linux' ile etiketlenmiş _was_ sorusu… –

5

Eğer sadece (sayım yöntemi boru şeyi yapabilirsiniz ve çıkış ya da yukarıda belirtilen dizinde kendiniz dosyaları saymak, ya yeniden C'de

ls -l /proc/<pid>/fd | wc - l 

yapabilirsiniz pid aracılığı süreci saptayabilirseniz mesela burada Counting the number of files in a directory using C)

2

Eğer demek istediğin nasıl programlama yoluyla daha sonra süreç içinde de yapabilirsin, normal (biraz korkunç) yöntemi tüm olası tanımlayıcılar üzerinde döngü gibi bir şey yapmak istiyorsa (aralık bulmak için RLIMIT_NOFILE okumak için getrlimit() kullanmak)gibi bir şey çağırıyor Her birive hangisinin açık olmadığını görmek için EBADF yanıtlarını kontrol edin. Eğer bir süreç açık vardır hangi dosyaların kabuğundan öğrenmek istediğiniz anlamına Eğer

sonra lsof -p <pid> istediğiniz şeydir.

+0

ben olmazdım 252 başarısız syscalls alınıyor açık FDS 0, 1, 2 ve 255'e sahip süreçlerin adil sayısını görebilirsiniz güzel… –

+0

Her şey değişkendir - açıkçası performans açısından kritik bir kod parçası yapmak istemiyorsunuz ama bunun dışında büyük bir sorun değil. Sınırın, yine de, modern bir linux sisteminde 2048 gibi bir şey olması daha olasıdır. – TomH

+3

RLIMIT_NOFILE sadece yeni oluşturulmuş dosya tanımlayıcıları için maksimum açıklamayı belirtir, açık dosya tanımlayıcıları için sınır değildir, bu nedenle dosya tanımlayıcı numaralarında üst sınırı bulmak için getrlimit'i kullanamazsınız. –

1

fstat komutu, sistemin tüm çalışan işlemlerini ve açık açıklayıcılarını listeler; ayrıca, ne tür bir tanımlamalayıcının olduğunu (dosya, soket, boru vb.) Listeler ve tanımlayıcının okuduğu veya yazdığı şeyin bir ipucunu vermeye çalışır. ne dosya sistemi ve bu dosya sistemi Burada

22

geçenleri inode numarası kullandığım için kullanılan bazı kod gibi, ben yaklaşık/proc/kendini (thx Donal!), ancak bu şekilde zaten muhtemelen daha genel olduğu bilmiyordum. En üstteki tüm işlevler için gerekli olanları ekledim.

#include <string.h> 
#include <stdio.h> 
#include <dirent.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/resource.h> 

#ifndef FALSE 
#define FALSE (0) 
#endif 
#ifndef TRUE 
#define TRUE (!FALSE) 
#endif 

/* implementation of Donal Fellows method */ 
int get_num_fds() 
{ 
    int fd_count; 
    char buf[64]; 
    struct dirent *dp; 

    snprintf(buf, 64, "/proc/%i/fd/", getpid()); 

    fd_count = 0; 
    DIR *dir = opendir(buf); 
    while ((dp = readdir(dir)) != NULL) { 
      fd_count++; 
    } 
    closedir(dir); 
    return fd_count; 
} 

Ben dosya bir kez kolları sızıntı ile çok kötü bir sorun geçti ve ben aslında Tom H. önerdi çözüm kodlu çıkıyor: dönmek için çok

/* check whether a file-descriptor is valid */ 
int pth_util_fd_valid(int fd) 
{ 
    if (fd < 3 || fd >= FD_SETSIZE) 
      return FALSE; 
    if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) 
      return FALSE; 
    return TRUE; 
} 

/* check first 1024 (usual size of FD_SESIZE) file handles */ 
int test_fds() 
{ 
    int i; 
    int fd_dup; 
    char errst[64]; 
    for (i = 0; i < FD_SETSIZE; i++) { 
      *errst = 0; 
      fd_dup = dup(i); 
      if (fd_dup == -1) { 
       strcpy(errst, strerror(errno)); 
       // EBADF oldfd isn’t an open file descriptor, or newfd is out of the allowed range for file descriptors. 
       // EBUSY (Linux only) This may be returned by dup2() during a race condition with open(2) and dup(). 
       // EINTR The dup2() call was interrupted by a signal; see signal(7). 
       // EMFILE The process already has the maximum number of file descriptors open and tried to open a new one. 
      } else { 
       close(fd_dup); 
       strcpy(errst, "dup() ok"); 
      } 
      printf("%4i: %5i %24s %s\n", i, fcntl(i, F_GETOWN), fd_info(i), errst); 
    } 
    return 0; 
} 

Bu istemek muhtemelen edeceğiz

char *fcntl_flags(int flags) 
{ 
    static char output[128]; 
    *output = 0; 

    if (flags & O_RDONLY) 
     strcat(output, "O_RDONLY "); 
    if (flags & O_WRONLY) 
     strcat(output, "O_WRONLY "); 
    if (flags & O_RDWR) 
     strcat(output, "O_RDWR "); 
    if (flags & O_CREAT) 
     strcat(output, "O_CREAT "); 
    if (flags & O_EXCL) 
     strcat(output, "O_EXCL "); 
    if (flags & O_NOCTTY) 
     strcat(output, "O_NOCTTY "); 
    if (flags & O_TRUNC) 
     strcat(output, "O_TRUNC "); 
    if (flags & O_APPEND) 
     strcat(output, "O_APPEND "); 
    if (flags & O_NONBLOCK) 
     strcat(output, "O_NONBLOCK "); 
    if (flags & O_SYNC) 
     strcat(output, "O_SYNC "); 
    if (flags & O_ASYNC) 
     strcat(output, "O_ASYNC "); 

    return output; 
} 

char *fd_info(int fd) 
{ 
    if (fd < 0 || fd >= FD_SETSIZE) 
     return FALSE; 
    // if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) 
    int rv = fcntl(fd, F_GETFL); 
    return (rv == -1) ? strerror(errno) : fcntl_flags(rv); 
} 

FD_SETSIZE genellikle 1024 ... yukarıdaki son printf tatmin ve sürecin başına maksimum dosyaları emin olmak istiyorsanız, bu işleve bir çağrı ile değiştirebilirsiniz 1024. genellikle bir TomH tarafından açıklanmıştır.Eğer (sadece bunu kontrol etmek hangi yaptım,) birlikte tek bir dosya içine bütün bunlar koyarsanız reklamı olarak

#include <sys/time.h> 
#include <sys/resource.h> 

rlim_t get_rlimit_files() 
{ 
    struct rlimit rlim; 
    getrlimit(RLIMIT_NOFILE, &rlim); 
    return rlim.rlim_cur; 
} 

, çalıştığını doğrulamak için buna benzer bir çıktı üretebilir:

0:  0     O_RDWR dup() ok 
1:  0    O_WRONLY dup() ok 
2:  0     O_RDWR dup() ok 
3:  0    O_NONBLOCK dup() ok 
4:  0  O_WRONLY O_NONBLOCK dup() ok 
5: -1  Bad file descriptor Bad file descriptor 
6: -1  Bad file descriptor Bad file descriptor 
7: -1  Bad file descriptor Bad file descriptor 
8: -1  Bad file descriptor Bad file descriptor 
9: -1  Bad file descriptor Bad file descriptor 

Umarım, sahip olduğunuz sorulara cevap verirsiniz ve merak ettiğinizde, OP'nin sorduğu soruyu yanıtlamak için buraya geldim ve cevapları okuduktan sonra, kodu yıllar önce yazmış olduğumu hatırlıyorum. Keyfini çıkarın.

+0

pth_util_fd_valid dosyasının fd tablosundaki deliklerle çalışmayacağını unutmayın. Aşağıdaki durumu düşünün: 'int fd = open (...); // fd = 3' 'fd = açık (...); // fd = 4' 'close (4)' İşlev fd = 4'e ulaşmaz. – kfir

+0

Kfir - pth_util_fd_valid yalnızca belirli bir dosya tanıtıcısının geçerliliğini bildirir, bir döngü içermez. – Orwellophile

+0

İkinci kod örneği, FD_SETSIZE öğesini tanımlamak için sys/select.h dosyasını içermelidir. –

2

Bazen C++ bir seçenek olduğunu, boost kullanılarak Donal çözümü :: dosya sistemi:

#include <iostream> 
#include <string> 
#include <boost/filesystem.hpp> 
#include <unistd.h> 

namespace fs = boost::filesystem; 

int main() 
{ 
    std::string path = "/proc/" + std::to_string(::getpid()) + "/fd/"; 
    unsigned count = std::distance(fs::directory_iterator(path), 
            fs::directory_iterator()); 
    std::cout << "Number of opened FDs: " << count << std::endl; 
} 
+1

C programlarında C, C++ değil. Bu cevap alakasız. – fuz

İlgili konular