2011-07-05 161 views

回答

22

由於您在Linux上,您(幾乎肯定)已安裝了/proc文件系統。這意味着最簡單的方法是獲取/proc/self/fd的內容列表;其中的每個文件都以FD命名。 (使用g_dir_openg_dir_read_nameg_dir_close做上市,當然)。

獲取信息,否則是適度尷尬(有例如,沒有幫助的POSIX API,這是不規範的區域)。

+3

要列出其他進程的列表,請列出「/ proc/PID/fd」目錄(其中PID是所討論進程的進程標識)。如果你不是root用戶,你將只能看到他們的一些進程。 –

+0

使用/ proc/*/pid當然是非常特定於linux的,並不是可移植的,但如果這不是問題,那麼它應該可以正常工作。 – TomH

+2

@Tom:使用'linux'標記問題... –

5

如果您可以通過PID你可以簡單地做

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

在C語言中,你可以管一切,重用輸出或您還可以計算自己在上述目錄中的文件(計數方法識別過程如這裏Counting the number of files in a directory using C

2

如果你的意思是如何從編程的過程中再去做正常的(如果稍有可怕的)方法是做這樣的事情遍歷所有可能的描述符(使用getrlimit()閱讀RLIMIT_NOFILE找到範圍)調用類似fcntl(fd, F_GETFD, 0)每一個和檢查EBADF反應,看看哪些沒有打開。

如果你的意思是你想從shell中找出進程已經打開的文件,那麼lsof -p <pid>就是你想要的。

+0

我看到相當數量的具有開放文件描述符0,1,2和255獲得252級失敗的系統調用不會進程很好...... –

+0

這一切都取決於 - 顯然你不想在一個性能關鍵的代碼塊中做它,但除此之外它不是一個大問題。無論如何,現代Linux系統的極限更可能是2048。 – TomH

+3

RLIMIT_NOFILE僅告訴您新創建的文件描述符的最大值,而不是當前打開的文件描述符的限制,因此您不能使用getrlimit來發現文件描述符編號的上限。 –

1

fstat命令列出系統的所有正在運行的進程及其打開的描述符,此外它列出了它是什麼類型的描述符(文件,套接字,管道等)並試圖提供描述符正在讀或寫的內容如什麼文件系統和該文件系統上的什麼inode號

22

這是我用過的一些代碼,我不知道/ proc/self(thx Donal!),但這種方式可能更通用。我已經包含了頂部所有功能的必需包含。

#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; 
} 

我經歷了非常不好的問題去與泄漏文件句柄一次,事實證明我實際編碼解決方案湯姆H.建議:

/* 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; 
} 

你可能會想,這些也是如此,滿足上述最後的printf ...

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通常爲1024,每個進程的最大文件通常是1024。如果你想確保,你可以用一個調用替換它這個功能,由TomH描述。

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

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

如果你把所有的一起到一個單一的文件(我所做的,只是爲了檢查它),你可以產生類似這樣的輸出,以確認它像宣傳的那樣:

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 

我希望能回答您的任何問題,如果您想知道,我實際上是來這裏尋找OP問題的答案,並且在閱讀答案後,請記住我多年前已經編寫了代碼。請享用。

+0

請注意,pth_util_fd_valid不適用於fd表中的孔。考慮以下情況: 'int fd = open(...); // fd = 3' 'fd = open(...); //fd = 4' 'close(4)' 函數不會達到fd = 4 – kfir

+0

@kfir - pth_util_fd_valid只報告給定文件句柄的有效性,它不包含循環。 – Orwellophile

+0

第二個代碼示例需要包含sys/select.h來定義FD_SETSIZE。 –

2

有時候C++是一種選擇,使用升壓多納爾的解決方案::文件系統:

#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程序中的OP程序,而不是C++。這個答案是無關緊要的。 – fuz