在iOS/iPhone上:"打开的文件过多":需要列出打开的文件(如lsof)

Tim*_*mes 17 c iphone ios

我们发现我们复杂的iPhone应用程序(ObjC,C++,JavaScript/WebKit)在异常情况下泄露了文件描述符.

我需要知道我们要打开哪些文件(通过文件路径).

我想要像BSD命令"lsof"这样的东西,当然,这在iOS 4中是不可用的,至少对我来说不行.理想情况下是C或ObjC功能.或者像鲨鱼或乐器这样的工具.只需要我们正在运行的应用程序的文件,而不是(与lsof一样)所有应用程序/进程.

我们用文件做各种各样的事情,并且"太多打开文件"失败的代码在很长时间内没有变化,并且由于情况不同寻常,这可能在几个月前就已经悄然发生.因此,没有必要提醒我查看打开文件的代码并确保关闭它们.我已经知道了.用一些lsof-esque来缩小范围会很好.谢谢.

Ric*_*ers 29

#import <sys/types.h>  
#import <fcntl.h>
#import <errno.h>
#import <sys/param.h>

+(void) lsof
{
    int flags;
    int fd;
    char buf[MAXPATHLEN+1] ;
    int n = 1 ;

    for (fd = 0; fd < (int) FD_SETSIZE; fd++) {
        errno = 0;
        flags = fcntl(fd, F_GETFD, 0);
        if (flags == -1 && errno) {
            if (errno != EBADF) {
                return ;
            }
            else
                continue;
        }
        fcntl(fd , F_GETPATH, buf ) ; 
        NSLog( @"File Descriptor %d number %d in use for: %s",fd,n , buf ) ;
        ++n ; 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 抱歉愚蠢的问题,但我应该在哪里放置这个片段,我如何将它用于我的应用程序? (3认同)
  • 该代码段结束了整整三天的调试unity3d错​​误的工作。非常感谢! (2认同)

Jai*_*tes 6

为了将来参考,我在装有 iOS 13 的 iPhone 11 上遇到了类似的问题;我通过创建太多文件和套接字来创建太多文件描述符 (FD)。我的解决方案是在运行时增加 FD setrlimit()

首先我得到了我的iPhone 11上的FD限制,代码如下:

// This goes somewhere in your code
struct rlimit rlim;

if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
    std::cout << "Soft limit: " << rlim.rlim_cur << std::endl;
    std::cout << "Hard limit: " << rlim.rlim_max << std::endl;
} else {
    std::cout << "Unable to get file descriptor limits" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

运行后getrlimit(),我可以确认,在iOS 13上,软限制是256个FD,硬限制是无限个FD。由于我在文件和套接字之间创建了超过 300 个 FD,因此我的应用程序崩溃了。

就我而言,我无法减少 FD 的数量,因此我决定增加 FD 软限制,代码如下:

// This goes somewhere in your code
struct rlimit rlim;

rlim.rlim_cur = NEW_SOFT_LIMIT;
rlim.rlim_max = NEW_HARD_LIMIT;

if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
    std::cout << "Unable to set file descriptor limits" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以在此处gettrlimit()此处找到更多信息。setrlimit()